mfd: asic3: enable DS1WM cell

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

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Philipp Zabel
2009-06-15 12:10:24 +02:00
committed by Samuel Ortiz
parent 1b89040c3a
commit 9461f65a85
2 changed files with 100 additions and 0 deletions

View File

@@ -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)

View File

@@ -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;