Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9461f65a authored by Philipp Zabel's avatar Philipp Zabel Committed by Samuel Ortiz
Browse files

mfd: asic3: enable DS1WM cell



This enables the ASIC3's DS1WM MFD cell, supported by the ds1wm driver.

Signed-off-by: default avatarPhilipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 1b89040c
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ config MFD_SM501_GPIO
config MFD_ASIC3
config MFD_ASIC3
	bool "Support for Compaq ASIC3"
	bool "Support for Compaq ASIC3"
	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
	select MFD_CORE
	 ---help---
	 ---help---
	  This driver supports the ASIC3 multifunction chip found on many
	  This driver supports the ASIC3 multifunction chip found on many
	  PDAs (mainly iPAQ and HTC based ones)
	  PDAs (mainly iPAQ and HTC based ones)
+99 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
 */
 */


#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/io.h>
@@ -24,6 +25,8 @@
#include <linux/platform_device.h>
#include <linux/platform_device.h>


#include <linux/mfd/asic3.h>
#include <linux/mfd/asic3.h>
#include <linux/mfd/core.h>
#include <linux/mfd/ds1wm.h>


enum {
enum {
	ASIC3_CLOCK_SPI,
	ASIC3_CLOCK_SPI,
@@ -616,6 +619,98 @@ static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
	spin_unlock_irqrestore(&asic->lock, flags);
	spin_unlock_irqrestore(&asic->lock, flags);
}
}


/* MFD cells (SPI, PWM, LED, DS1WM, MMC) */
static struct ds1wm_driver_data ds1wm_pdata = {
	.active_high = 1,
};

static struct resource ds1wm_resources[] = {
	{
		.start = ASIC3_OWM_BASE,
		.end   = ASIC3_OWM_BASE + 0x13,
		.flags = IORESOURCE_MEM,
	},
	{
		.start = ASIC3_IRQ_OWM,
		.start = ASIC3_IRQ_OWM,
		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
	},
};

static int ds1wm_enable(struct platform_device *pdev)
{
	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);

	/* Turn on external clocks and the OWM clock */
	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
	msleep(1);

	/* Reset and enable DS1WM */
	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
			   ASIC3_EXTCF_OWM_RESET, 1);
	msleep(1);
	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
			   ASIC3_EXTCF_OWM_RESET, 0);
	msleep(1);
	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
			   ASIC3_EXTCF_OWM_EN, 1);
	msleep(1);

	return 0;
}

static int ds1wm_disable(struct platform_device *pdev)
{
	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);

	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
			   ASIC3_EXTCF_OWM_EN, 0);

	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);

	return 0;
}

static struct mfd_cell asic3_cell_ds1wm = {
	.name          = "ds1wm",
	.enable        = ds1wm_enable,
	.disable       = ds1wm_disable,
	.driver_data   = &ds1wm_pdata,
	.num_resources = ARRAY_SIZE(ds1wm_resources),
	.resources     = ds1wm_resources,
};

static int __init asic3_mfd_probe(struct platform_device *pdev,
				  struct resource *mem)
{
	struct asic3 *asic = platform_get_drvdata(pdev);
	int ret;

	/* DS1WM */
	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
			   ASIC3_EXTCF_OWM_SMB, 0);

	ds1wm_resources[0].start >>= asic->bus_shift;
	ds1wm_resources[0].end   >>= asic->bus_shift;

	asic3_cell_ds1wm.platform_data = &asic3_cell_ds1wm;
	asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);

	ret = mfd_add_devices(&pdev->dev, pdev->id,
			&asic3_cell_ds1wm, 1, mem, asic->irq_base);

	return ret;
}

static void asic3_mfd_remove(struct platform_device *pdev)
{
	mfd_remove_devices(&pdev->dev);
}

/* Core */
/* Core */
static int __init asic3_probe(struct platform_device *pdev)
static int __init asic3_probe(struct platform_device *pdev)
{
{
@@ -683,6 +778,8 @@ static int __init asic3_probe(struct platform_device *pdev)
	 */
	 */
	memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init));
	memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init));


	asic3_mfd_probe(pdev, mem);

	dev_info(asic->dev, "ASIC3 Core driver\n");
	dev_info(asic->dev, "ASIC3 Core driver\n");


	return 0;
	return 0;
@@ -704,6 +801,8 @@ static int asic3_remove(struct platform_device *pdev)
	int ret;
	int ret;
	struct asic3 *asic = platform_get_drvdata(pdev);
	struct asic3 *asic = platform_get_drvdata(pdev);


	asic3_mfd_remove(pdev);

	ret = asic3_gpio_remove(pdev);
	ret = asic3_gpio_remove(pdev);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;