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

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
...@@ -30,6 +30,7 @@ config MFD_SM501_GPIO ...@@ -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)
......
...@@ -17,6 +17,7 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment