diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 14:13:29 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 14:13:29 +1100 |
commit | b4a415df1bff5a73f87fde895459525110b248cf (patch) | |
tree | 3ad393d0542d49aceb8a8e35c77f083f7438818d /drivers | |
parent | a5fbf13d63d41c1428412e555fa15168f6f1ea0d (diff) | |
parent | b3df6513659704ece28da3b80cc36c2a8de315ce (diff) |
Merge remote branch 'mfd/for-next'
Conflicts:
drivers/mfd/asic3.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc6387xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/tmio_core.c
drivers/mmc/host/tmio_mmc.c
drivers/mmc/host/tmio_mmc.h
include/linux/mfd/tmio.h
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mfd/asic3.c | 9 | ||||
-rw-r--r-- | drivers/mfd/sm501.c | 7 | ||||
-rw-r--r-- | drivers/mfd/t7l66xb.c | 40 | ||||
-rw-r--r-- | drivers/mfd/tc6387xb.c | 36 | ||||
-rw-r--r-- | drivers/mfd/tc6393xb.c | 14 | ||||
-rw-r--r-- | drivers/mfd/tmio_core.c | 20 | ||||
-rw-r--r-- | drivers/mfd/wm8350-irq.c | 155 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc.h | 2 | ||||
-rw-r--r-- | drivers/power/wm8350_power.c | 24 | ||||
-rw-r--r-- | drivers/regulator/wm8350-regulator.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-wm8350.c | 11 |
13 files changed, 172 insertions, 160 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 87829789243e..1414cec7e46d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -205,7 +205,7 @@ config MFD_WM831X functionality of the device. config MFD_WM8350 - tristate + bool config MFD_WM8350_CONFIG_MODE_0 bool @@ -256,9 +256,9 @@ config MFD_WM8352_CONFIG_MODE_3 depends on MFD_WM8350 config MFD_WM8350_I2C - tristate "Support Wolfson Microelectronics WM8350 with I2C" + bool "Support Wolfson Microelectronics WM8350 with I2C" select MFD_WM8350 - depends on I2C + depends on I2C=y help The WM8350 is an integrated audio and power management subsystem with watchdog and RTC functionality for embedded diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index ff79b00d14f2..1dc6d05fb902 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -690,20 +690,20 @@ static void asic3_mmc_pwr(struct platform_device *pdev, int state) { struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); - tmio_core_mmc_pwr(asic->tmio_cnf, state); + tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state); } static void asic3_mmc_clk_div(struct platform_device *pdev, int state) { struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); - tmio_core_mmc_clk_div(asic->tmio_cnf, state); + tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state); } static struct tmio_mmc_data asic3_mmc_data = { .hclk = 24576000, .set_pwr = asic3_mmc_pwr, - .set_no_clk_div = asic3_mmc_clk_div, + .set_clk_div = asic3_mmc_clk_div, }; static struct resource asic3_mmc_resources[] = { @@ -756,7 +756,8 @@ static int asic3_mmc_enable(struct platform_device *pdev) ASIC3_SDHWCTRL_SDPWR, 1); /* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */ - tmio_core_mmc_enable(asic->tmio_cnf, ASIC3_SD_CTRL_BASE >> 1); + tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift, + ASIC3_SD_CTRL_BASE >> 1); return 0; } diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 0cc5eeff5ee8..dc9ea95c0561 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -1430,7 +1430,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev) } sm->regs_claim = request_mem_region(sm->io_res->start, - 0x100, "sm501"); + resource_size(sm->io_res), "sm501"); if (sm->regs_claim == NULL) { dev_err(&dev->dev, "cannot claim registers\n"); @@ -1440,8 +1440,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev) platform_set_drvdata(dev, sm); - sm->regs = ioremap(sm->io_res->start, - (sm->io_res->end - sm->io_res->start) - 1); + sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res)); if (sm->regs == NULL) { dev_err(&dev->dev, "cannot remap registers\n"); @@ -1645,7 +1644,7 @@ static int __devinit sm501_pci_probe(struct pci_dev *dev, sm->mem_res = &dev->resource[0]; sm->regs_claim = request_mem_region(sm->io_res->start, - 0x100, "sm501"); + resource_size(sm->io_res), "sm501"); if (sm->regs_claim == NULL) { dev_err(&dev->dev, "cannot claim registers\n"); err= -EBUSY; diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 2fa070361f05..26d9176fca91 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -38,7 +38,18 @@ enum { T7L66XB_CELL_MMC, }; -static const struct resource t7l66xb_mmc_resources[]; +static const struct resource t7l66xb_mmc_resources[] = { + { + .start = 0x800, + .end = 0x9ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_T7L66XB_MMC, + .end = IRQ_T7L66XB_MMC, + .flags = IORESOURCE_IRQ, + }, +}; #define SCR_REVID 0x08 /* b Revision ID */ #define SCR_IMR 0x42 /* b Interrupt Mask */ @@ -85,7 +96,7 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc) spin_unlock_irqrestore(&t7l66xb->lock, flags); - tmio_core_mmc_enable(t7l66xb->scr + 0x200, + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0, t7l66xb_mmc_resources[0].start & 0xfffe); return 0; @@ -116,7 +127,7 @@ static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct t7l66xb *t7l66xb = platform_get_drvdata(dev); - tmio_core_mmc_pwr(t7l66xb->scr + 0x200, state); + tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state); } static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) @@ -124,7 +135,7 @@ static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct t7l66xb *t7l66xb = platform_get_drvdata(dev); - tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, state); + tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state); } /*--------------------------------------------------------------------------*/ @@ -132,20 +143,7 @@ static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) static struct tmio_mmc_data t7166xb_mmc_data = { .hclk = 24000000, .set_pwr = t7l66xb_mmc_pwr, - .set_no_clk_div = t7l66xb_mmc_clk_div, -}; - -static const struct resource t7l66xb_mmc_resources[] = { - { - .start = 0x800, - .end = 0x9ff, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_T7L66XB_MMC, - .end = IRQ_T7L66XB_MMC, - .flags = IORESOURCE_IRQ, - }, + .set_clk_div = t7l66xb_mmc_clk_div, }; static const struct resource t7l66xb_nand_resources[] = { @@ -300,7 +298,7 @@ static int t7l66xb_resume(struct platform_device *dev) if (pdata && pdata->resume) pdata->resume(dev); - tmio_core_mmc_enable(t7l66xb->scr + 0x200, + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0, t7l66xb_mmc_resources[0].start & 0xfffe); return 0; @@ -362,7 +360,7 @@ static int t7l66xb_probe(struct platform_device *dev) if (ret) goto err_request_scr; - t7l66xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1); + t7l66xb->scr = ioremap(rscr->start, resource_size(rscr)); if (!t7l66xb->scr) { ret = -ENOMEM; goto err_ioremap; @@ -405,12 +403,12 @@ static int t7l66xb_probe(struct platform_device *dev) err_ioremap: release_resource(&t7l66xb->rscr); err_request_scr: - kfree(t7l66xb); clk_put(t7l66xb->clk48m); err_clk48m_get: clk_put(t7l66xb->clk32k); err_clk32k_get: err_noirq: + kfree(t7l66xb); return ret; } diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index fa8da0264a9f..5c7f04343d5c 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -28,7 +28,18 @@ struct tc6387xb { struct resource rscr; }; -static struct resource tc6387xb_mmc_resources[]; +static struct resource tc6387xb_mmc_resources[] = { + { + .start = 0x800, + .end = 0x9ff, + .flags = IORESOURCE_MEM, + }, + { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; /*--------------------------------------------------------------------------*/ @@ -54,7 +65,7 @@ static int tc6387xb_resume(struct platform_device *dev) if (pdata && pdata->resume) pdata->resume(dev); - tmio_core_mmc_resume(tc6387xb->scr + 0x200, + tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0, tc6387xb_mmc_resources[0].start & 0xfffe); return 0; @@ -71,7 +82,7 @@ static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - tmio_core_mmc_pwr(tc6387xb->scr + 0x200, state); + tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state); } static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) @@ -79,7 +90,7 @@ static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, state); + tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state); } @@ -90,7 +101,7 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc) clk_enable(tc6387xb->clk32k); - tmio_core_mmc_enable(tc6387xb->scr + 0x200, + tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0, tc6387xb_mmc_resources[0].start & 0xfffe); return 0; @@ -109,24 +120,11 @@ static int tc6387xb_mmc_disable(struct platform_device *mmc) static struct tmio_mmc_data tc6387xb_mmc_data = { .hclk = 24000000, .set_pwr = tc6387xb_mmc_pwr, - .set_no_clk_div = tc6387xb_mmc_clk_div, + .set_clk_div = tc6387xb_mmc_clk_div, }; /*--------------------------------------------------------------------------*/ -static struct resource tc6387xb_mmc_resources[] = { - { - .start = 0x800, - .end = 0x9ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .flags = IORESOURCE_IRQ, - }, -}; - static struct mfd_cell tc6387xb_cells[] = { [TC6387XB_CELL_MMC] = { .name = "tmio-mmc", diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 40bb375c605e..c59e5c5737d0 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -342,7 +342,7 @@ static int tc6393xb_mmc_enable(struct platform_device *mmc) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); - tmio_core_mmc_enable(tc6393xb->scr + 0x200, + tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0, tc6393xb_mmc_resources[0].start & 0xfffe); return 0; @@ -353,7 +353,7 @@ static int tc6393xb_mmc_resume(struct platform_device *mmc) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); - tmio_core_mmc_resume(tc6393xb->scr + 0x200, + tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0, tc6393xb_mmc_resources[0].start & 0xfffe); return 0; @@ -364,7 +364,7 @@ static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); - tmio_core_mmc_pwr(tc6393xb->scr + 0x200, state); + tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state); } static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state) @@ -372,13 +372,13 @@ static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state) struct platform_device *dev = to_platform_device(mmc->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); - tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, state); + tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state); } static struct tmio_mmc_data tc6393xb_mmc_data = { - .hclk = 33000000, + .hclk = 24000000, .set_pwr = tc6393xb_mmc_pwr, - .set_no_clk_div = tc6393xb_mmc_clk_div, + .set_clk_div = tc6393xb_mmc_clk_div, }; static struct mfd_cell __devinitdata tc6393xb_cells[] = { @@ -647,7 +647,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) if (ret) goto err_request_scr; - tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1); + tc6393xb->scr = ioremap(rscr->start, resource_size(rscr)); if (!tc6393xb->scr) { ret = -ENOMEM; goto err_ioremap; diff --git a/drivers/mfd/tmio_core.c b/drivers/mfd/tmio_core.c index f88b06393540..eddc19ae464b 100644 --- a/drivers/mfd/tmio_core.c +++ b/drivers/mfd/tmio_core.c @@ -1,6 +1,4 @@ /* - * Toshiba TC6393XB SoC support - * * Copyright(c) 2009 Ian Molton <spyro@f2s.com> * * This program is free software; you can redistribute it and/or modify @@ -10,9 +8,7 @@ #include <linux/mfd/tmio.h> -static int shift; - -int tmio_core_mmc_enable(void __iomem *cnf, unsigned long base) +int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base) { /* Enable the MMC/SD Control registers */ sd_config_write16(cnf, shift, CNF_CMD, SDCREN); @@ -24,14 +20,14 @@ int tmio_core_mmc_enable(void __iomem *cnf, unsigned long base) /* The below is required but why? FIXME */ sd_config_write8(cnf, shift, CNF_STOP_CLK_CTL, 0x1f); - /* Power down SD bus*/ + /* Power down SD bus */ sd_config_write8(cnf, shift, CNF_PWR_CTL_2, 0x00); return 0; } EXPORT_SYMBOL(tmio_core_mmc_enable); -int tmio_core_mmc_resume(void __iomem *cnf, unsigned long base) +int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base) { /* Enable the MMC/SD Control registers */ @@ -42,21 +38,15 @@ int tmio_core_mmc_resume(void __iomem *cnf, unsigned long base) } EXPORT_SYMBOL(tmio_core_mmc_resume); -void tmio_core_mmc_pwr(void __iomem *cnf, int state) +void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state) { sd_config_write8(cnf, shift, CNF_PWR_CTL_2, state ? 0x02 : 0x00); } EXPORT_SYMBOL(tmio_core_mmc_pwr); -void tmio_core_mmc_clk_div(void __iomem *cnf, int state) +void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state) { sd_config_write8(cnf, shift, CNF_SD_CLK_MODE, state ? 1 : 0); } EXPORT_SYMBOL(tmio_core_mmc_clk_div); -void tmio_core_set_bus_shift(int bus_shift) -{ - shift = bus_shift; -} -EXPORT_SYMBOL(tmio_core_set_bus_shift); - diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c index c8df547c4747..f56c9adf9493 100644 --- a/drivers/mfd/wm8350-irq.c +++ b/drivers/mfd/wm8350-irq.c @@ -18,7 +18,7 @@ #include <linux/bug.h> #include <linux/device.h> #include <linux/interrupt.h> -#include <linux/workqueue.h> +#include <linux/irq.h> #include <linux/mfd/wm8350/core.h> #include <linux/mfd/wm8350/audio.h> @@ -29,8 +29,6 @@ #include <linux/mfd/wm8350/supply.h> #include <linux/mfd/wm8350/wdt.h> -#define WM8350_NUM_IRQ_REGS 7 - #define WM8350_INT_OFFSET_1 0 #define WM8350_INT_OFFSET_2 1 #define WM8350_POWER_UP_INT_OFFSET 2 @@ -366,19 +364,10 @@ static struct wm8350_irq_data wm8350_irqs[] = { }, }; -static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) +static inline struct wm8350_irq_data *irq_to_wm8350_irq(struct wm8350 *wm8350, + int irq) { - mutex_lock(&wm8350->irq_mutex); - - if (wm8350->irq[irq].handler) - wm8350->irq[irq].handler(irq, wm8350->irq[irq].data); - else { - dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n", - irq); - wm8350_mask_irq(wm8350, irq); - } - - mutex_unlock(&wm8350->irq_mutex); + return &wm8350_irqs[irq - wm8350->irq_base]; } /* @@ -386,7 +375,9 @@ static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) * interrupts are clear on read the IRQ line will be reasserted and * the physical IRQ will be handled again if another interrupt is * asserted while we run - in the normal course of events this is a - * rare occurrence so we save I2C/SPI reads. + * rare occurrence so we save I2C/SPI reads. We're also assuming that + * it's rare to get lots of interrupts firing simultaneously so try to + * minimise I/O. */ static irqreturn_t wm8350_irq(int irq, void *irq_data) { @@ -397,7 +388,6 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data) struct wm8350_irq_data *data; int i; - /* TODO: Use block reads to improve performance? */ level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS) & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK); @@ -416,93 +406,101 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data) sub_reg[data->reg] = wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 + data->reg); - sub_reg[data->reg] &= - ~wm8350_reg_read(wm8350, - WM8350_INT_STATUS_1_MASK + - data->reg); + sub_reg[data->reg] &= ~wm8350->irq_masks[data->reg]; read_done[data->reg] = 1; } if (sub_reg[data->reg] & data->mask) - wm8350_irq_call_handler(wm8350, i); + handle_nested_irq(wm8350->irq_base + i); } return IRQ_HANDLED; } -int wm8350_register_irq(struct wm8350 *wm8350, int irq, - irq_handler_t handler, unsigned long flags, - const char *name, void *data) +static void wm8350_irq_lock(unsigned int irq) { - if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) - return -EINVAL; - - if (wm8350->irq[irq].handler) - return -EBUSY; - - mutex_lock(&wm8350->irq_mutex); - wm8350->irq[irq].handler = handler; - wm8350->irq[irq].data = data; - mutex_unlock(&wm8350->irq_mutex); - - wm8350_unmask_irq(wm8350, irq); + struct wm8350 *wm8350 = get_irq_chip_data(irq); - return 0; + mutex_lock(&wm8350->irq_lock); } -EXPORT_SYMBOL_GPL(wm8350_register_irq); -int wm8350_free_irq(struct wm8350 *wm8350, int irq) +static void wm8350_irq_sync_unlock(unsigned int irq) { - if (irq < 0 || irq > WM8350_NUM_IRQ) - return -EINVAL; + struct wm8350 *wm8350 = get_irq_chip_data(irq); + int i; - wm8350_mask_irq(wm8350, irq); + for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) { + /* If there's been a change in the mask write it back + * to the hardware. */ + if (wm8350->irq_masks[i] != + wm8350->reg_cache[WM8350_INT_STATUS_1_MASK + i]) + WARN_ON(wm8350_reg_write(wm8350, + WM8350_INT_STATUS_1_MASK + i, + wm8350->irq_masks[i])); + } - mutex_lock(&wm8350->irq_mutex); - wm8350->irq[irq].handler = NULL; - mutex_unlock(&wm8350->irq_mutex); - return 0; + mutex_unlock(&wm8350->irq_lock); } -EXPORT_SYMBOL_GPL(wm8350_free_irq); -int wm8350_mask_irq(struct wm8350 *wm8350, int irq) +static void wm8350_irq_enable(unsigned int irq) { - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK + - wm8350_irqs[irq].reg, - wm8350_irqs[irq].mask); + struct wm8350 *wm8350 = get_irq_chip_data(irq); + struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq); + + wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask; } -EXPORT_SYMBOL_GPL(wm8350_mask_irq); -int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) +static void wm8350_irq_disable(unsigned int irq) { - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK + - wm8350_irqs[irq].reg, - wm8350_irqs[irq].mask); + struct wm8350 *wm8350 = get_irq_chip_data(irq); + struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq); + + wm8350->irq_masks[irq_data->reg] |= irq_data->mask; } -EXPORT_SYMBOL_GPL(wm8350_unmask_irq); + +static struct irq_chip wm8350_irq_chip = { + .name = "wm8350", + .bus_lock = wm8350_irq_lock, + .bus_sync_unlock = wm8350_irq_sync_unlock, + .disable = wm8350_irq_disable, + .enable = wm8350_irq_enable, +}; int wm8350_irq_init(struct wm8350 *wm8350, int irq, struct wm8350_platform_data *pdata) { - int ret; + int ret, cur_irq, i; int flags = IRQF_ONESHOT; if (!irq) { - dev_err(wm8350->dev, "No IRQ configured\n"); - return -EINVAL; + dev_warn(wm8350->dev, "No interrupt support, no core IRQ\n"); + return 0; + } + + if (!pdata || !pdata->irq_base) { + dev_warn(wm8350->dev, "No interrupt support, no IRQ base\n"); + return 0; } + /* Mask top level interrupts */ wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF); - mutex_init(&wm8350->irq_mutex); + /* Mask all individual interrupts by default and cache the + * masks. We read the masks back since there are unwritable + * bits in the mask registers. */ + for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) { + wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK + i, + 0xFFFF); + wm8350->irq_masks[i] = + wm8350_reg_read(wm8350, + WM8350_INT_STATUS_1_MASK + i); + } + + mutex_init(&wm8350->irq_lock); wm8350->chip_irq = irq; + wm8350->irq_base = pdata->irq_base; - if (pdata && pdata->irq_high) { + if (pdata->irq_high) { flags |= IRQF_TRIGGER_HIGH; wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, @@ -514,11 +512,32 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq, WM8350_IRQ_POL); } + /* Register with genirq */ + for (cur_irq = wm8350->irq_base; + cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base; + cur_irq++) { + set_irq_chip_data(cur_irq, wm8350); + set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip, + handle_edge_irq); + set_irq_nested_thread(cur_irq, 1); + + /* ARM needs us to explicitly flag the IRQ as valid + * and will set them noprobe when we do so. */ +#ifdef CONFIG_ARM + set_irq_flags(cur_irq, IRQF_VALID); +#else + set_irq_noprobe(cur_irq); +#endif + } + ret = request_threaded_irq(irq, NULL, wm8350_irq, flags, "wm8350", wm8350); if (ret != 0) dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret); + /* Allow interrupts to fire */ + wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0); + return ret; } diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 329ef5dbe8dc..053fc65f7dbb 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -55,8 +55,8 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) clk |= 0x100; } - if (host->set_no_clk_div) - host->set_no_clk_div(host->pdev, (clk>>22) & 1); + if (host->set_clk_div) + host->set_clk_div(host->pdev, (clk>>22) & 1); sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff); } @@ -548,7 +548,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) platform_set_drvdata(dev, mmc); host->set_pwr = pdata->set_pwr; - host->set_no_clk_div = pdata->set_no_clk_div; + host->set_clk_div = pdata->set_clk_div; /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ host->bus_shift = resource_size(res_ctl) >> 10; diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index c676767cce8d..692dc23363b9 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -100,7 +100,7 @@ struct tmio_mmc_host { /* Callbacks for clock / power control */ void (*set_pwr)(struct platform_device *host, int state); - void (*set_no_clk_div)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); /* pio related stuff */ struct scatterlist *sg_ptr; diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c index ad4f071e1287..3839a5e1c4a7 100644 --- a/drivers/power/wm8350_power.c +++ b/drivers/power/wm8350_power.c @@ -428,18 +428,18 @@ static void wm8350_init_charger(struct wm8350 *wm8350) static void free_charger_irq(struct wm8350 *wm8350) { - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); - wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); - wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB); - wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); - wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350); } static __devinit int wm8350_power_probe(struct platform_device *pdev) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 1bbff099a546..0764a0b60658 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1407,7 +1407,7 @@ static int wm8350_regulator_remove(struct platform_device *pdev) struct regulator_dev *rdev = platform_get_drvdata(pdev); struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq); + wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev); regulator_unregister(rdev); diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index f1e440521c54..3d0dc76b38af 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -307,11 +307,18 @@ static int wm8350_rtc_update_irq_enable(struct device *dev, { struct wm8350 *wm8350 = dev_get_drvdata(dev); + /* Suppress duplicate changes since genirq nests enable and + * disable calls. */ + if (enabled == wm8350->rtc.update_enabled) + return 0; + if (enabled) wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); else wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); + wm8350->rtc.update_enabled = enabled; + return 0; } @@ -478,8 +485,8 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350_rtc *wm_rtc = &wm8350->rtc; - wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); - wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); + wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350); + wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350); rtc_device_unregister(wm_rtc->rtc); |