diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 16:56:35 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 16:56:35 -0400 |
| commit | 30304e5a79d424eb2c8707b3ff0e9b8bf6ab3e8f (patch) | |
| tree | 63968fb97b86861e31922515395feef8a110f884 | |
| parent | 750f77064a290beb162352077b52c61b04bcae0e (diff) | |
| parent | b8589e2a8065b8e7773742b60ae96b63b757bb69 (diff) | |
Merge tag 'mfd_3.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFD changes from Samuel Ortiz:
- 4 new drivers: Freescale i.MX on-chip Anatop, Ricoh's RC5T583 and
TI's TPS65090 and TPS65217.
- New variants support (8420, 8520 ab9540), cleanups and bug fixes for
the abx500 and db8500 ST-E chipsets.
- Some minor fixes and update for the wm8994 from Mark.
- The beginning of a long term TWL cleanup effort coming from the TI
folks.
- Various fixes and cleanups for the s5m, TPS659xx, pm860x, and MAX8997
drivers.
Fix up trivial conflicts due to duplicate patches and header file
cleanups (<linux/device.h> removal etc).
* tag 'mfd_3.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (97 commits)
gpio/twl: Add DT support to gpio-twl4030 driver
gpio/twl: Allocate irq_desc dynamically for SPARSE_IRQ support
mfd: Detach twl6040 from the pmic mfd driver
mfd: Replace twl-* pr_ macros by the dev_ equivalent and do various cleanups
mfd: Micro-optimization on twl4030 IRQ handler
mfd: Make twl4030 SIH SPARSE_IRQ capable
mfd: Move twl-core IRQ allocation into twl[4030|6030]-irq files
mfd: Remove references already defineid in header file from twl-core
mfd: Remove unneeded header from twl-core
mfd: Make twl-core not depend on pdata->irq_base/end
ARM: OMAP2+: board-omap4-*: Do not use anymore TWL6030_IRQ_BASE in board files
mfd: Return twl6030_mmc_card_detect IRQ for board setup
Revert "mfd: Add platform data for MAX8997 haptic driver"
mfd: Add support for TPS65090
mfd: Add some da9052-i2c section annotations
mfd: Build rtc5t583 only if I2C config is selected to y.
mfd: Add anatop mfd driver
mfd: Fix compilation error in tps65910.h
mfd: Add 8420 variant to db8500-prcmu
mfd: Add 8520 PRCMU variant to db8500-prcmu
...
69 files changed, 5211 insertions, 1126 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt b/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt new file mode 100644 index 000000000000..16695d9cf1e8 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | twl4030 GPIO controller bindings | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: | ||
| 5 | - "ti,twl4030-gpio" for twl4030 GPIO controller | ||
| 6 | - #gpio-cells : Should be two. | ||
| 7 | - first cell is the pin number | ||
| 8 | - second cell is used to specify optional parameters (unused) | ||
| 9 | - gpio-controller : Marks the device node as a GPIO controller. | ||
| 10 | - #interrupt-cells : Should be 2. | ||
| 11 | - interrupt-controller: Mark the device node as an interrupt controller | ||
| 12 | The first cell is the GPIO number. | ||
| 13 | The second cell is not used. | ||
| 14 | |||
| 15 | Example: | ||
| 16 | |||
| 17 | twl_gpio: gpio { | ||
| 18 | compatible = "ti,twl4030-gpio"; | ||
| 19 | #gpio-cells = <2>; | ||
| 20 | gpio-controller; | ||
| 21 | #interrupt-cells = <2>; | ||
| 22 | interrupt-controller; | ||
| 23 | }; | ||
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 30768c2f53fd..37dcb1bc025e 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c | |||
| @@ -490,21 +490,22 @@ static struct platform_device omap_vwlan_device = { | |||
| 490 | 490 | ||
| 491 | static int omap4_twl6030_hsmmc_late_init(struct device *dev) | 491 | static int omap4_twl6030_hsmmc_late_init(struct device *dev) |
| 492 | { | 492 | { |
| 493 | int ret = 0; | 493 | int irq = 0; |
| 494 | struct platform_device *pdev = container_of(dev, | 494 | struct platform_device *pdev = container_of(dev, |
| 495 | struct platform_device, dev); | 495 | struct platform_device, dev); |
| 496 | struct omap_mmc_platform_data *pdata = dev->platform_data; | 496 | struct omap_mmc_platform_data *pdata = dev->platform_data; |
| 497 | 497 | ||
| 498 | /* Setting MMC1 Card detect Irq */ | 498 | /* Setting MMC1 Card detect Irq */ |
| 499 | if (pdev->id == 0) { | 499 | if (pdev->id == 0) { |
| 500 | ret = twl6030_mmc_card_detect_config(); | 500 | irq = twl6030_mmc_card_detect_config(); |
| 501 | if (ret) | 501 | if (irq < 0) { |
| 502 | pr_err("Failed configuring MMC1 card detect\n"); | 502 | pr_err("Failed configuring MMC1 card detect\n"); |
| 503 | pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE + | 503 | return irq; |
| 504 | MMCDETECT_INTR_OFFSET; | 504 | } |
| 505 | pdata->slots[0].card_detect_irq = irq; | ||
| 505 | pdata->slots[0].card_detect = twl6030_mmc_card_detect; | 506 | pdata->slots[0].card_detect = twl6030_mmc_card_detect; |
| 506 | } | 507 | } |
| 507 | return ret; | 508 | return 0; |
| 508 | } | 509 | } |
| 509 | 510 | ||
| 510 | static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev) | 511 | static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev) |
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index e9071a57c37b..8bf8e99c358e 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c | |||
| @@ -238,7 +238,7 @@ struct wl12xx_platform_data omap_panda_wlan_data __initdata = { | |||
| 238 | 238 | ||
| 239 | static int omap4_twl6030_hsmmc_late_init(struct device *dev) | 239 | static int omap4_twl6030_hsmmc_late_init(struct device *dev) |
| 240 | { | 240 | { |
| 241 | int ret = 0; | 241 | int irq = 0; |
| 242 | struct platform_device *pdev = container_of(dev, | 242 | struct platform_device *pdev = container_of(dev, |
| 243 | struct platform_device, dev); | 243 | struct platform_device, dev); |
| 244 | struct omap_mmc_platform_data *pdata = dev->platform_data; | 244 | struct omap_mmc_platform_data *pdata = dev->platform_data; |
| @@ -249,14 +249,15 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev) | |||
| 249 | } | 249 | } |
| 250 | /* Setting MMC1 Card detect Irq */ | 250 | /* Setting MMC1 Card detect Irq */ |
| 251 | if (pdev->id == 0) { | 251 | if (pdev->id == 0) { |
| 252 | ret = twl6030_mmc_card_detect_config(); | 252 | irq = twl6030_mmc_card_detect_config(); |
| 253 | if (ret) | 253 | if (irq < 0) { |
| 254 | dev_err(dev, "%s: Error card detect config(%d)\n", | 254 | dev_err(dev, "%s: Error card detect config(%d)\n", |
| 255 | __func__, ret); | 255 | __func__, irq); |
| 256 | else | 256 | return irq; |
| 257 | pdata->slots[0].card_detect = twl6030_mmc_card_detect; | 257 | } |
| 258 | pdata->slots[0].card_detect = twl6030_mmc_card_detect; | ||
| 258 | } | 259 | } |
| 259 | return ret; | 260 | return 0; |
| 260 | } | 261 | } |
| 261 | 262 | ||
| 262 | static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev) | 263 | static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev) |
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index b6a67728cc88..0ace108c3e3d 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #include <linux/mfd/wm831x/gpio.h> | 17 | #include <linux/mfd/wm831x/gpio.h> |
| 18 | #include <linux/mfd/wm8994/pdata.h> | 18 | #include <linux/mfd/wm8994/pdata.h> |
| 19 | 19 | ||
| 20 | #include <linux/regulator/machine.h> | ||
| 21 | |||
| 20 | #include <sound/wm5100.h> | 22 | #include <sound/wm5100.h> |
| 21 | #include <sound/wm8996.h> | 23 | #include <sound/wm8996.h> |
| 22 | #include <sound/wm8962.h> | 24 | #include <sound/wm8962.h> |
| @@ -153,6 +155,14 @@ static const struct i2c_board_info wm1259_devs[] = { | |||
| 153 | }, | 155 | }, |
| 154 | }; | 156 | }; |
| 155 | 157 | ||
| 158 | static struct regulator_init_data wm8994_ldo1 = { | ||
| 159 | .supply_regulator = "WALLVDD", | ||
| 160 | }; | ||
| 161 | |||
| 162 | static struct regulator_init_data wm8994_ldo2 = { | ||
| 163 | .supply_regulator = "WALLVDD", | ||
| 164 | }; | ||
| 165 | |||
| 156 | static struct wm8994_pdata wm8994_pdata = { | 166 | static struct wm8994_pdata wm8994_pdata = { |
| 157 | .gpio_base = CODEC_GPIO_BASE, | 167 | .gpio_base = CODEC_GPIO_BASE, |
| 158 | .gpio_defaults = { | 168 | .gpio_defaults = { |
| @@ -160,8 +170,8 @@ static struct wm8994_pdata wm8994_pdata = { | |||
| 160 | }, | 170 | }, |
| 161 | .irq_base = CODEC_IRQ_BASE, | 171 | .irq_base = CODEC_IRQ_BASE, |
| 162 | .ldo = { | 172 | .ldo = { |
| 163 | { .supply = "WALLVDD" }, | 173 | { .init_data = &wm8994_ldo1, }, |
| 164 | { .supply = "WALLVDD" }, | 174 | { .init_data = &wm8994_ldo2, }, |
| 165 | }, | 175 | }, |
| 166 | }; | 176 | }; |
| 167 | 177 | ||
diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index d2d4131435a6..7d34c52798b5 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START | 14 | #define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START |
| 15 | #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ | 15 | #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ |
| 16 | + AB8500_NR_IRQS) | 16 | + AB8500_MAX_NR_IRQS) |
| 17 | 17 | ||
| 18 | /* TC35892 */ | 18 | /* TC35892 */ |
| 19 | #define TC35892_NR_INTERNAL_IRQS 8 | 19 | #define TC35892_NR_INTERNAL_IRQS 8 |
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index f5002015d82e..a22ffa5bff9f 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c | |||
| @@ -22,11 +22,11 @@ static struct cpufreq_frequency_table freq_table[] = { | |||
| 22 | }, | 22 | }, |
| 23 | [1] = { | 23 | [1] = { |
| 24 | .index = 1, | 24 | .index = 1, |
| 25 | .frequency = 300000, | 25 | .frequency = 400000, |
| 26 | }, | 26 | }, |
| 27 | [2] = { | 27 | [2] = { |
| 28 | .index = 2, | 28 | .index = 2, |
| 29 | .frequency = 600000, | 29 | .frequency = 800000, |
| 30 | }, | 30 | }, |
| 31 | [3] = { | 31 | [3] = { |
| 32 | /* Used for MAX_OPP, if available */ | 32 | /* Used for MAX_OPP, if available */ |
| @@ -113,12 +113,9 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) | |||
| 113 | 113 | ||
| 114 | BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); | 114 | BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); |
| 115 | 115 | ||
| 116 | if (!prcmu_is_u8400()) { | 116 | if (prcmu_has_arm_maxopp()) |
| 117 | freq_table[1].frequency = 400000; | 117 | freq_table[3].frequency = 1000000; |
| 118 | freq_table[2].frequency = 800000; | 118 | |
| 119 | if (prcmu_has_arm_maxopp()) | ||
| 120 | freq_table[3].frequency = 1000000; | ||
| 121 | } | ||
| 122 | pr_info("db8500-cpufreq : Available frequencies:\n"); | 119 | pr_info("db8500-cpufreq : Available frequencies:\n"); |
| 123 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) | 120 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) |
| 124 | pr_info(" %d Mhz\n", freq_table[i].frequency/1000); | 121 | pr_info(" %d Mhz\n", freq_table[i].frequency/1000); |
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 87a68a896abf..094c5c4fd7f2 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c | |||
| @@ -307,13 +307,11 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
| 307 | struct stmpe_gpio_platform_data *pdata; | 307 | struct stmpe_gpio_platform_data *pdata; |
| 308 | struct stmpe_gpio *stmpe_gpio; | 308 | struct stmpe_gpio *stmpe_gpio; |
| 309 | int ret; | 309 | int ret; |
| 310 | int irq; | 310 | int irq = 0; |
| 311 | 311 | ||
| 312 | pdata = stmpe->pdata->gpio; | 312 | pdata = stmpe->pdata->gpio; |
| 313 | 313 | ||
| 314 | irq = platform_get_irq(pdev, 0); | 314 | irq = platform_get_irq(pdev, 0); |
| 315 | if (irq < 0) | ||
| 316 | return irq; | ||
| 317 | 315 | ||
| 318 | stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); | 316 | stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); |
| 319 | if (!stmpe_gpio) | 317 | if (!stmpe_gpio) |
| @@ -330,21 +328,28 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
| 330 | stmpe_gpio->chip.dev = &pdev->dev; | 328 | stmpe_gpio->chip.dev = &pdev->dev; |
| 331 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; | 329 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; |
| 332 | 330 | ||
| 333 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | 331 | if (irq >= 0) |
| 332 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | ||
| 333 | else | ||
| 334 | dev_info(&pdev->dev, | ||
| 335 | "device configured in no-irq mode; " | ||
| 336 | "irqs are not available\n"); | ||
| 334 | 337 | ||
| 335 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | 338 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); |
| 336 | if (ret) | 339 | if (ret) |
| 337 | goto out_free; | 340 | goto out_free; |
| 338 | 341 | ||
| 339 | ret = stmpe_gpio_irq_init(stmpe_gpio); | 342 | if (irq >= 0) { |
| 340 | if (ret) | 343 | ret = stmpe_gpio_irq_init(stmpe_gpio); |
| 341 | goto out_disable; | 344 | if (ret) |
| 345 | goto out_disable; | ||
| 342 | 346 | ||
| 343 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, | 347 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, |
| 344 | "stmpe-gpio", stmpe_gpio); | 348 | IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio); |
| 345 | if (ret) { | 349 | if (ret) { |
| 346 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | 350 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); |
| 347 | goto out_removeirq; | 351 | goto out_removeirq; |
| 352 | } | ||
| 348 | } | 353 | } |
| 349 | 354 | ||
| 350 | ret = gpiochip_add(&stmpe_gpio->chip); | 355 | ret = gpiochip_add(&stmpe_gpio->chip); |
| @@ -361,9 +366,11 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
| 361 | return 0; | 366 | return 0; |
| 362 | 367 | ||
| 363 | out_freeirq: | 368 | out_freeirq: |
| 364 | free_irq(irq, stmpe_gpio); | 369 | if (irq >= 0) |
| 370 | free_irq(irq, stmpe_gpio); | ||
| 365 | out_removeirq: | 371 | out_removeirq: |
| 366 | stmpe_gpio_irq_remove(stmpe_gpio); | 372 | if (irq >= 0) |
| 373 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
| 367 | out_disable: | 374 | out_disable: |
| 368 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | 375 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); |
| 369 | out_free: | 376 | out_free: |
| @@ -391,8 +398,10 @@ static int __devexit stmpe_gpio_remove(struct platform_device *pdev) | |||
| 391 | 398 | ||
| 392 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | 399 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); |
| 393 | 400 | ||
| 394 | free_irq(irq, stmpe_gpio); | 401 | if (irq >= 0) { |
| 395 | stmpe_gpio_irq_remove(stmpe_gpio); | 402 | free_irq(irq, stmpe_gpio); |
| 403 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
| 404 | } | ||
| 396 | platform_set_drvdata(pdev, NULL); | 405 | platform_set_drvdata(pdev, NULL); |
| 397 | kfree(stmpe_gpio); | 406 | kfree(stmpe_gpio); |
| 398 | 407 | ||
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index b8b4f228757c..94256fe7bf36 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | #include <linux/irq.h> | 32 | #include <linux/irq.h> |
| 33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
| 34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 35 | #include <linux/of.h> | ||
| 36 | #include <linux/irqdomain.h> | ||
| 35 | 37 | ||
| 36 | #include <linux/i2c/twl.h> | 38 | #include <linux/i2c/twl.h> |
| 37 | 39 | ||
| @@ -256,7 +258,8 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) | |||
| 256 | * and vMMC2 power supplies based on card presence. | 258 | * and vMMC2 power supplies based on card presence. |
| 257 | */ | 259 | */ |
| 258 | pdata = chip->dev->platform_data; | 260 | pdata = chip->dev->platform_data; |
| 259 | value |= pdata->mmc_cd & 0x03; | 261 | if (pdata) |
| 262 | value |= pdata->mmc_cd & 0x03; | ||
| 260 | 263 | ||
| 261 | status = gpio_twl4030_write(REG_GPIO_CTRL, value); | 264 | status = gpio_twl4030_write(REG_GPIO_CTRL, value); |
| 262 | } | 265 | } |
| @@ -395,59 +398,70 @@ static int gpio_twl4030_remove(struct platform_device *pdev); | |||
| 395 | static int __devinit gpio_twl4030_probe(struct platform_device *pdev) | 398 | static int __devinit gpio_twl4030_probe(struct platform_device *pdev) |
| 396 | { | 399 | { |
| 397 | struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; | 400 | struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; |
| 398 | int ret; | 401 | struct device_node *node = pdev->dev.of_node; |
| 402 | int ret, irq_base; | ||
| 399 | 403 | ||
| 400 | /* maybe setup IRQs */ | 404 | /* maybe setup IRQs */ |
| 401 | if (pdata->irq_base) { | 405 | if (is_module()) { |
| 402 | if (is_module()) { | 406 | dev_err(&pdev->dev, "can't dispatch IRQs from modules\n"); |
| 403 | dev_err(&pdev->dev, | 407 | goto no_irqs; |
| 404 | "can't dispatch IRQs from modules\n"); | 408 | } |
| 405 | goto no_irqs; | 409 | |
| 406 | } | 410 | irq_base = irq_alloc_descs(-1, 0, TWL4030_GPIO_MAX, 0); |
| 407 | ret = twl4030_sih_setup(TWL4030_MODULE_GPIO); | 411 | if (irq_base < 0) { |
| 408 | if (ret < 0) | 412 | dev_err(&pdev->dev, "Failed to alloc irq_descs\n"); |
| 409 | return ret; | 413 | return irq_base; |
| 410 | WARN_ON(ret != pdata->irq_base); | ||
| 411 | twl4030_gpio_irq_base = ret; | ||
| 412 | } | 414 | } |
| 413 | 415 | ||
| 416 | irq_domain_add_legacy(node, TWL4030_GPIO_MAX, irq_base, 0, | ||
| 417 | &irq_domain_simple_ops, NULL); | ||
| 418 | |||
| 419 | ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base); | ||
| 420 | if (ret < 0) | ||
| 421 | return ret; | ||
| 422 | |||
| 423 | twl4030_gpio_irq_base = irq_base; | ||
| 424 | |||
| 414 | no_irqs: | 425 | no_irqs: |
| 415 | /* | 426 | twl_gpiochip.base = -1; |
| 416 | * NOTE: boards may waste power if they don't set pullups | ||
| 417 | * and pulldowns correctly ... default for non-ULPI pins is | ||
| 418 | * pulldown, and some other pins may have external pullups | ||
| 419 | * or pulldowns. Careful! | ||
| 420 | */ | ||
| 421 | ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns); | ||
| 422 | if (ret) | ||
| 423 | dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n", | ||
| 424 | pdata->pullups, pdata->pulldowns, | ||
| 425 | ret); | ||
| 426 | |||
| 427 | ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd); | ||
| 428 | if (ret) | ||
| 429 | dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n", | ||
| 430 | pdata->debounce, pdata->mmc_cd, | ||
| 431 | ret); | ||
| 432 | |||
| 433 | twl_gpiochip.base = pdata->gpio_base; | ||
| 434 | twl_gpiochip.ngpio = TWL4030_GPIO_MAX; | 427 | twl_gpiochip.ngpio = TWL4030_GPIO_MAX; |
| 435 | twl_gpiochip.dev = &pdev->dev; | 428 | twl_gpiochip.dev = &pdev->dev; |
| 436 | 429 | ||
| 437 | /* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE, | 430 | if (pdata) { |
| 438 | * is (still) clear if use_leds is set. | 431 | twl_gpiochip.base = pdata->gpio_base; |
| 439 | */ | 432 | |
| 440 | if (pdata->use_leds) | 433 | /* |
| 441 | twl_gpiochip.ngpio += 2; | 434 | * NOTE: boards may waste power if they don't set pullups |
| 435 | * and pulldowns correctly ... default for non-ULPI pins is | ||
| 436 | * pulldown, and some other pins may have external pullups | ||
| 437 | * or pulldowns. Careful! | ||
| 438 | */ | ||
| 439 | ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns); | ||
| 440 | if (ret) | ||
| 441 | dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n", | ||
| 442 | pdata->pullups, pdata->pulldowns, | ||
| 443 | ret); | ||
| 444 | |||
| 445 | ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd); | ||
| 446 | if (ret) | ||
| 447 | dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n", | ||
| 448 | pdata->debounce, pdata->mmc_cd, | ||
| 449 | ret); | ||
| 450 | |||
| 451 | /* | ||
| 452 | * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE, | ||
| 453 | * is (still) clear if use_leds is set. | ||
| 454 | */ | ||
| 455 | if (pdata->use_leds) | ||
| 456 | twl_gpiochip.ngpio += 2; | ||
| 457 | } | ||
| 442 | 458 | ||
| 443 | ret = gpiochip_add(&twl_gpiochip); | 459 | ret = gpiochip_add(&twl_gpiochip); |
| 444 | if (ret < 0) { | 460 | if (ret < 0) { |
| 445 | dev_err(&pdev->dev, | 461 | dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); |
| 446 | "could not register gpiochip, %d\n", | ||
| 447 | ret); | ||
| 448 | twl_gpiochip.ngpio = 0; | 462 | twl_gpiochip.ngpio = 0; |
| 449 | gpio_twl4030_remove(pdev); | 463 | gpio_twl4030_remove(pdev); |
| 450 | } else if (pdata->setup) { | 464 | } else if (pdata && pdata->setup) { |
| 451 | int status; | 465 | int status; |
| 452 | 466 | ||
| 453 | status = pdata->setup(&pdev->dev, | 467 | status = pdata->setup(&pdev->dev, |
| @@ -465,7 +479,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev) | |||
| 465 | struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; | 479 | struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; |
| 466 | int status; | 480 | int status; |
| 467 | 481 | ||
| 468 | if (pdata->teardown) { | 482 | if (pdata && pdata->teardown) { |
| 469 | status = pdata->teardown(&pdev->dev, | 483 | status = pdata->teardown(&pdev->dev, |
| 470 | pdata->gpio_base, TWL4030_GPIO_MAX); | 484 | pdata->gpio_base, TWL4030_GPIO_MAX); |
| 471 | if (status) { | 485 | if (status) { |
| @@ -486,12 +500,21 @@ static int gpio_twl4030_remove(struct platform_device *pdev) | |||
| 486 | return -EIO; | 500 | return -EIO; |
| 487 | } | 501 | } |
| 488 | 502 | ||
| 503 | static const struct of_device_id twl_gpio_match[] = { | ||
| 504 | { .compatible = "ti,twl4030-gpio", }, | ||
| 505 | { }, | ||
| 506 | }; | ||
| 507 | MODULE_DEVICE_TABLE(of, twl_gpio_match); | ||
| 508 | |||
| 489 | /* Note: this hardware lives inside an I2C-based multi-function device. */ | 509 | /* Note: this hardware lives inside an I2C-based multi-function device. */ |
| 490 | MODULE_ALIAS("platform:twl4030_gpio"); | 510 | MODULE_ALIAS("platform:twl4030_gpio"); |
| 491 | 511 | ||
| 492 | static struct platform_driver gpio_twl4030_driver = { | 512 | static struct platform_driver gpio_twl4030_driver = { |
| 493 | .driver.name = "twl4030_gpio", | 513 | .driver = { |
| 494 | .driver.owner = THIS_MODULE, | 514 | .name = "twl4030_gpio", |
| 515 | .owner = THIS_MODULE, | ||
| 516 | .of_match_table = of_match_ptr(twl_gpio_match), | ||
| 517 | }, | ||
| 495 | .probe = gpio_twl4030_probe, | 518 | .probe = gpio_twl4030_probe, |
| 496 | .remove = gpio_twl4030_remove, | 519 | .remove = gpio_twl4030_remove, |
| 497 | }; | 520 | }; |
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c index 6c6b240a782e..ce86c5e3c2c2 100644 --- a/drivers/hwmon/mc13783-adc.c +++ b/drivers/hwmon/mc13783-adc.c | |||
| @@ -59,7 +59,7 @@ static int mc13783_adc_read(struct device *dev, | |||
| 59 | 59 | ||
| 60 | ret = mc13xxx_adc_do_conversion(priv->mc13xxx, | 60 | ret = mc13xxx_adc_do_conversion(priv->mc13xxx, |
| 61 | MC13XXX_ADC_MODE_MULT_CHAN, | 61 | MC13XXX_ADC_MODE_MULT_CHAN, |
| 62 | channel, sample); | 62 | channel, 0, 0, sample); |
| 63 | if (ret) | 63 | if (ret) |
| 64 | return ret; | 64 | return ret; |
| 65 | 65 | ||
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c index f2e0cbc5ab64..f9ce1835e4d7 100644 --- a/drivers/input/misc/88pm860x_onkey.c +++ b/drivers/input/misc/88pm860x_onkey.c | |||
| @@ -105,6 +105,8 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev) | |||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | platform_set_drvdata(pdev, info); | 107 | platform_set_drvdata(pdev, info); |
| 108 | device_init_wakeup(&pdev->dev, 1); | ||
| 109 | |||
| 108 | return 0; | 110 | return 0; |
| 109 | 111 | ||
| 110 | out_irq: | 112 | out_irq: |
| @@ -129,10 +131,34 @@ static int __devexit pm860x_onkey_remove(struct platform_device *pdev) | |||
| 129 | return 0; | 131 | return 0; |
| 130 | } | 132 | } |
| 131 | 133 | ||
| 134 | #ifdef CONFIG_PM_SLEEP | ||
| 135 | static int pm860x_onkey_suspend(struct device *dev) | ||
| 136 | { | ||
| 137 | struct platform_device *pdev = to_platform_device(dev); | ||
| 138 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 139 | |||
| 140 | if (device_may_wakeup(dev)) | ||
| 141 | chip->wakeup_flag |= 1 << PM8607_IRQ_ONKEY; | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | static int pm860x_onkey_resume(struct device *dev) | ||
| 145 | { | ||
| 146 | struct platform_device *pdev = to_platform_device(dev); | ||
| 147 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 148 | |||
| 149 | if (device_may_wakeup(dev)) | ||
| 150 | chip->wakeup_flag &= ~(1 << PM8607_IRQ_ONKEY); | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | #endif | ||
| 154 | |||
| 155 | static SIMPLE_DEV_PM_OPS(pm860x_onkey_pm_ops, pm860x_onkey_suspend, pm860x_onkey_resume); | ||
| 156 | |||
| 132 | static struct platform_driver pm860x_onkey_driver = { | 157 | static struct platform_driver pm860x_onkey_driver = { |
| 133 | .driver = { | 158 | .driver = { |
| 134 | .name = "88pm860x-onkey", | 159 | .name = "88pm860x-onkey", |
| 135 | .owner = THIS_MODULE, | 160 | .owner = THIS_MODULE, |
| 161 | .pm = &pm860x_onkey_pm_ops, | ||
| 136 | }, | 162 | }, |
| 137 | .probe = pm860x_onkey_probe, | 163 | .probe = pm860x_onkey_probe, |
| 138 | .remove = __devexit_p(pm860x_onkey_remove), | 164 | .remove = __devexit_p(pm860x_onkey_remove), |
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index ede02743eac1..48dc5b0d26f1 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c | |||
| @@ -39,6 +39,7 @@ struct mc13783_ts_priv { | |||
| 39 | struct delayed_work work; | 39 | struct delayed_work work; |
| 40 | struct workqueue_struct *workq; | 40 | struct workqueue_struct *workq; |
| 41 | unsigned int sample[4]; | 41 | unsigned int sample[4]; |
| 42 | struct mc13xxx_ts_platform_data *touch; | ||
| 42 | }; | 43 | }; |
| 43 | 44 | ||
| 44 | static irqreturn_t mc13783_ts_handler(int irq, void *data) | 45 | static irqreturn_t mc13783_ts_handler(int irq, void *data) |
| @@ -125,7 +126,9 @@ static void mc13783_ts_work(struct work_struct *work) | |||
| 125 | unsigned int channel = 12; | 126 | unsigned int channel = 12; |
| 126 | 127 | ||
| 127 | if (mc13xxx_adc_do_conversion(priv->mc13xxx, | 128 | if (mc13xxx_adc_do_conversion(priv->mc13xxx, |
| 128 | mode, channel, priv->sample) == 0) | 129 | mode, channel, |
| 130 | priv->touch->ato, priv->touch->atox, | ||
| 131 | priv->sample) == 0) | ||
| 129 | mc13783_ts_report_sample(priv); | 132 | mc13783_ts_report_sample(priv); |
| 130 | } | 133 | } |
| 131 | 134 | ||
| @@ -179,6 +182,12 @@ static int __init mc13783_ts_probe(struct platform_device *pdev) | |||
| 179 | INIT_DELAYED_WORK(&priv->work, mc13783_ts_work); | 182 | INIT_DELAYED_WORK(&priv->work, mc13783_ts_work); |
| 180 | priv->mc13xxx = dev_get_drvdata(pdev->dev.parent); | 183 | priv->mc13xxx = dev_get_drvdata(pdev->dev.parent); |
| 181 | priv->idev = idev; | 184 | priv->idev = idev; |
| 185 | priv->touch = dev_get_platdata(&pdev->dev); | ||
| 186 | if (!priv->touch) { | ||
| 187 | dev_err(&pdev->dev, "missing platform data\n"); | ||
| 188 | ret = -ENODEV; | ||
| 189 | goto err_free_mem; | ||
| 190 | } | ||
| 182 | 191 | ||
| 183 | /* | 192 | /* |
| 184 | * We need separate workqueue because mc13783_adc_do_conversion | 193 | * We need separate workqueue because mc13783_adc_do_conversion |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 4ca00624bd18..5b61aaf7ac0f 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
| @@ -114,6 +114,27 @@ static inline int __blink_ctl_mask(int port) | |||
| 114 | return ret; | 114 | return ret; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static int led_power_set(struct pm860x_chip *chip, int port, int on) | ||
| 118 | { | ||
| 119 | int ret = -EINVAL; | ||
| 120 | |||
| 121 | switch (port) { | ||
| 122 | case PM8606_LED1_RED: | ||
| 123 | case PM8606_LED1_GREEN: | ||
| 124 | case PM8606_LED1_BLUE: | ||
| 125 | ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) : | ||
| 126 | pm8606_osc_disable(chip, RGB1_ENABLE); | ||
| 127 | break; | ||
| 128 | case PM8606_LED2_RED: | ||
| 129 | case PM8606_LED2_GREEN: | ||
| 130 | case PM8606_LED2_BLUE: | ||
| 131 | ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) : | ||
| 132 | pm8606_osc_disable(chip, RGB2_ENABLE); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | |||
| 117 | static void pm860x_led_work(struct work_struct *work) | 138 | static void pm860x_led_work(struct work_struct *work) |
| 118 | { | 139 | { |
| 119 | 140 | ||
| @@ -126,6 +147,7 @@ static void pm860x_led_work(struct work_struct *work) | |||
| 126 | chip = led->chip; | 147 | chip = led->chip; |
| 127 | mutex_lock(&led->lock); | 148 | mutex_lock(&led->lock); |
| 128 | if ((led->current_brightness == 0) && led->brightness) { | 149 | if ((led->current_brightness == 0) && led->brightness) { |
| 150 | led_power_set(chip, led->port, 1); | ||
| 129 | if (led->iset) { | 151 | if (led->iset) { |
| 130 | pm860x_set_bits(led->i2c, __led_off(led->port), | 152 | pm860x_set_bits(led->i2c, __led_off(led->port), |
| 131 | LED_CURRENT_MASK, led->iset); | 153 | LED_CURRENT_MASK, led->iset); |
| @@ -149,6 +171,7 @@ static void pm860x_led_work(struct work_struct *work) | |||
| 149 | LED_CURRENT_MASK, 0); | 171 | LED_CURRENT_MASK, 0); |
| 150 | mask = __blink_ctl_mask(led->port); | 172 | mask = __blink_ctl_mask(led->port); |
| 151 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); | 173 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); |
| 174 | led_power_set(chip, led->port, 0); | ||
| 152 | } | 175 | } |
| 153 | } | 176 | } |
| 154 | led->current_brightness = led->brightness; | 177 | led->current_brightness = led->brightness; |
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 17dfe9bb6d27..87bd5ba38d5b 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
| @@ -503,6 +503,101 @@ static void device_irq_exit(struct pm860x_chip *chip) | |||
| 503 | free_irq(chip->core_irq, chip); | 503 | free_irq(chip->core_irq, chip); |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client) | ||
| 507 | { | ||
| 508 | int ret = -EIO; | ||
| 509 | struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? | ||
| 510 | chip->client : chip->companion; | ||
| 511 | |||
| 512 | dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); | ||
| 513 | dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", | ||
| 514 | __func__, chip->osc_vote, | ||
| 515 | chip->osc_status); | ||
| 516 | |||
| 517 | mutex_lock(&chip->osc_lock); | ||
| 518 | /* Update voting status */ | ||
| 519 | chip->osc_vote |= client; | ||
| 520 | /* If reference group is off - turn on*/ | ||
| 521 | if (chip->osc_status != PM8606_REF_GP_OSC_ON) { | ||
| 522 | chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; | ||
| 523 | /* Enable Reference group Vsys */ | ||
| 524 | if (pm860x_set_bits(i2c, PM8606_VSYS, | ||
| 525 | PM8606_VSYS_EN, PM8606_VSYS_EN)) | ||
| 526 | goto out; | ||
| 527 | |||
| 528 | /*Enable Internal Oscillator */ | ||
| 529 | if (pm860x_set_bits(i2c, PM8606_MISC, | ||
| 530 | PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN)) | ||
| 531 | goto out; | ||
| 532 | /* Update status (only if writes succeed) */ | ||
| 533 | chip->osc_status = PM8606_REF_GP_OSC_ON; | ||
| 534 | } | ||
| 535 | mutex_unlock(&chip->osc_lock); | ||
| 536 | |||
| 537 | dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", | ||
| 538 | __func__, chip->osc_vote, | ||
| 539 | chip->osc_status, ret); | ||
| 540 | return 0; | ||
| 541 | out: | ||
| 542 | mutex_unlock(&chip->osc_lock); | ||
| 543 | return ret; | ||
| 544 | } | ||
| 545 | EXPORT_SYMBOL(pm8606_osc_enable); | ||
| 546 | |||
| 547 | int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client) | ||
| 548 | { | ||
| 549 | int ret = -EIO; | ||
| 550 | struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? | ||
| 551 | chip->client : chip->companion; | ||
| 552 | |||
| 553 | dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); | ||
| 554 | dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", | ||
| 555 | __func__, chip->osc_vote, | ||
| 556 | chip->osc_status); | ||
| 557 | |||
| 558 | mutex_lock(&chip->osc_lock); | ||
| 559 | /*Update voting status */ | ||
| 560 | chip->osc_vote &= ~(client); | ||
| 561 | /* If reference group is off and this is the last client to release | ||
| 562 | * - turn off */ | ||
| 563 | if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) && | ||
| 564 | (chip->osc_vote == REF_GP_NO_CLIENTS)) { | ||
| 565 | chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; | ||
| 566 | /* Disable Reference group Vsys */ | ||
| 567 | if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0)) | ||
| 568 | goto out; | ||
| 569 | /* Disable Internal Oscillator */ | ||
| 570 | if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0)) | ||
| 571 | goto out; | ||
| 572 | chip->osc_status = PM8606_REF_GP_OSC_OFF; | ||
| 573 | } | ||
| 574 | mutex_unlock(&chip->osc_lock); | ||
| 575 | |||
| 576 | dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", | ||
| 577 | __func__, chip->osc_vote, | ||
| 578 | chip->osc_status, ret); | ||
| 579 | return 0; | ||
| 580 | out: | ||
| 581 | mutex_unlock(&chip->osc_lock); | ||
| 582 | return ret; | ||
| 583 | } | ||
| 584 | EXPORT_SYMBOL(pm8606_osc_disable); | ||
| 585 | |||
| 586 | static void __devinit device_osc_init(struct i2c_client *i2c) | ||
| 587 | { | ||
| 588 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); | ||
| 589 | |||
| 590 | mutex_init(&chip->osc_lock); | ||
| 591 | /* init portofino reference group voting and status */ | ||
| 592 | /* Disable Reference group Vsys */ | ||
| 593 | pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0); | ||
| 594 | /* Disable Internal Oscillator */ | ||
| 595 | pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0); | ||
| 596 | |||
| 597 | chip->osc_vote = REF_GP_NO_CLIENTS; | ||
| 598 | chip->osc_status = PM8606_REF_GP_OSC_OFF; | ||
| 599 | } | ||
| 600 | |||
| 506 | static void __devinit device_bk_init(struct pm860x_chip *chip, | 601 | static void __devinit device_bk_init(struct pm860x_chip *chip, |
| 507 | struct pm860x_platform_data *pdata) | 602 | struct pm860x_platform_data *pdata) |
| 508 | { | 603 | { |
| @@ -767,6 +862,15 @@ out: | |||
| 767 | return; | 862 | return; |
| 768 | } | 863 | } |
| 769 | 864 | ||
| 865 | static void __devinit device_8606_init(struct pm860x_chip *chip, | ||
| 866 | struct i2c_client *i2c, | ||
| 867 | struct pm860x_platform_data *pdata) | ||
| 868 | { | ||
| 869 | device_osc_init(i2c); | ||
| 870 | device_bk_init(chip, pdata); | ||
| 871 | device_led_init(chip, pdata); | ||
| 872 | } | ||
| 873 | |||
| 770 | int __devinit pm860x_device_init(struct pm860x_chip *chip, | 874 | int __devinit pm860x_device_init(struct pm860x_chip *chip, |
| 771 | struct pm860x_platform_data *pdata) | 875 | struct pm860x_platform_data *pdata) |
| 772 | { | 876 | { |
| @@ -774,8 +878,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
| 774 | 878 | ||
| 775 | switch (chip->id) { | 879 | switch (chip->id) { |
| 776 | case CHIP_PM8606: | 880 | case CHIP_PM8606: |
| 777 | device_bk_init(chip, pdata); | 881 | device_8606_init(chip, chip->client, pdata); |
| 778 | device_led_init(chip, pdata); | ||
| 779 | break; | 882 | break; |
| 780 | case CHIP_PM8607: | 883 | case CHIP_PM8607: |
| 781 | device_8607_init(chip, chip->client, pdata); | 884 | device_8607_init(chip, chip->client, pdata); |
| @@ -785,8 +888,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
| 785 | if (chip->companion) { | 888 | if (chip->companion) { |
| 786 | switch (chip->id) { | 889 | switch (chip->id) { |
| 787 | case CHIP_PM8607: | 890 | case CHIP_PM8607: |
| 788 | device_bk_init(chip, pdata); | 891 | device_8606_init(chip, chip->companion, pdata); |
| 789 | device_led_init(chip, pdata); | ||
| 790 | break; | 892 | break; |
| 791 | case CHIP_PM8606: | 893 | case CHIP_PM8606: |
| 792 | device_8607_init(chip, chip->companion, pdata); | 894 | device_8607_init(chip, chip->companion, pdata); |
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c index f93dd9571c3c..b2cfdc458561 100644 --- a/drivers/mfd/88pm860x-i2c.c +++ b/drivers/mfd/88pm860x-i2c.c | |||
| @@ -334,10 +334,35 @@ static int __devexit pm860x_remove(struct i2c_client *client) | |||
| 334 | return 0; | 334 | return 0; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | #ifdef CONFIG_PM_SLEEP | ||
| 338 | static int pm860x_suspend(struct device *dev) | ||
| 339 | { | ||
| 340 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
| 341 | struct pm860x_chip *chip = i2c_get_clientdata(client); | ||
| 342 | |||
| 343 | if (device_may_wakeup(dev) && chip->wakeup_flag) | ||
| 344 | enable_irq_wake(chip->core_irq); | ||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | static int pm860x_resume(struct device *dev) | ||
| 349 | { | ||
| 350 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
| 351 | struct pm860x_chip *chip = i2c_get_clientdata(client); | ||
| 352 | |||
| 353 | if (device_may_wakeup(dev) && chip->wakeup_flag) | ||
| 354 | disable_irq_wake(chip->core_irq); | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | #endif | ||
| 358 | |||
| 359 | static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume); | ||
| 360 | |||
| 337 | static struct i2c_driver pm860x_driver = { | 361 | static struct i2c_driver pm860x_driver = { |
| 338 | .driver = { | 362 | .driver = { |
| 339 | .name = "88PM860x", | 363 | .name = "88PM860x", |
| 340 | .owner = THIS_MODULE, | 364 | .owner = THIS_MODULE, |
| 365 | .pm = &pm860x_pm_ops, | ||
| 341 | }, | 366 | }, |
| 342 | .probe = pm860x_probe, | 367 | .probe = pm860x_probe, |
| 343 | .remove = __devexit_p(pm860x_remove), | 368 | .remove = __devexit_p(pm860x_remove), |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 243e0c663c37..29f463cc09cb 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
| @@ -143,6 +143,21 @@ config TPS6507X | |||
| 143 | This driver can also be built as a module. If so, the module | 143 | This driver can also be built as a module. If so, the module |
| 144 | will be called tps6507x. | 144 | will be called tps6507x. |
| 145 | 145 | ||
| 146 | config MFD_TPS65217 | ||
| 147 | tristate "TPS65217 Power Management / White LED chips" | ||
| 148 | depends on I2C | ||
| 149 | select MFD_CORE | ||
| 150 | select REGMAP_I2C | ||
| 151 | help | ||
| 152 | If you say yes here you get support for the TPS65217 series of | ||
| 153 | Power Management / White LED chips. | ||
| 154 | These include voltage regulators, lithium ion/polymer battery | ||
| 155 | charger, wled and other features that are often used in portable | ||
| 156 | devices. | ||
| 157 | |||
| 158 | This driver can also be built as a module. If so, the module | ||
| 159 | will be called tps65217. | ||
| 160 | |||
| 146 | config MFD_TPS6586X | 161 | config MFD_TPS6586X |
| 147 | bool "TPS6586x Power Management chips" | 162 | bool "TPS6586x Power Management chips" |
| 148 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS | 163 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS |
| @@ -162,6 +177,7 @@ config MFD_TPS65910 | |||
| 162 | depends on I2C=y && GPIOLIB | 177 | depends on I2C=y && GPIOLIB |
| 163 | select MFD_CORE | 178 | select MFD_CORE |
| 164 | select GPIO_TPS65910 | 179 | select GPIO_TPS65910 |
| 180 | select REGMAP_I2C | ||
| 165 | help | 181 | help |
| 166 | if you say yes here you get support for the TPS65910 series of | 182 | if you say yes here you get support for the TPS65910 series of |
| 167 | Power Management chips. | 183 | Power Management chips. |
| @@ -171,7 +187,7 @@ config MFD_TPS65912 | |||
| 171 | depends on GPIOLIB | 187 | depends on GPIOLIB |
| 172 | 188 | ||
| 173 | config MFD_TPS65912_I2C | 189 | config MFD_TPS65912_I2C |
| 174 | bool "TPS95612 Power Management chip with I2C" | 190 | bool "TPS65912 Power Management chip with I2C" |
| 175 | select MFD_CORE | 191 | select MFD_CORE |
| 176 | select MFD_TPS65912 | 192 | select MFD_TPS65912 |
| 177 | depends on I2C=y && GPIOLIB | 193 | depends on I2C=y && GPIOLIB |
| @@ -400,7 +416,7 @@ config MFD_MAX8997 | |||
| 400 | depends on I2C=y && GENERIC_HARDIRQS | 416 | depends on I2C=y && GENERIC_HARDIRQS |
| 401 | select MFD_CORE | 417 | select MFD_CORE |
| 402 | help | 418 | help |
| 403 | Say yes here to support for Maxim Semiconductor MAX8998/8966. | 419 | Say yes here to support for Maxim Semiconductor MAX8997/8966. |
| 404 | This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic, | 420 | This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic, |
| 405 | MUIC controls on chip. | 421 | MUIC controls on chip. |
| 406 | This driver provides common support for accessing the device; | 422 | This driver provides common support for accessing the device; |
| @@ -812,6 +828,18 @@ config MFD_PM8XXX_IRQ | |||
| 812 | config TPS65911_COMPARATOR | 828 | config TPS65911_COMPARATOR |
| 813 | tristate | 829 | tristate |
| 814 | 830 | ||
| 831 | config MFD_TPS65090 | ||
| 832 | bool "TPS65090 Power Management chips" | ||
| 833 | depends on I2C=y && GENERIC_HARDIRQS | ||
| 834 | select MFD_CORE | ||
| 835 | select REGMAP_I2C | ||
| 836 | help | ||
| 837 | If you say yes here you get support for the TPS65090 series of | ||
| 838 | Power Management chips. | ||
| 839 | This driver provides common support for accessing the device, | ||
| 840 | additional drivers must be enabled in order to use the | ||
| 841 | functionality of the device. | ||
| 842 | |||
| 815 | config MFD_AAT2870_CORE | 843 | config MFD_AAT2870_CORE |
| 816 | bool "Support for the AnalogicTech AAT2870" | 844 | bool "Support for the AnalogicTech AAT2870" |
| 817 | select MFD_CORE | 845 | select MFD_CORE |
| @@ -831,6 +859,28 @@ config MFD_INTEL_MSIC | |||
| 831 | Passage) chip. This chip embeds audio, battery, GPIO, etc. | 859 | Passage) chip. This chip embeds audio, battery, GPIO, etc. |
| 832 | devices used in Intel Medfield platforms. | 860 | devices used in Intel Medfield platforms. |
| 833 | 861 | ||
| 862 | config MFD_RC5T583 | ||
| 863 | bool "Ricoh RC5T583 Power Management system device" | ||
| 864 | depends on I2C=y && GENERIC_HARDIRQS | ||
| 865 | select MFD_CORE | ||
| 866 | select REGMAP_I2C | ||
| 867 | help | ||
| 868 | Select this option to get support for the RICOH583 Power | ||
| 869 | Management system device. | ||
| 870 | This driver provides common support for accessing the device | ||
| 871 | through i2c interface. The device supports multiple sub-devices | ||
| 872 | like GPIO, interrupts, RTC, LDO and DCDC regulators, onkey. | ||
| 873 | Additional drivers must be enabled in order to use the | ||
| 874 | different functionality of the device. | ||
| 875 | |||
| 876 | config MFD_ANATOP | ||
| 877 | bool "Support for Freescale i.MX on-chip ANATOP controller" | ||
| 878 | depends on SOC_IMX6Q | ||
| 879 | help | ||
| 880 | Select this option to enable Freescale i.MX on-chip ANATOP | ||
| 881 | MFD controller. This controller embeds regulator and | ||
| 882 | thermal devices for Freescale i.MX platforms. | ||
| 883 | |||
| 834 | endmenu | 884 | endmenu |
| 835 | endif | 885 | endif |
| 836 | 886 | ||
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index b953bab934f7..05fa538c5efe 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
| @@ -38,6 +38,7 @@ obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o wm8994-regmap.o | |||
| 38 | obj-$(CONFIG_TPS6105X) += tps6105x.o | 38 | obj-$(CONFIG_TPS6105X) += tps6105x.o |
| 39 | obj-$(CONFIG_TPS65010) += tps65010.o | 39 | obj-$(CONFIG_TPS65010) += tps65010.o |
| 40 | obj-$(CONFIG_TPS6507X) += tps6507x.o | 40 | obj-$(CONFIG_TPS6507X) += tps6507x.o |
| 41 | obj-$(CONFIG_MFD_TPS65217) += tps65217.o | ||
| 41 | obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o | 42 | obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o |
| 42 | tps65912-objs := tps65912-core.o tps65912-irq.o | 43 | tps65912-objs := tps65912-core.o tps65912-irq.o |
| 43 | obj-$(CONFIG_MFD_TPS65912) += tps65912.o | 44 | obj-$(CONFIG_MFD_TPS65912) += tps65912.o |
| @@ -109,6 +110,9 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o | |||
| 109 | obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o | 110 | obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o |
| 110 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o | 111 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o |
| 111 | obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o | 112 | obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o |
| 113 | obj-$(CONFIG_MFD_TPS65090) += tps65090.o | ||
| 112 | obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o | 114 | obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o |
| 113 | obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o | 115 | obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o |
| 116 | obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o | ||
| 114 | obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o | 117 | obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o |
| 118 | obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o | ||
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index d295941c9a3d..1f08704f7ae8 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #define AB8500_IT_SOURCE6_REG 0x05 | 32 | #define AB8500_IT_SOURCE6_REG 0x05 |
| 33 | #define AB8500_IT_SOURCE7_REG 0x06 | 33 | #define AB8500_IT_SOURCE7_REG 0x06 |
| 34 | #define AB8500_IT_SOURCE8_REG 0x07 | 34 | #define AB8500_IT_SOURCE8_REG 0x07 |
| 35 | #define AB9540_IT_SOURCE13_REG 0x0C | ||
| 35 | #define AB8500_IT_SOURCE19_REG 0x12 | 36 | #define AB8500_IT_SOURCE19_REG 0x12 |
| 36 | #define AB8500_IT_SOURCE20_REG 0x13 | 37 | #define AB8500_IT_SOURCE20_REG 0x13 |
| 37 | #define AB8500_IT_SOURCE21_REG 0x14 | 38 | #define AB8500_IT_SOURCE21_REG 0x14 |
| @@ -53,6 +54,7 @@ | |||
| 53 | #define AB8500_IT_LATCH9_REG 0x28 | 54 | #define AB8500_IT_LATCH9_REG 0x28 |
| 54 | #define AB8500_IT_LATCH10_REG 0x29 | 55 | #define AB8500_IT_LATCH10_REG 0x29 |
| 55 | #define AB8500_IT_LATCH12_REG 0x2B | 56 | #define AB8500_IT_LATCH12_REG 0x2B |
| 57 | #define AB9540_IT_LATCH13_REG 0x2C | ||
| 56 | #define AB8500_IT_LATCH19_REG 0x32 | 58 | #define AB8500_IT_LATCH19_REG 0x32 |
| 57 | #define AB8500_IT_LATCH20_REG 0x33 | 59 | #define AB8500_IT_LATCH20_REG 0x33 |
| 58 | #define AB8500_IT_LATCH21_REG 0x34 | 60 | #define AB8500_IT_LATCH21_REG 0x34 |
| @@ -90,21 +92,39 @@ | |||
| 90 | #define AB8500_IT_MASK24_REG 0x57 | 92 | #define AB8500_IT_MASK24_REG 0x57 |
| 91 | 93 | ||
| 92 | #define AB8500_REV_REG 0x80 | 94 | #define AB8500_REV_REG 0x80 |
| 95 | #define AB8500_IC_NAME_REG 0x82 | ||
| 93 | #define AB8500_SWITCH_OFF_STATUS 0x00 | 96 | #define AB8500_SWITCH_OFF_STATUS 0x00 |
| 94 | 97 | ||
| 95 | #define AB8500_TURN_ON_STATUS 0x00 | 98 | #define AB8500_TURN_ON_STATUS 0x00 |
| 96 | 99 | ||
| 100 | #define AB9540_MODEM_CTRL2_REG 0x23 | ||
| 101 | #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) | ||
| 102 | |||
| 97 | /* | 103 | /* |
| 98 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt | 104 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt |
| 99 | * numbers are indexed into this array with (num / 8). | 105 | * numbers are indexed into this array with (num / 8). The interupts are |
| 106 | * defined in linux/mfd/ab8500.h | ||
| 100 | * | 107 | * |
| 101 | * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at | 108 | * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at |
| 102 | * offset 0. | 109 | * offset 0. |
| 103 | */ | 110 | */ |
| 111 | /* AB8500 support */ | ||
| 104 | static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { | 112 | static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { |
| 105 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, | 113 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, |
| 106 | }; | 114 | }; |
| 107 | 115 | ||
| 116 | /* AB9540 support */ | ||
| 117 | static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { | ||
| 118 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static const char ab8500_version_str[][7] = { | ||
| 122 | [AB8500_VERSION_AB8500] = "AB8500", | ||
| 123 | [AB8500_VERSION_AB8505] = "AB8505", | ||
| 124 | [AB8500_VERSION_AB9540] = "AB9540", | ||
| 125 | [AB8500_VERSION_AB8540] = "AB8540", | ||
| 126 | }; | ||
| 127 | |||
| 108 | static int ab8500_get_chip_id(struct device *dev) | 128 | static int ab8500_get_chip_id(struct device *dev) |
| 109 | { | 129 | { |
| 110 | struct ab8500 *ab8500; | 130 | struct ab8500 *ab8500; |
| @@ -127,9 +147,7 @@ static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, | |||
| 127 | 147 | ||
| 128 | dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); | 148 | dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); |
| 129 | 149 | ||
| 130 | ret = mutex_lock_interruptible(&ab8500->lock); | 150 | mutex_lock(&ab8500->lock); |
| 131 | if (ret) | ||
| 132 | return ret; | ||
| 133 | 151 | ||
| 134 | ret = ab8500->write(ab8500, addr, data); | 152 | ret = ab8500->write(ab8500, addr, data); |
| 135 | if (ret < 0) | 153 | if (ret < 0) |
| @@ -156,9 +174,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, | |||
| 156 | * bank on higher 8 bits and reg in lower */ | 174 | * bank on higher 8 bits and reg in lower */ |
| 157 | u16 addr = ((u16)bank) << 8 | reg; | 175 | u16 addr = ((u16)bank) << 8 | reg; |
| 158 | 176 | ||
| 159 | ret = mutex_lock_interruptible(&ab8500->lock); | 177 | mutex_lock(&ab8500->lock); |
| 160 | if (ret) | ||
| 161 | return ret; | ||
| 162 | 178 | ||
| 163 | ret = ab8500->read(ab8500, addr); | 179 | ret = ab8500->read(ab8500, addr); |
| 164 | if (ret < 0) | 180 | if (ret < 0) |
| @@ -185,31 +201,38 @@ static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, | |||
| 185 | u8 reg, u8 bitmask, u8 bitvalues) | 201 | u8 reg, u8 bitmask, u8 bitvalues) |
| 186 | { | 202 | { |
| 187 | int ret; | 203 | int ret; |
| 188 | u8 data; | ||
| 189 | /* put the u8 bank and u8 reg together into a an u16. | 204 | /* put the u8 bank and u8 reg together into a an u16. |
| 190 | * bank on higher 8 bits and reg in lower */ | 205 | * bank on higher 8 bits and reg in lower */ |
| 191 | u16 addr = ((u16)bank) << 8 | reg; | 206 | u16 addr = ((u16)bank) << 8 | reg; |
| 192 | 207 | ||
| 193 | ret = mutex_lock_interruptible(&ab8500->lock); | 208 | mutex_lock(&ab8500->lock); |
| 194 | if (ret) | ||
| 195 | return ret; | ||
| 196 | 209 | ||
| 197 | ret = ab8500->read(ab8500, addr); | 210 | if (ab8500->write_masked == NULL) { |
| 198 | if (ret < 0) { | 211 | u8 data; |
| 199 | dev_err(ab8500->dev, "failed to read reg %#x: %d\n", | ||
| 200 | addr, ret); | ||
| 201 | goto out; | ||
| 202 | } | ||
| 203 | 212 | ||
| 204 | data = (u8)ret; | 213 | ret = ab8500->read(ab8500, addr); |
| 205 | data = (~bitmask & data) | (bitmask & bitvalues); | 214 | if (ret < 0) { |
| 215 | dev_err(ab8500->dev, "failed to read reg %#x: %d\n", | ||
| 216 | addr, ret); | ||
| 217 | goto out; | ||
| 218 | } | ||
| 206 | 219 | ||
| 207 | ret = ab8500->write(ab8500, addr, data); | 220 | data = (u8)ret; |
| 208 | if (ret < 0) | 221 | data = (~bitmask & data) | (bitmask & bitvalues); |
| 209 | dev_err(ab8500->dev, "failed to write reg %#x: %d\n", | 222 | |
| 210 | addr, ret); | 223 | ret = ab8500->write(ab8500, addr, data); |
| 224 | if (ret < 0) | ||
| 225 | dev_err(ab8500->dev, "failed to write reg %#x: %d\n", | ||
| 226 | addr, ret); | ||
| 211 | 227 | ||
| 212 | dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data); | 228 | dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, |
| 229 | data); | ||
| 230 | goto out; | ||
| 231 | } | ||
| 232 | ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); | ||
| 233 | if (ret < 0) | ||
| 234 | dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, | ||
| 235 | ret); | ||
| 213 | out: | 236 | out: |
| 214 | mutex_unlock(&ab8500->lock); | 237 | mutex_unlock(&ab8500->lock); |
| 215 | return ret; | 238 | return ret; |
| @@ -248,7 +271,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) | |||
| 248 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); | 271 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); |
| 249 | int i; | 272 | int i; |
| 250 | 273 | ||
| 251 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { | 274 | for (i = 0; i < ab8500->mask_size; i++) { |
| 252 | u8 old = ab8500->oldmask[i]; | 275 | u8 old = ab8500->oldmask[i]; |
| 253 | u8 new = ab8500->mask[i]; | 276 | u8 new = ab8500->mask[i]; |
| 254 | int reg; | 277 | int reg; |
| @@ -256,14 +279,17 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) | |||
| 256 | if (new == old) | 279 | if (new == old) |
| 257 | continue; | 280 | continue; |
| 258 | 281 | ||
| 259 | /* Interrupt register 12 doesn't exist prior to version 2.0 */ | 282 | /* |
| 260 | if (ab8500_irq_regoffset[i] == 11 && | 283 | * Interrupt register 12 doesn't exist prior to AB8500 version |
| 261 | ab8500->chip_id < AB8500_CUT2P0) | 284 | * 2.0 |
| 285 | */ | ||
| 286 | if (ab8500->irq_reg_offset[i] == 11 && | ||
| 287 | is_ab8500_1p1_or_earlier(ab8500)) | ||
| 262 | continue; | 288 | continue; |
| 263 | 289 | ||
| 264 | ab8500->oldmask[i] = new; | 290 | ab8500->oldmask[i] = new; |
| 265 | 291 | ||
| 266 | reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; | 292 | reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; |
| 267 | set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); | 293 | set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); |
| 268 | } | 294 | } |
| 269 | 295 | ||
| @@ -306,13 +332,16 @@ static irqreturn_t ab8500_irq(int irq, void *dev) | |||
| 306 | 332 | ||
| 307 | dev_vdbg(ab8500->dev, "interrupt\n"); | 333 | dev_vdbg(ab8500->dev, "interrupt\n"); |
| 308 | 334 | ||
| 309 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { | 335 | for (i = 0; i < ab8500->mask_size; i++) { |
| 310 | int regoffset = ab8500_irq_regoffset[i]; | 336 | int regoffset = ab8500->irq_reg_offset[i]; |
| 311 | int status; | 337 | int status; |
| 312 | u8 value; | 338 | u8 value; |
| 313 | 339 | ||
| 314 | /* Interrupt register 12 doesn't exist prior to version 2.0 */ | 340 | /* |
| 315 | if (regoffset == 11 && ab8500->chip_id < AB8500_CUT2P0) | 341 | * Interrupt register 12 doesn't exist prior to AB8500 version |
| 342 | * 2.0 | ||
| 343 | */ | ||
| 344 | if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) | ||
| 316 | continue; | 345 | continue; |
| 317 | 346 | ||
| 318 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, | 347 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, |
| @@ -336,8 +365,16 @@ static int ab8500_irq_init(struct ab8500 *ab8500) | |||
| 336 | { | 365 | { |
| 337 | int base = ab8500->irq_base; | 366 | int base = ab8500->irq_base; |
| 338 | int irq; | 367 | int irq; |
| 368 | int num_irqs; | ||
| 369 | |||
| 370 | if (is_ab9540(ab8500)) | ||
| 371 | num_irqs = AB9540_NR_IRQS; | ||
| 372 | else if (is_ab8505(ab8500)) | ||
| 373 | num_irqs = AB8505_NR_IRQS; | ||
| 374 | else | ||
| 375 | num_irqs = AB8500_NR_IRQS; | ||
| 339 | 376 | ||
| 340 | for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { | 377 | for (irq = base; irq < base + num_irqs; irq++) { |
| 341 | irq_set_chip_data(irq, ab8500); | 378 | irq_set_chip_data(irq, ab8500); |
| 342 | irq_set_chip_and_handler(irq, &ab8500_irq_chip, | 379 | irq_set_chip_and_handler(irq, &ab8500_irq_chip, |
| 343 | handle_simple_irq); | 380 | handle_simple_irq); |
| @@ -356,8 +393,16 @@ static void ab8500_irq_remove(struct ab8500 *ab8500) | |||
| 356 | { | 393 | { |
| 357 | int base = ab8500->irq_base; | 394 | int base = ab8500->irq_base; |
| 358 | int irq; | 395 | int irq; |
| 396 | int num_irqs; | ||
| 359 | 397 | ||
| 360 | for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { | 398 | if (is_ab9540(ab8500)) |
| 399 | num_irqs = AB9540_NR_IRQS; | ||
| 400 | else if (is_ab8505(ab8500)) | ||
| 401 | num_irqs = AB8505_NR_IRQS; | ||
| 402 | else | ||
| 403 | num_irqs = AB8500_NR_IRQS; | ||
| 404 | |||
| 405 | for (irq = base; irq < base + num_irqs; irq++) { | ||
| 361 | #ifdef CONFIG_ARM | 406 | #ifdef CONFIG_ARM |
| 362 | set_irq_flags(irq, 0); | 407 | set_irq_flags(irq, 0); |
| 363 | #endif | 408 | #endif |
| @@ -366,6 +411,7 @@ static void ab8500_irq_remove(struct ab8500 *ab8500) | |||
| 366 | } | 411 | } |
| 367 | } | 412 | } |
| 368 | 413 | ||
| 414 | /* AB8500 GPIO Resources */ | ||
| 369 | static struct resource __devinitdata ab8500_gpio_resources[] = { | 415 | static struct resource __devinitdata ab8500_gpio_resources[] = { |
| 370 | { | 416 | { |
| 371 | .name = "GPIO_INT6", | 417 | .name = "GPIO_INT6", |
| @@ -375,6 +421,28 @@ static struct resource __devinitdata ab8500_gpio_resources[] = { | |||
| 375 | } | 421 | } |
| 376 | }; | 422 | }; |
| 377 | 423 | ||
| 424 | /* AB9540 GPIO Resources */ | ||
| 425 | static struct resource __devinitdata ab9540_gpio_resources[] = { | ||
| 426 | { | ||
| 427 | .name = "GPIO_INT6", | ||
| 428 | .start = AB8500_INT_GPIO6R, | ||
| 429 | .end = AB8500_INT_GPIO41F, | ||
| 430 | .flags = IORESOURCE_IRQ, | ||
| 431 | }, | ||
| 432 | { | ||
| 433 | .name = "GPIO_INT14", | ||
| 434 | .start = AB9540_INT_GPIO50R, | ||
| 435 | .end = AB9540_INT_GPIO54R, | ||
| 436 | .flags = IORESOURCE_IRQ, | ||
| 437 | }, | ||
| 438 | { | ||
| 439 | .name = "GPIO_INT15", | ||
| 440 | .start = AB9540_INT_GPIO50F, | ||
| 441 | .end = AB9540_INT_GPIO54F, | ||
| 442 | .flags = IORESOURCE_IRQ, | ||
| 443 | } | ||
| 444 | }; | ||
| 445 | |||
| 378 | static struct resource __devinitdata ab8500_gpadc_resources[] = { | 446 | static struct resource __devinitdata ab8500_gpadc_resources[] = { |
| 379 | { | 447 | { |
| 380 | .name = "HW_CONV_END", | 448 | .name = "HW_CONV_END", |
| @@ -491,12 +559,6 @@ static struct resource __devinitdata ab8500_charger_resources[] = { | |||
| 491 | .flags = IORESOURCE_IRQ, | 559 | .flags = IORESOURCE_IRQ, |
| 492 | }, | 560 | }, |
| 493 | { | 561 | { |
| 494 | .name = "USB_CHARGE_DET_DONE", | ||
| 495 | .start = AB8500_INT_USB_CHG_DET_DONE, | ||
| 496 | .end = AB8500_INT_USB_CHG_DET_DONE, | ||
| 497 | .flags = IORESOURCE_IRQ, | ||
| 498 | }, | ||
| 499 | { | ||
| 500 | .name = "VBUS_OVV", | 562 | .name = "VBUS_OVV", |
| 501 | .start = AB8500_INT_VBUS_OVV, | 563 | .start = AB8500_INT_VBUS_OVV, |
| 502 | .end = AB8500_INT_VBUS_OVV, | 564 | .end = AB8500_INT_VBUS_OVV, |
| @@ -534,14 +596,8 @@ static struct resource __devinitdata ab8500_charger_resources[] = { | |||
| 534 | }, | 596 | }, |
| 535 | { | 597 | { |
| 536 | .name = "USB_CHARGER_NOT_OKR", | 598 | .name = "USB_CHARGER_NOT_OKR", |
| 537 | .start = AB8500_INT_USB_CHARGER_NOT_OK, | 599 | .start = AB8500_INT_USB_CHARGER_NOT_OKR, |
| 538 | .end = AB8500_INT_USB_CHARGER_NOT_OK, | 600 | .end = AB8500_INT_USB_CHARGER_NOT_OKR, |
| 539 | .flags = IORESOURCE_IRQ, | ||
| 540 | }, | ||
| 541 | { | ||
| 542 | .name = "USB_CHARGER_NOT_OKF", | ||
| 543 | .start = AB8500_INT_USB_CHARGER_NOT_OKF, | ||
| 544 | .end = AB8500_INT_USB_CHARGER_NOT_OKF, | ||
| 545 | .flags = IORESOURCE_IRQ, | 601 | .flags = IORESOURCE_IRQ, |
| 546 | }, | 602 | }, |
| 547 | { | 603 | { |
| @@ -616,6 +672,12 @@ static struct resource __devinitdata ab8500_fg_resources[] = { | |||
| 616 | .end = AB8500_INT_CC_INT_CALIB, | 672 | .end = AB8500_INT_CC_INT_CALIB, |
| 617 | .flags = IORESOURCE_IRQ, | 673 | .flags = IORESOURCE_IRQ, |
| 618 | }, | 674 | }, |
| 675 | { | ||
| 676 | .name = "CCEOC", | ||
| 677 | .start = AB8500_INT_CCEOC, | ||
| 678 | .end = AB8500_INT_CCEOC, | ||
| 679 | .flags = IORESOURCE_IRQ, | ||
| 680 | }, | ||
| 619 | }; | 681 | }; |
| 620 | 682 | ||
| 621 | static struct resource __devinitdata ab8500_chargalg_resources[] = {}; | 683 | static struct resource __devinitdata ab8500_chargalg_resources[] = {}; |
| @@ -630,8 +692,8 @@ static struct resource __devinitdata ab8500_debug_resources[] = { | |||
| 630 | }, | 692 | }, |
| 631 | { | 693 | { |
| 632 | .name = "IRQ_LAST", | 694 | .name = "IRQ_LAST", |
| 633 | .start = AB8500_INT_USB_CHARGER_NOT_OKF, | 695 | .start = AB8500_INT_XTAL32K_KO, |
| 634 | .end = AB8500_INT_USB_CHARGER_NOT_OKF, | 696 | .end = AB8500_INT_XTAL32K_KO, |
| 635 | .flags = IORESOURCE_IRQ, | 697 | .flags = IORESOURCE_IRQ, |
| 636 | }, | 698 | }, |
| 637 | }; | 699 | }; |
| @@ -691,7 +753,7 @@ static struct resource __devinitdata ab8500_temp_resources[] = { | |||
| 691 | }, | 753 | }, |
| 692 | }; | 754 | }; |
| 693 | 755 | ||
| 694 | static struct mfd_cell __devinitdata ab8500_devs[] = { | 756 | static struct mfd_cell __devinitdata abx500_common_devs[] = { |
| 695 | #ifdef CONFIG_DEBUG_FS | 757 | #ifdef CONFIG_DEBUG_FS |
| 696 | { | 758 | { |
| 697 | .name = "ab8500-debug", | 759 | .name = "ab8500-debug", |
| @@ -706,11 +768,6 @@ static struct mfd_cell __devinitdata ab8500_devs[] = { | |||
| 706 | .name = "ab8500-regulator", | 768 | .name = "ab8500-regulator", |
| 707 | }, | 769 | }, |
| 708 | { | 770 | { |
| 709 | .name = "ab8500-gpio", | ||
| 710 | .num_resources = ARRAY_SIZE(ab8500_gpio_resources), | ||
| 711 | .resources = ab8500_gpio_resources, | ||
| 712 | }, | ||
| 713 | { | ||
| 714 | .name = "ab8500-gpadc", | 771 | .name = "ab8500-gpadc", |
| 715 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), | 772 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), |
| 716 | .resources = ab8500_gpadc_resources, | 773 | .resources = ab8500_gpadc_resources, |
| @@ -748,11 +805,7 @@ static struct mfd_cell __devinitdata ab8500_devs[] = { | |||
| 748 | { | 805 | { |
| 749 | .name = "ab8500-codec", | 806 | .name = "ab8500-codec", |
| 750 | }, | 807 | }, |
| 751 | { | 808 | |
| 752 | .name = "ab8500-usb", | ||
| 753 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), | ||
| 754 | .resources = ab8500_usb_resources, | ||
| 755 | }, | ||
| 756 | { | 809 | { |
| 757 | .name = "ab8500-poweron-key", | 810 | .name = "ab8500-poweron-key", |
| 758 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), | 811 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), |
| @@ -781,6 +834,32 @@ static struct mfd_cell __devinitdata ab8500_devs[] = { | |||
| 781 | }, | 834 | }, |
| 782 | }; | 835 | }; |
| 783 | 836 | ||
| 837 | static struct mfd_cell __devinitdata ab8500_devs[] = { | ||
| 838 | { | ||
| 839 | .name = "ab8500-gpio", | ||
| 840 | .num_resources = ARRAY_SIZE(ab8500_gpio_resources), | ||
| 841 | .resources = ab8500_gpio_resources, | ||
| 842 | }, | ||
| 843 | { | ||
| 844 | .name = "ab8500-usb", | ||
| 845 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), | ||
| 846 | .resources = ab8500_usb_resources, | ||
| 847 | }, | ||
| 848 | }; | ||
| 849 | |||
| 850 | static struct mfd_cell __devinitdata ab9540_devs[] = { | ||
| 851 | { | ||
| 852 | .name = "ab8500-gpio", | ||
| 853 | .num_resources = ARRAY_SIZE(ab9540_gpio_resources), | ||
| 854 | .resources = ab9540_gpio_resources, | ||
| 855 | }, | ||
| 856 | { | ||
| 857 | .name = "ab9540-usb", | ||
| 858 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), | ||
| 859 | .resources = ab8500_usb_resources, | ||
| 860 | }, | ||
| 861 | }; | ||
| 862 | |||
| 784 | static ssize_t show_chip_id(struct device *dev, | 863 | static ssize_t show_chip_id(struct device *dev, |
| 785 | struct device_attribute *attr, char *buf) | 864 | struct device_attribute *attr, char *buf) |
| 786 | { | 865 | { |
| @@ -842,9 +921,64 @@ static ssize_t show_turn_on_status(struct device *dev, | |||
| 842 | return sprintf(buf, "%#x\n", value); | 921 | return sprintf(buf, "%#x\n", value); |
| 843 | } | 922 | } |
| 844 | 923 | ||
| 924 | static ssize_t show_ab9540_dbbrstn(struct device *dev, | ||
| 925 | struct device_attribute *attr, char *buf) | ||
| 926 | { | ||
| 927 | struct ab8500 *ab8500; | ||
| 928 | int ret; | ||
| 929 | u8 value; | ||
| 930 | |||
| 931 | ab8500 = dev_get_drvdata(dev); | ||
| 932 | |||
| 933 | ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, | ||
| 934 | AB9540_MODEM_CTRL2_REG, &value); | ||
| 935 | if (ret < 0) | ||
| 936 | return ret; | ||
| 937 | |||
| 938 | return sprintf(buf, "%d\n", | ||
| 939 | (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); | ||
| 940 | } | ||
| 941 | |||
| 942 | static ssize_t store_ab9540_dbbrstn(struct device *dev, | ||
| 943 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 944 | { | ||
| 945 | struct ab8500 *ab8500; | ||
| 946 | int ret = count; | ||
| 947 | int err; | ||
| 948 | u8 bitvalues; | ||
| 949 | |||
| 950 | ab8500 = dev_get_drvdata(dev); | ||
| 951 | |||
| 952 | if (count > 0) { | ||
| 953 | switch (buf[0]) { | ||
| 954 | case '0': | ||
| 955 | bitvalues = 0; | ||
| 956 | break; | ||
| 957 | case '1': | ||
| 958 | bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; | ||
| 959 | break; | ||
| 960 | default: | ||
| 961 | goto exit; | ||
| 962 | } | ||
| 963 | |||
| 964 | err = mask_and_set_register_interruptible(ab8500, | ||
| 965 | AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, | ||
| 966 | AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); | ||
| 967 | if (err) | ||
| 968 | dev_info(ab8500->dev, | ||
| 969 | "Failed to set DBBRSTN %c, err %#x\n", | ||
| 970 | buf[0], err); | ||
| 971 | } | ||
| 972 | |||
| 973 | exit: | ||
| 974 | return ret; | ||
| 975 | } | ||
| 976 | |||
| 845 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); | 977 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); |
| 846 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); | 978 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); |
| 847 | static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); | 979 | static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); |
| 980 | static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, | ||
| 981 | show_ab9540_dbbrstn, store_ab9540_dbbrstn); | ||
| 848 | 982 | ||
| 849 | static struct attribute *ab8500_sysfs_entries[] = { | 983 | static struct attribute *ab8500_sysfs_entries[] = { |
| 850 | &dev_attr_chip_id.attr, | 984 | &dev_attr_chip_id.attr, |
| @@ -853,11 +987,23 @@ static struct attribute *ab8500_sysfs_entries[] = { | |||
| 853 | NULL, | 987 | NULL, |
| 854 | }; | 988 | }; |
| 855 | 989 | ||
| 990 | static struct attribute *ab9540_sysfs_entries[] = { | ||
| 991 | &dev_attr_chip_id.attr, | ||
| 992 | &dev_attr_switch_off_status.attr, | ||
| 993 | &dev_attr_turn_on_status.attr, | ||
| 994 | &dev_attr_dbbrstn.attr, | ||
| 995 | NULL, | ||
| 996 | }; | ||
| 997 | |||
| 856 | static struct attribute_group ab8500_attr_group = { | 998 | static struct attribute_group ab8500_attr_group = { |
| 857 | .attrs = ab8500_sysfs_entries, | 999 | .attrs = ab8500_sysfs_entries, |
| 858 | }; | 1000 | }; |
| 859 | 1001 | ||
| 860 | int __devinit ab8500_init(struct ab8500 *ab8500) | 1002 | static struct attribute_group ab9540_attr_group = { |
| 1003 | .attrs = ab9540_sysfs_entries, | ||
| 1004 | }; | ||
| 1005 | |||
| 1006 | int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) | ||
| 861 | { | 1007 | { |
| 862 | struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); | 1008 | struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); |
| 863 | int ret; | 1009 | int ret; |
| @@ -870,25 +1016,45 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
| 870 | mutex_init(&ab8500->lock); | 1016 | mutex_init(&ab8500->lock); |
| 871 | mutex_init(&ab8500->irq_lock); | 1017 | mutex_init(&ab8500->irq_lock); |
| 872 | 1018 | ||
| 1019 | if (version != AB8500_VERSION_UNDEFINED) | ||
| 1020 | ab8500->version = version; | ||
| 1021 | else { | ||
| 1022 | ret = get_register_interruptible(ab8500, AB8500_MISC, | ||
| 1023 | AB8500_IC_NAME_REG, &value); | ||
| 1024 | if (ret < 0) | ||
| 1025 | return ret; | ||
| 1026 | |||
| 1027 | ab8500->version = value; | ||
| 1028 | } | ||
| 1029 | |||
| 873 | ret = get_register_interruptible(ab8500, AB8500_MISC, | 1030 | ret = get_register_interruptible(ab8500, AB8500_MISC, |
| 874 | AB8500_REV_REG, &value); | 1031 | AB8500_REV_REG, &value); |
| 875 | if (ret < 0) | 1032 | if (ret < 0) |
| 876 | return ret; | 1033 | return ret; |
| 877 | 1034 | ||
| 878 | switch (value) { | ||
| 879 | case AB8500_CUT1P0: | ||
| 880 | case AB8500_CUT1P1: | ||
| 881 | case AB8500_CUT2P0: | ||
| 882 | case AB8500_CUT3P0: | ||
| 883 | case AB8500_CUT3P3: | ||
| 884 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); | ||
| 885 | break; | ||
| 886 | default: | ||
| 887 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); | ||
| 888 | return -EINVAL; | ||
| 889 | } | ||
| 890 | ab8500->chip_id = value; | 1035 | ab8500->chip_id = value; |
| 891 | 1036 | ||
| 1037 | dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", | ||
| 1038 | ab8500_version_str[ab8500->version], | ||
| 1039 | ab8500->chip_id >> 4, | ||
| 1040 | ab8500->chip_id & 0x0F); | ||
| 1041 | |||
| 1042 | /* Configure AB8500 or AB9540 IRQ */ | ||
| 1043 | if (is_ab9540(ab8500) || is_ab8505(ab8500)) { | ||
| 1044 | ab8500->mask_size = AB9540_NUM_IRQ_REGS; | ||
| 1045 | ab8500->irq_reg_offset = ab9540_irq_regoffset; | ||
| 1046 | } else { | ||
| 1047 | ab8500->mask_size = AB8500_NUM_IRQ_REGS; | ||
| 1048 | ab8500->irq_reg_offset = ab8500_irq_regoffset; | ||
| 1049 | } | ||
| 1050 | ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL); | ||
| 1051 | if (!ab8500->mask) | ||
| 1052 | return -ENOMEM; | ||
| 1053 | ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL); | ||
| 1054 | if (!ab8500->oldmask) { | ||
| 1055 | ret = -ENOMEM; | ||
| 1056 | goto out_freemask; | ||
| 1057 | } | ||
| 892 | /* | 1058 | /* |
| 893 | * ab8500 has switched off due to (SWITCH_OFF_STATUS): | 1059 | * ab8500 has switched off due to (SWITCH_OFF_STATUS): |
| 894 | * 0x01 Swoff bit programming | 1060 | * 0x01 Swoff bit programming |
| @@ -911,30 +1077,33 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
| 911 | plat->init(ab8500); | 1077 | plat->init(ab8500); |
| 912 | 1078 | ||
| 913 | /* Clear and mask all interrupts */ | 1079 | /* Clear and mask all interrupts */ |
| 914 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { | 1080 | for (i = 0; i < ab8500->mask_size; i++) { |
| 915 | /* Interrupt register 12 doesn't exist prior to version 2.0 */ | 1081 | /* |
| 916 | if (ab8500_irq_regoffset[i] == 11 && | 1082 | * Interrupt register 12 doesn't exist prior to AB8500 version |
| 917 | ab8500->chip_id < AB8500_CUT2P0) | 1083 | * 2.0 |
| 1084 | */ | ||
| 1085 | if (ab8500->irq_reg_offset[i] == 11 && | ||
| 1086 | is_ab8500_1p1_or_earlier(ab8500)) | ||
| 918 | continue; | 1087 | continue; |
| 919 | 1088 | ||
| 920 | get_register_interruptible(ab8500, AB8500_INTERRUPT, | 1089 | get_register_interruptible(ab8500, AB8500_INTERRUPT, |
| 921 | AB8500_IT_LATCH1_REG + ab8500_irq_regoffset[i], | 1090 | AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], |
| 922 | &value); | 1091 | &value); |
| 923 | set_register_interruptible(ab8500, AB8500_INTERRUPT, | 1092 | set_register_interruptible(ab8500, AB8500_INTERRUPT, |
| 924 | AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i], 0xff); | 1093 | AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); |
| 925 | } | 1094 | } |
| 926 | 1095 | ||
| 927 | ret = abx500_register_ops(ab8500->dev, &ab8500_ops); | 1096 | ret = abx500_register_ops(ab8500->dev, &ab8500_ops); |
| 928 | if (ret) | 1097 | if (ret) |
| 929 | return ret; | 1098 | goto out_freeoldmask; |
| 930 | 1099 | ||
| 931 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) | 1100 | for (i = 0; i < ab8500->mask_size; i++) |
| 932 | ab8500->mask[i] = ab8500->oldmask[i] = 0xff; | 1101 | ab8500->mask[i] = ab8500->oldmask[i] = 0xff; |
| 933 | 1102 | ||
| 934 | if (ab8500->irq_base) { | 1103 | if (ab8500->irq_base) { |
| 935 | ret = ab8500_irq_init(ab8500); | 1104 | ret = ab8500_irq_init(ab8500); |
| 936 | if (ret) | 1105 | if (ret) |
| 937 | return ret; | 1106 | goto out_freeoldmask; |
| 938 | 1107 | ||
| 939 | ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, | 1108 | ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, |
| 940 | IRQF_ONESHOT | IRQF_NO_SUSPEND, | 1109 | IRQF_ONESHOT | IRQF_NO_SUSPEND, |
| @@ -943,17 +1112,34 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
| 943 | goto out_removeirq; | 1112 | goto out_removeirq; |
| 944 | } | 1113 | } |
| 945 | 1114 | ||
| 946 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, | 1115 | ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, |
| 947 | ARRAY_SIZE(ab8500_devs), NULL, | 1116 | ARRAY_SIZE(abx500_common_devs), NULL, |
| 948 | ab8500->irq_base); | 1117 | ab8500->irq_base); |
| 1118 | |||
| 949 | if (ret) | 1119 | if (ret) |
| 950 | goto out_freeirq; | 1120 | goto out_freeirq; |
| 951 | 1121 | ||
| 952 | ret = sysfs_create_group(&ab8500->dev->kobj, &ab8500_attr_group); | 1122 | if (is_ab9540(ab8500)) |
| 1123 | ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, | ||
| 1124 | ARRAY_SIZE(ab9540_devs), NULL, | ||
| 1125 | ab8500->irq_base); | ||
| 1126 | else | ||
| 1127 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, | ||
| 1128 | ARRAY_SIZE(ab9540_devs), NULL, | ||
| 1129 | ab8500->irq_base); | ||
| 953 | if (ret) | 1130 | if (ret) |
| 954 | dev_err(ab8500->dev, "error creating sysfs entries\n"); | 1131 | goto out_freeirq; |
| 955 | 1132 | ||
| 956 | return ret; | 1133 | if (is_ab9540(ab8500)) |
| 1134 | ret = sysfs_create_group(&ab8500->dev->kobj, | ||
| 1135 | &ab9540_attr_group); | ||
| 1136 | else | ||
| 1137 | ret = sysfs_create_group(&ab8500->dev->kobj, | ||
| 1138 | &ab8500_attr_group); | ||
| 1139 | if (ret) | ||
| 1140 | dev_err(ab8500->dev, "error creating sysfs entries\n"); | ||
| 1141 | else | ||
| 1142 | return ret; | ||
| 957 | 1143 | ||
| 958 | out_freeirq: | 1144 | out_freeirq: |
| 959 | if (ab8500->irq_base) | 1145 | if (ab8500->irq_base) |
| @@ -961,18 +1147,27 @@ out_freeirq: | |||
| 961 | out_removeirq: | 1147 | out_removeirq: |
| 962 | if (ab8500->irq_base) | 1148 | if (ab8500->irq_base) |
| 963 | ab8500_irq_remove(ab8500); | 1149 | ab8500_irq_remove(ab8500); |
| 1150 | out_freeoldmask: | ||
| 1151 | kfree(ab8500->oldmask); | ||
| 1152 | out_freemask: | ||
| 1153 | kfree(ab8500->mask); | ||
| 964 | 1154 | ||
| 965 | return ret; | 1155 | return ret; |
| 966 | } | 1156 | } |
| 967 | 1157 | ||
| 968 | int __devexit ab8500_exit(struct ab8500 *ab8500) | 1158 | int __devexit ab8500_exit(struct ab8500 *ab8500) |
| 969 | { | 1159 | { |
| 970 | sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); | 1160 | if (is_ab9540(ab8500)) |
| 1161 | sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); | ||
| 1162 | else | ||
| 1163 | sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); | ||
| 971 | mfd_remove_devices(ab8500->dev); | 1164 | mfd_remove_devices(ab8500->dev); |
| 972 | if (ab8500->irq_base) { | 1165 | if (ab8500->irq_base) { |
| 973 | free_irq(ab8500->irq, ab8500); | 1166 | free_irq(ab8500->irq, ab8500); |
| 974 | ab8500_irq_remove(ab8500); | 1167 | ab8500_irq_remove(ab8500); |
| 975 | } | 1168 | } |
| 1169 | kfree(ab8500->oldmask); | ||
| 1170 | kfree(ab8500->mask); | ||
| 976 | 1171 | ||
| 977 | return 0; | 1172 | return 0; |
| 978 | } | 1173 | } |
diff --git a/drivers/mfd/ab8500-i2c.c b/drivers/mfd/ab8500-i2c.c index 087fecd71ce0..b83045f102be 100644 --- a/drivers/mfd/ab8500-i2c.c +++ b/drivers/mfd/ab8500-i2c.c | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
| 13 | #include <linux/mfd/abx500/ab8500.h> | 13 | #include <linux/mfd/abx500/ab8500.h> |
| 14 | #include <linux/mfd/db8500-prcmu.h> | 14 | #include <linux/mfd/dbx500-prcmu.h> |
| 15 | 15 | ||
| 16 | static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) | 16 | static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) |
| 17 | { | 17 | { |
| @@ -23,6 +23,18 @@ static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) | |||
| 23 | return ret; | 23 | return ret; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, | ||
| 27 | u8 data) | ||
| 28 | { | ||
| 29 | int ret; | ||
| 30 | |||
| 31 | ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data, | ||
| 32 | &mask, 1); | ||
| 33 | if (ret < 0) | ||
| 34 | dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); | ||
| 35 | return ret; | ||
| 36 | } | ||
| 37 | |||
| 26 | static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr) | 38 | static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr) |
| 27 | { | 39 | { |
| 28 | int ret; | 40 | int ret; |
| @@ -38,6 +50,7 @@ static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr) | |||
| 38 | 50 | ||
| 39 | static int __devinit ab8500_i2c_probe(struct platform_device *plf) | 51 | static int __devinit ab8500_i2c_probe(struct platform_device *plf) |
| 40 | { | 52 | { |
| 53 | const struct platform_device_id *platid = platform_get_device_id(plf); | ||
| 41 | struct ab8500 *ab8500; | 54 | struct ab8500 *ab8500; |
| 42 | struct resource *resource; | 55 | struct resource *resource; |
| 43 | int ret; | 56 | int ret; |
| @@ -58,13 +71,15 @@ static int __devinit ab8500_i2c_probe(struct platform_device *plf) | |||
| 58 | 71 | ||
| 59 | ab8500->read = ab8500_i2c_read; | 72 | ab8500->read = ab8500_i2c_read; |
| 60 | ab8500->write = ab8500_i2c_write; | 73 | ab8500->write = ab8500_i2c_write; |
| 74 | ab8500->write_masked = ab8500_i2c_write_masked; | ||
| 61 | 75 | ||
| 62 | platform_set_drvdata(plf, ab8500); | 76 | platform_set_drvdata(plf, ab8500); |
| 63 | 77 | ||
| 64 | ret = ab8500_init(ab8500); | 78 | ret = ab8500_init(ab8500, platid->driver_data); |
| 65 | if (ret) | 79 | if (ret) |
| 66 | kfree(ab8500); | 80 | kfree(ab8500); |
| 67 | 81 | ||
| 82 | |||
| 68 | return ret; | 83 | return ret; |
| 69 | } | 84 | } |
| 70 | 85 | ||
| @@ -78,13 +93,22 @@ static int __devexit ab8500_i2c_remove(struct platform_device *plf) | |||
| 78 | return 0; | 93 | return 0; |
| 79 | } | 94 | } |
| 80 | 95 | ||
| 96 | static const struct platform_device_id ab8500_id[] = { | ||
| 97 | { "ab8500-i2c", AB8500_VERSION_AB8500 }, | ||
| 98 | { "ab8505-i2c", AB8500_VERSION_AB8505 }, | ||
| 99 | { "ab9540-i2c", AB8500_VERSION_AB9540 }, | ||
| 100 | { "ab8540-i2c", AB8500_VERSION_AB8540 }, | ||
| 101 | { } | ||
| 102 | }; | ||
| 103 | |||
| 81 | static struct platform_driver ab8500_i2c_driver = { | 104 | static struct platform_driver ab8500_i2c_driver = { |
| 82 | .driver = { | 105 | .driver = { |
| 83 | .name = "ab8500-i2c", | 106 | .name = "ab8500-i2c", |
| 84 | .owner = THIS_MODULE, | 107 | .owner = THIS_MODULE, |
| 85 | }, | 108 | }, |
| 86 | .probe = ab8500_i2c_probe, | 109 | .probe = ab8500_i2c_probe, |
| 87 | .remove = __devexit_p(ab8500_i2c_remove) | 110 | .remove = __devexit_p(ab8500_i2c_remove), |
| 111 | .id_table = ab8500_id, | ||
| 88 | }; | 112 | }; |
| 89 | 113 | ||
| 90 | static int __init ab8500_i2c_init(void) | 114 | static int __init ab8500_i2c_init(void) |
diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c new file mode 100644 index 000000000000..2af42480635e --- /dev/null +++ b/drivers/mfd/anatop-mfd.c | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | /* | ||
| 2 | * Anatop MFD driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org> | ||
| 5 | * Copyright (C) 2012 Linaro | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along | ||
| 18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * This program is free software; you can redistribute it and/or modify | ||
| 21 | * it under the terms of the GNU General Public License as published by | ||
| 22 | * the Free Software Foundation; either version 2 of the License, or | ||
| 23 | * (at your option) any later version. | ||
| 24 | * | ||
| 25 | * This program is distributed in the hope that it will be useful, | ||
| 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 28 | * GNU General Public License for more details. | ||
| 29 | * | ||
| 30 | * You should have received a copy of the GNU General Public License along | ||
| 31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 32 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include <linux/io.h> | ||
| 37 | #include <linux/module.h> | ||
| 38 | #include <linux/platform_device.h> | ||
| 39 | #include <linux/of.h> | ||
| 40 | #include <linux/of_platform.h> | ||
| 41 | #include <linux/of_address.h> | ||
| 42 | #include <linux/mfd/anatop.h> | ||
| 43 | |||
| 44 | u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, | ||
| 45 | int bit_width) | ||
| 46 | { | ||
| 47 | u32 val, mask; | ||
| 48 | |||
| 49 | if (bit_width == 32) | ||
| 50 | mask = ~0; | ||
| 51 | else | ||
| 52 | mask = (1 << bit_width) - 1; | ||
| 53 | |||
| 54 | val = readl(adata->ioreg + addr); | ||
| 55 | val = (val >> bit_shift) & mask; | ||
| 56 | |||
| 57 | return val; | ||
| 58 | } | ||
| 59 | EXPORT_SYMBOL_GPL(anatop_get_bits); | ||
| 60 | |||
| 61 | void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift, | ||
| 62 | int bit_width, u32 data) | ||
| 63 | { | ||
| 64 | u32 val, mask; | ||
| 65 | |||
| 66 | if (bit_width == 32) | ||
| 67 | mask = ~0; | ||
| 68 | else | ||
| 69 | mask = (1 << bit_width) - 1; | ||
| 70 | |||
| 71 | spin_lock(&adata->reglock); | ||
| 72 | val = readl(adata->ioreg + addr) & ~(mask << bit_shift); | ||
| 73 | writel((data << bit_shift) | val, adata->ioreg + addr); | ||
| 74 | spin_unlock(&adata->reglock); | ||
| 75 | } | ||
| 76 | EXPORT_SYMBOL_GPL(anatop_set_bits); | ||
| 77 | |||
| 78 | static const struct of_device_id of_anatop_match[] = { | ||
| 79 | { .compatible = "fsl,imx6q-anatop", }, | ||
| 80 | { }, | ||
| 81 | }; | ||
| 82 | |||
| 83 | static int __devinit of_anatop_probe(struct platform_device *pdev) | ||
| 84 | { | ||
| 85 | struct device *dev = &pdev->dev; | ||
| 86 | struct device_node *np = dev->of_node; | ||
| 87 | void *ioreg; | ||
| 88 | struct anatop *drvdata; | ||
| 89 | |||
| 90 | ioreg = of_iomap(np, 0); | ||
| 91 | if (!ioreg) | ||
| 92 | return -EADDRNOTAVAIL; | ||
| 93 | drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); | ||
| 94 | if (!drvdata) | ||
| 95 | return -ENOMEM; | ||
| 96 | drvdata->ioreg = ioreg; | ||
| 97 | spin_lock_init(&drvdata->reglock); | ||
| 98 | platform_set_drvdata(pdev, drvdata); | ||
| 99 | of_platform_populate(np, of_anatop_match, NULL, dev); | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int __devexit of_anatop_remove(struct platform_device *pdev) | ||
| 105 | { | ||
| 106 | struct anatop *drvdata; | ||
| 107 | drvdata = platform_get_drvdata(pdev); | ||
| 108 | iounmap(drvdata->ioreg); | ||
| 109 | |||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | static struct platform_driver anatop_of_driver = { | ||
| 114 | .driver = { | ||
| 115 | .name = "anatop-mfd", | ||
| 116 | .owner = THIS_MODULE, | ||
| 117 | .of_match_table = of_anatop_match, | ||
| 118 | }, | ||
| 119 | .probe = of_anatop_probe, | ||
| 120 | .remove = of_anatop_remove, | ||
| 121 | }; | ||
| 122 | |||
| 123 | static int __init anatop_init(void) | ||
| 124 | { | ||
| 125 | return platform_driver_register(&anatop_of_driver); | ||
| 126 | } | ||
| 127 | postcore_initcall(anatop_init); | ||
| 128 | |||
| 129 | static void __exit anatop_exit(void) | ||
| 130 | { | ||
| 131 | platform_driver_unregister(&anatop_of_driver); | ||
| 132 | } | ||
| 133 | module_exit(anatop_exit); | ||
| 134 | |||
| 135 | MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>"); | ||
| 136 | MODULE_DESCRIPTION("ANATOP MFD driver"); | ||
| 137 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index b85bbd7f0d19..1895cf9fab8c 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
| @@ -525,6 +525,11 @@ static void asic3_gpio_set(struct gpio_chip *chip, | |||
| 525 | return; | 525 | return; |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
| 529 | { | ||
| 530 | return (offset < ASIC3_NUM_GPIOS) ? IRQ_BOARD_START + offset : -ENXIO; | ||
| 531 | } | ||
| 532 | |||
| 528 | static __init int asic3_gpio_probe(struct platform_device *pdev, | 533 | static __init int asic3_gpio_probe(struct platform_device *pdev, |
| 529 | u16 *gpio_config, int num) | 534 | u16 *gpio_config, int num) |
| 530 | { | 535 | { |
| @@ -976,6 +981,7 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
| 976 | asic->gpio.set = asic3_gpio_set; | 981 | asic->gpio.set = asic3_gpio_set; |
| 977 | asic->gpio.direction_input = asic3_gpio_direction_input; | 982 | asic->gpio.direction_input = asic3_gpio_direction_input; |
| 978 | asic->gpio.direction_output = asic3_gpio_direction_output; | 983 | asic->gpio.direction_output = asic3_gpio_direction_output; |
| 984 | asic->gpio.to_irq = asic3_gpio_to_irq; | ||
| 979 | 985 | ||
| 980 | ret = asic3_gpio_probe(pdev, | 986 | ret = asic3_gpio_probe(pdev, |
| 981 | pdata->gpio_config, | 987 | pdata->gpio_config, |
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 5ddde2a9176a..7ff313fe9fb1 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
| 17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
| 21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 22 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| @@ -647,8 +646,6 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) | |||
| 647 | struct irq_desc *desc; | 646 | struct irq_desc *desc; |
| 648 | int ret; | 647 | int ret; |
| 649 | 648 | ||
| 650 | mutex_init(&da9052->io_lock); | ||
| 651 | |||
| 652 | if (pdata && pdata->init != NULL) | 649 | if (pdata && pdata->init != NULL) |
| 653 | pdata->init(da9052); | 650 | pdata->init(da9052); |
| 654 | 651 | ||
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 44b97c70a61f..36b88e395499 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c | |||
| @@ -74,24 +74,27 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client, | |||
| 74 | 74 | ||
| 75 | ret = da9052_i2c_enable_multiwrite(da9052); | 75 | ret = da9052_i2c_enable_multiwrite(da9052); |
| 76 | if (ret < 0) | 76 | if (ret < 0) |
| 77 | goto err; | 77 | goto err_regmap; |
| 78 | 78 | ||
| 79 | ret = da9052_device_init(da9052, id->driver_data); | 79 | ret = da9052_device_init(da9052, id->driver_data); |
| 80 | if (ret != 0) | 80 | if (ret != 0) |
| 81 | goto err; | 81 | goto err_regmap; |
| 82 | 82 | ||
| 83 | return 0; | 83 | return 0; |
| 84 | 84 | ||
| 85 | err_regmap: | ||
| 86 | regmap_exit(da9052->regmap); | ||
| 85 | err: | 87 | err: |
| 86 | kfree(da9052); | 88 | kfree(da9052); |
| 87 | return ret; | 89 | return ret; |
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | static int da9052_i2c_remove(struct i2c_client *client) | 92 | static int __devexit da9052_i2c_remove(struct i2c_client *client) |
| 91 | { | 93 | { |
| 92 | struct da9052 *da9052 = i2c_get_clientdata(client); | 94 | struct da9052 *da9052 = i2c_get_clientdata(client); |
| 93 | 95 | ||
| 94 | da9052_device_exit(da9052); | 96 | da9052_device_exit(da9052); |
| 97 | regmap_exit(da9052->regmap); | ||
| 95 | kfree(da9052); | 98 | kfree(da9052); |
| 96 | 99 | ||
| 97 | return 0; | 100 | return 0; |
| @@ -107,7 +110,7 @@ static struct i2c_device_id da9052_i2c_id[] = { | |||
| 107 | 110 | ||
| 108 | static struct i2c_driver da9052_i2c_driver = { | 111 | static struct i2c_driver da9052_i2c_driver = { |
| 109 | .probe = da9052_i2c_probe, | 112 | .probe = da9052_i2c_probe, |
| 110 | .remove = da9052_i2c_remove, | 113 | .remove = __devexit_p(da9052_i2c_remove), |
| 111 | .id_table = da9052_i2c_id, | 114 | .id_table = da9052_i2c_id, |
| 112 | .driver = { | 115 | .driver = { |
| 113 | .name = "da9052", | 116 | .name = "da9052", |
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c index cdbc7cad326f..6faf149e8d94 100644 --- a/drivers/mfd/da9052-spi.c +++ b/drivers/mfd/da9052-spi.c | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | #include <linux/mfd/da9052/da9052.h> | 22 | #include <linux/mfd/da9052/da9052.h> |
| 23 | 23 | ||
| 24 | static int da9052_spi_probe(struct spi_device *spi) | 24 | static int __devinit da9052_spi_probe(struct spi_device *spi) |
| 25 | { | 25 | { |
| 26 | int ret; | 26 | int ret; |
| 27 | const struct spi_device_id *id = spi_get_device_id(spi); | 27 | const struct spi_device_id *id = spi_get_device_id(spi); |
| @@ -52,20 +52,23 @@ static int da9052_spi_probe(struct spi_device *spi) | |||
| 52 | 52 | ||
| 53 | ret = da9052_device_init(da9052, id->driver_data); | 53 | ret = da9052_device_init(da9052, id->driver_data); |
| 54 | if (ret != 0) | 54 | if (ret != 0) |
| 55 | goto err; | 55 | goto err_regmap; |
| 56 | 56 | ||
| 57 | return 0; | 57 | return 0; |
| 58 | 58 | ||
| 59 | err_regmap: | ||
| 60 | regmap_exit(da9052->regmap); | ||
| 59 | err: | 61 | err: |
| 60 | kfree(da9052); | 62 | kfree(da9052); |
| 61 | return ret; | 63 | return ret; |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 64 | static int da9052_spi_remove(struct spi_device *spi) | 66 | static int __devexit da9052_spi_remove(struct spi_device *spi) |
| 65 | { | 67 | { |
| 66 | struct da9052 *da9052 = dev_get_drvdata(&spi->dev); | 68 | struct da9052 *da9052 = dev_get_drvdata(&spi->dev); |
| 67 | 69 | ||
| 68 | da9052_device_exit(da9052); | 70 | da9052_device_exit(da9052); |
| 71 | regmap_exit(da9052->regmap); | ||
| 69 | kfree(da9052); | 72 | kfree(da9052); |
| 70 | 73 | ||
| 71 | return 0; | 74 | return 0; |
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index af8e0efedbe4..ebc1e8658226 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/mfd/dbx500-prcmu.h> | 30 | #include <linux/mfd/dbx500-prcmu.h> |
| 31 | #include <linux/regulator/db8500-prcmu.h> | 31 | #include <linux/regulator/db8500-prcmu.h> |
| 32 | #include <linux/regulator/machine.h> | 32 | #include <linux/regulator/machine.h> |
| 33 | #include <asm/hardware/gic.h> | ||
| 33 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
| 34 | #include <mach/irqs.h> | 35 | #include <mach/irqs.h> |
| 35 | #include <mach/db8500-regs.h> | 36 | #include <mach/db8500-regs.h> |
| @@ -39,11 +40,6 @@ | |||
| 39 | /* Offset for the firmware version within the TCPM */ | 40 | /* Offset for the firmware version within the TCPM */ |
| 40 | #define PRCMU_FW_VERSION_OFFSET 0xA4 | 41 | #define PRCMU_FW_VERSION_OFFSET 0xA4 |
| 41 | 42 | ||
| 42 | /* PRCMU project numbers, defined by PRCMU FW */ | ||
| 43 | #define PRCMU_PROJECT_ID_8500V1_0 1 | ||
| 44 | #define PRCMU_PROJECT_ID_8500V2_0 2 | ||
| 45 | #define PRCMU_PROJECT_ID_8400V2_0 3 | ||
| 46 | |||
| 47 | /* Index of different voltages to be used when accessing AVSData */ | 43 | /* Index of different voltages to be used when accessing AVSData */ |
| 48 | #define PRCM_AVS_BASE 0x2FC | 44 | #define PRCM_AVS_BASE 0x2FC |
| 49 | #define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) | 45 | #define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) |
| @@ -137,6 +133,8 @@ | |||
| 137 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) | 133 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) |
| 138 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) | 134 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) |
| 139 | #define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) | 135 | #define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) |
| 136 | #define PLL_SOC0_OFF 0x1 | ||
| 137 | #define PLL_SOC0_ON 0x2 | ||
| 140 | #define PLL_SOC1_OFF 0x4 | 138 | #define PLL_SOC1_OFF 0x4 |
| 141 | #define PLL_SOC1_ON 0x8 | 139 | #define PLL_SOC1_ON 0x8 |
| 142 | 140 | ||
| @@ -266,6 +264,11 @@ | |||
| 266 | #define WAKEUP_BIT_GPIO7 BIT(30) | 264 | #define WAKEUP_BIT_GPIO7 BIT(30) |
| 267 | #define WAKEUP_BIT_GPIO8 BIT(31) | 265 | #define WAKEUP_BIT_GPIO8 BIT(31) |
| 268 | 266 | ||
| 267 | static struct { | ||
| 268 | bool valid; | ||
| 269 | struct prcmu_fw_version version; | ||
| 270 | } fw_info; | ||
| 271 | |||
| 269 | /* | 272 | /* |
| 270 | * This vector maps irq numbers to the bits in the bit field used in | 273 | * This vector maps irq numbers to the bits in the bit field used in |
| 271 | * communication with the PRCMU firmware. | 274 | * communication with the PRCMU firmware. |
| @@ -341,11 +344,13 @@ static struct { | |||
| 341 | * mb1_transfer - state needed for mailbox 1 communication. | 344 | * mb1_transfer - state needed for mailbox 1 communication. |
| 342 | * @lock: The transaction lock. | 345 | * @lock: The transaction lock. |
| 343 | * @work: The transaction completion structure. | 346 | * @work: The transaction completion structure. |
| 347 | * @ape_opp: The current APE OPP. | ||
| 344 | * @ack: Reply ("acknowledge") data. | 348 | * @ack: Reply ("acknowledge") data. |
| 345 | */ | 349 | */ |
| 346 | static struct { | 350 | static struct { |
| 347 | struct mutex lock; | 351 | struct mutex lock; |
| 348 | struct completion work; | 352 | struct completion work; |
| 353 | u8 ape_opp; | ||
| 349 | struct { | 354 | struct { |
| 350 | u8 header; | 355 | u8 header; |
| 351 | u8 arm_opp; | 356 | u8 arm_opp; |
| @@ -413,79 +418,102 @@ static struct { | |||
| 413 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); | 418 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); |
| 414 | 419 | ||
| 415 | /* Spinlocks */ | 420 | /* Spinlocks */ |
| 421 | static DEFINE_SPINLOCK(prcmu_lock); | ||
| 416 | static DEFINE_SPINLOCK(clkout_lock); | 422 | static DEFINE_SPINLOCK(clkout_lock); |
| 417 | static DEFINE_SPINLOCK(gpiocr_lock); | ||
| 418 | 423 | ||
| 419 | /* Global var to runtime determine TCDM base for v2 or v1 */ | 424 | /* Global var to runtime determine TCDM base for v2 or v1 */ |
| 420 | static __iomem void *tcdm_base; | 425 | static __iomem void *tcdm_base; |
| 421 | 426 | ||
| 422 | struct clk_mgt { | 427 | struct clk_mgt { |
| 423 | unsigned int offset; | 428 | void __iomem *reg; |
| 424 | u32 pllsw; | 429 | u32 pllsw; |
| 430 | int branch; | ||
| 431 | bool clk38div; | ||
| 432 | }; | ||
| 433 | |||
| 434 | enum { | ||
| 435 | PLL_RAW, | ||
| 436 | PLL_FIX, | ||
| 437 | PLL_DIV | ||
| 425 | }; | 438 | }; |
| 426 | 439 | ||
| 427 | static DEFINE_SPINLOCK(clk_mgt_lock); | 440 | static DEFINE_SPINLOCK(clk_mgt_lock); |
| 428 | 441 | ||
| 429 | #define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 } | 442 | #define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \ |
| 443 | { (PRCM_##_name##_MGT), 0 , _branch, _clk38div} | ||
| 430 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { | 444 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { |
| 431 | CLK_MGT_ENTRY(SGACLK), | 445 | CLK_MGT_ENTRY(SGACLK, PLL_DIV, false), |
| 432 | CLK_MGT_ENTRY(UARTCLK), | 446 | CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true), |
| 433 | CLK_MGT_ENTRY(MSP02CLK), | 447 | CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true), |
| 434 | CLK_MGT_ENTRY(MSP1CLK), | 448 | CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true), |
| 435 | CLK_MGT_ENTRY(I2CCLK), | 449 | CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true), |
| 436 | CLK_MGT_ENTRY(SDMMCCLK), | 450 | CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true), |
| 437 | CLK_MGT_ENTRY(SLIMCLK), | 451 | CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true), |
| 438 | CLK_MGT_ENTRY(PER1CLK), | 452 | CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true), |
| 439 | CLK_MGT_ENTRY(PER2CLK), | 453 | CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true), |
| 440 | CLK_MGT_ENTRY(PER3CLK), | 454 | CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true), |
| 441 | CLK_MGT_ENTRY(PER5CLK), | 455 | CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true), |
| 442 | CLK_MGT_ENTRY(PER6CLK), | 456 | CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true), |
| 443 | CLK_MGT_ENTRY(PER7CLK), | 457 | CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true), |
| 444 | CLK_MGT_ENTRY(LCDCLK), | 458 | CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true), |
| 445 | CLK_MGT_ENTRY(BMLCLK), | 459 | CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true), |
| 446 | CLK_MGT_ENTRY(HSITXCLK), | 460 | CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true), |
| 447 | CLK_MGT_ENTRY(HSIRXCLK), | 461 | CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true), |
| 448 | CLK_MGT_ENTRY(HDMICLK), | 462 | CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false), |
| 449 | CLK_MGT_ENTRY(APEATCLK), | 463 | CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true), |
| 450 | CLK_MGT_ENTRY(APETRACECLK), | 464 | CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true), |
| 451 | CLK_MGT_ENTRY(MCDECLK), | 465 | CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true), |
| 452 | CLK_MGT_ENTRY(IPI2CCLK), | 466 | CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true), |
| 453 | CLK_MGT_ENTRY(DSIALTCLK), | 467 | CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false), |
| 454 | CLK_MGT_ENTRY(DMACLK), | 468 | CLK_MGT_ENTRY(DMACLK, PLL_DIV, true), |
| 455 | CLK_MGT_ENTRY(B2R2CLK), | 469 | CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true), |
| 456 | CLK_MGT_ENTRY(TVCLK), | 470 | CLK_MGT_ENTRY(TVCLK, PLL_FIX, true), |
| 457 | CLK_MGT_ENTRY(SSPCLK), | 471 | CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true), |
| 458 | CLK_MGT_ENTRY(RNGCLK), | 472 | CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true), |
| 459 | CLK_MGT_ENTRY(UICCCLK), | 473 | CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false), |
| 474 | }; | ||
| 475 | |||
| 476 | struct dsiclk { | ||
| 477 | u32 divsel_mask; | ||
| 478 | u32 divsel_shift; | ||
| 479 | u32 divsel; | ||
| 480 | }; | ||
| 481 | |||
| 482 | static struct dsiclk dsiclk[2] = { | ||
| 483 | { | ||
| 484 | .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK, | ||
| 485 | .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT, | ||
| 486 | .divsel = PRCM_DSI_PLLOUT_SEL_PHI, | ||
| 487 | }, | ||
| 488 | { | ||
| 489 | .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK, | ||
| 490 | .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT, | ||
| 491 | .divsel = PRCM_DSI_PLLOUT_SEL_PHI, | ||
| 492 | } | ||
| 460 | }; | 493 | }; |
| 461 | 494 | ||
| 462 | static struct regulator *hwacc_regulator[NUM_HW_ACC]; | 495 | struct dsiescclk { |
| 463 | static struct regulator *hwacc_ret_regulator[NUM_HW_ACC]; | 496 | u32 en; |
| 464 | 497 | u32 div_mask; | |
| 465 | static bool hwacc_enabled[NUM_HW_ACC]; | 498 | u32 div_shift; |
| 466 | static bool hwacc_ret_enabled[NUM_HW_ACC]; | ||
| 467 | |||
| 468 | static const char *hwacc_regulator_name[NUM_HW_ACC] = { | ||
| 469 | [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp", | ||
| 470 | [HW_ACC_SVAPIPE] = "hwacc-sva-pipe", | ||
| 471 | [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp", | ||
| 472 | [HW_ACC_SIAPIPE] = "hwacc-sia-pipe", | ||
| 473 | [HW_ACC_SGA] = "hwacc-sga", | ||
| 474 | [HW_ACC_B2R2] = "hwacc-b2r2", | ||
| 475 | [HW_ACC_MCDE] = "hwacc-mcde", | ||
| 476 | [HW_ACC_ESRAM1] = "hwacc-esram1", | ||
| 477 | [HW_ACC_ESRAM2] = "hwacc-esram2", | ||
| 478 | [HW_ACC_ESRAM3] = "hwacc-esram3", | ||
| 479 | [HW_ACC_ESRAM4] = "hwacc-esram4", | ||
| 480 | }; | 499 | }; |
| 481 | 500 | ||
| 482 | static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | 501 | static struct dsiescclk dsiescclk[3] = { |
| 483 | [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp-ret", | 502 | { |
| 484 | [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp-ret", | 503 | .en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN, |
| 485 | [HW_ACC_ESRAM1] = "hwacc-esram1-ret", | 504 | .div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK, |
| 486 | [HW_ACC_ESRAM2] = "hwacc-esram2-ret", | 505 | .div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT, |
| 487 | [HW_ACC_ESRAM3] = "hwacc-esram3-ret", | 506 | }, |
| 488 | [HW_ACC_ESRAM4] = "hwacc-esram4-ret", | 507 | { |
| 508 | .en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN, | ||
| 509 | .div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK, | ||
| 510 | .div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT, | ||
| 511 | }, | ||
| 512 | { | ||
| 513 | .en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN, | ||
| 514 | .div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK, | ||
| 515 | .div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT, | ||
| 516 | } | ||
| 489 | }; | 517 | }; |
| 490 | 518 | ||
| 491 | /* | 519 | /* |
| @@ -503,9 +531,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | |||
| 503 | /* PLLDIV=12, PLLSW=4 (PLLDDR) */ | 531 | /* PLLDIV=12, PLLSW=4 (PLLDDR) */ |
| 504 | #define PRCMU_DSI_CLOCK_SETTING 0x0000008C | 532 | #define PRCMU_DSI_CLOCK_SETTING 0x0000008C |
| 505 | 533 | ||
| 506 | /* PLLDIV=8, PLLSW=4 (PLLDDR) */ | ||
| 507 | #define PRCMU_DSI_CLOCK_SETTING_U8400 0x00000088 | ||
| 508 | |||
| 509 | /* DPI 50000000 Hz */ | 534 | /* DPI 50000000 Hz */ |
| 510 | #define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ | 535 | #define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ |
| 511 | (16 << PRCMU_CLK_PLL_DIV_SHIFT)) | 536 | (16 << PRCMU_CLK_PLL_DIV_SHIFT)) |
| @@ -514,9 +539,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | |||
| 514 | /* D=101, N=1, R=4, SELDIV2=0 */ | 539 | /* D=101, N=1, R=4, SELDIV2=0 */ |
| 515 | #define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 | 540 | #define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 |
| 516 | 541 | ||
| 517 | /* D=70, N=1, R=3, SELDIV2=0 */ | ||
| 518 | #define PRCMU_PLLDSI_FREQ_SETTING_U8400 0x00030146 | ||
| 519 | |||
| 520 | #define PRCMU_ENABLE_PLLDSI 0x00000001 | 542 | #define PRCMU_ENABLE_PLLDSI 0x00000001 |
| 521 | #define PRCMU_DISABLE_PLLDSI 0x00000000 | 543 | #define PRCMU_DISABLE_PLLDSI 0x00000000 |
| 522 | #define PRCMU_RELEASE_RESET_DSS 0x0000400C | 544 | #define PRCMU_RELEASE_RESET_DSS 0x0000400C |
| @@ -528,30 +550,17 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | |||
| 528 | 550 | ||
| 529 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 | 551 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 |
| 530 | 552 | ||
| 531 | static struct { | ||
| 532 | u8 project_number; | ||
| 533 | u8 api_version; | ||
| 534 | u8 func_version; | ||
| 535 | u8 errata; | ||
| 536 | } prcmu_version; | ||
| 537 | |||
| 538 | |||
| 539 | int db8500_prcmu_enable_dsipll(void) | 553 | int db8500_prcmu_enable_dsipll(void) |
| 540 | { | 554 | { |
| 541 | int i; | 555 | int i; |
| 542 | unsigned int plldsifreq; | ||
| 543 | 556 | ||
| 544 | /* Clear DSIPLL_RESETN */ | 557 | /* Clear DSIPLL_RESETN */ |
| 545 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); | 558 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); |
| 546 | /* Unclamp DSIPLL in/out */ | 559 | /* Unclamp DSIPLL in/out */ |
| 547 | writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); | 560 | writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); |
| 548 | 561 | ||
| 549 | if (prcmu_is_u8400()) | ||
| 550 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; | ||
| 551 | else | ||
| 552 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; | ||
| 553 | /* Set DSI PLL FREQ */ | 562 | /* Set DSI PLL FREQ */ |
| 554 | writel(plldsifreq, PRCM_PLLDSI_FREQ); | 563 | writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ); |
| 555 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); | 564 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); |
| 556 | /* Enable Escape clocks */ | 565 | /* Enable Escape clocks */ |
| 557 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); | 566 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); |
| @@ -583,12 +592,6 @@ int db8500_prcmu_disable_dsipll(void) | |||
| 583 | int db8500_prcmu_set_display_clocks(void) | 592 | int db8500_prcmu_set_display_clocks(void) |
| 584 | { | 593 | { |
| 585 | unsigned long flags; | 594 | unsigned long flags; |
| 586 | unsigned int dsiclk; | ||
| 587 | |||
| 588 | if (prcmu_is_u8400()) | ||
| 589 | dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400; | ||
| 590 | else | ||
| 591 | dsiclk = PRCMU_DSI_CLOCK_SETTING; | ||
| 592 | 595 | ||
| 593 | spin_lock_irqsave(&clk_mgt_lock, flags); | 596 | spin_lock_irqsave(&clk_mgt_lock, flags); |
| 594 | 597 | ||
| @@ -596,7 +599,7 @@ int db8500_prcmu_set_display_clocks(void) | |||
| 596 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 599 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
| 597 | cpu_relax(); | 600 | cpu_relax(); |
| 598 | 601 | ||
| 599 | writel(dsiclk, PRCM_HDMICLK_MGT); | 602 | writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT); |
| 600 | writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); | 603 | writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); |
| 601 | writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); | 604 | writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); |
| 602 | 605 | ||
| @@ -608,43 +611,41 @@ int db8500_prcmu_set_display_clocks(void) | |||
| 608 | return 0; | 611 | return 0; |
| 609 | } | 612 | } |
| 610 | 613 | ||
| 611 | /** | 614 | u32 db8500_prcmu_read(unsigned int reg) |
| 612 | * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. | 615 | { |
| 613 | */ | 616 | return readl(_PRCMU_BASE + reg); |
| 614 | void prcmu_enable_spi2(void) | 617 | } |
| 618 | |||
| 619 | void db8500_prcmu_write(unsigned int reg, u32 value) | ||
| 615 | { | 620 | { |
| 616 | u32 reg; | ||
| 617 | unsigned long flags; | 621 | unsigned long flags; |
| 618 | 622 | ||
| 619 | spin_lock_irqsave(&gpiocr_lock, flags); | 623 | spin_lock_irqsave(&prcmu_lock, flags); |
| 620 | reg = readl(PRCM_GPIOCR); | 624 | writel(value, (_PRCMU_BASE + reg)); |
| 621 | writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); | 625 | spin_unlock_irqrestore(&prcmu_lock, flags); |
| 622 | spin_unlock_irqrestore(&gpiocr_lock, flags); | ||
| 623 | } | 626 | } |
| 624 | 627 | ||
| 625 | /** | 628 | void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value) |
| 626 | * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. | ||
| 627 | */ | ||
| 628 | void prcmu_disable_spi2(void) | ||
| 629 | { | 629 | { |
| 630 | u32 reg; | 630 | u32 val; |
| 631 | unsigned long flags; | 631 | unsigned long flags; |
| 632 | 632 | ||
| 633 | spin_lock_irqsave(&gpiocr_lock, flags); | 633 | spin_lock_irqsave(&prcmu_lock, flags); |
| 634 | reg = readl(PRCM_GPIOCR); | 634 | val = readl(_PRCMU_BASE + reg); |
| 635 | writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); | 635 | val = ((val & ~mask) | (value & mask)); |
| 636 | spin_unlock_irqrestore(&gpiocr_lock, flags); | 636 | writel(val, (_PRCMU_BASE + reg)); |
| 637 | spin_unlock_irqrestore(&prcmu_lock, flags); | ||
| 637 | } | 638 | } |
| 638 | 639 | ||
| 639 | bool prcmu_has_arm_maxopp(void) | 640 | struct prcmu_fw_version *prcmu_get_fw_version(void) |
| 640 | { | 641 | { |
| 641 | return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & | 642 | return fw_info.valid ? &fw_info.version : NULL; |
| 642 | PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; | ||
| 643 | } | 643 | } |
| 644 | 644 | ||
| 645 | bool prcmu_is_u8400(void) | 645 | bool prcmu_has_arm_maxopp(void) |
| 646 | { | 646 | { |
| 647 | return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0; | 647 | return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & |
| 648 | PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; | ||
| 648 | } | 649 | } |
| 649 | 650 | ||
| 650 | /** | 651 | /** |
| @@ -787,6 +788,124 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | |||
| 787 | return 0; | 788 | return 0; |
| 788 | } | 789 | } |
| 789 | 790 | ||
| 791 | u8 db8500_prcmu_get_power_state_result(void) | ||
| 792 | { | ||
| 793 | return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS); | ||
| 794 | } | ||
| 795 | |||
| 796 | /* This function decouple the gic from the prcmu */ | ||
| 797 | int db8500_prcmu_gic_decouple(void) | ||
| 798 | { | ||
| 799 | u32 val = readl(PRCM_A9_MASK_REQ); | ||
| 800 | |||
| 801 | /* Set bit 0 register value to 1 */ | ||
| 802 | writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, | ||
| 803 | PRCM_A9_MASK_REQ); | ||
| 804 | |||
| 805 | /* Make sure the register is updated */ | ||
| 806 | readl(PRCM_A9_MASK_REQ); | ||
| 807 | |||
| 808 | /* Wait a few cycles for the gic mask completion */ | ||
| 809 | udelay(1); | ||
| 810 | |||
| 811 | return 0; | ||
| 812 | } | ||
| 813 | |||
| 814 | /* This function recouple the gic with the prcmu */ | ||
| 815 | int db8500_prcmu_gic_recouple(void) | ||
| 816 | { | ||
| 817 | u32 val = readl(PRCM_A9_MASK_REQ); | ||
| 818 | |||
| 819 | /* Set bit 0 register value to 0 */ | ||
| 820 | writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ); | ||
| 821 | |||
| 822 | return 0; | ||
| 823 | } | ||
| 824 | |||
| 825 | #define PRCMU_GIC_NUMBER_REGS 5 | ||
| 826 | |||
| 827 | /* | ||
| 828 | * This function checks if there are pending irq on the gic. It only | ||
| 829 | * makes sense if the gic has been decoupled before with the | ||
| 830 | * db8500_prcmu_gic_decouple function. Disabling an interrupt only | ||
| 831 | * disables the forwarding of the interrupt to any CPU interface. It | ||
| 832 | * does not prevent the interrupt from changing state, for example | ||
| 833 | * becoming pending, or active and pending if it is already | ||
| 834 | * active. Hence, we have to check the interrupt is pending *and* is | ||
| 835 | * active. | ||
| 836 | */ | ||
| 837 | bool db8500_prcmu_gic_pending_irq(void) | ||
| 838 | { | ||
| 839 | u32 pr; /* Pending register */ | ||
| 840 | u32 er; /* Enable register */ | ||
| 841 | void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE); | ||
| 842 | int i; | ||
| 843 | |||
| 844 | /* 5 registers. STI & PPI not skipped */ | ||
| 845 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) { | ||
| 846 | |||
| 847 | pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4); | ||
| 848 | er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); | ||
| 849 | |||
| 850 | if (pr & er) | ||
| 851 | return true; /* There is a pending interrupt */ | ||
| 852 | } | ||
| 853 | |||
| 854 | return false; | ||
| 855 | } | ||
| 856 | |||
| 857 | /* | ||
| 858 | * This function checks if there are pending interrupt on the | ||
| 859 | * prcmu which has been delegated to monitor the irqs with the | ||
| 860 | * db8500_prcmu_copy_gic_settings function. | ||
| 861 | */ | ||
| 862 | bool db8500_prcmu_pending_irq(void) | ||
| 863 | { | ||
| 864 | u32 it, im; | ||
| 865 | int i; | ||
| 866 | |||
| 867 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) { | ||
| 868 | it = readl(PRCM_ARMITVAL31TO0 + i * 4); | ||
| 869 | im = readl(PRCM_ARMITMSK31TO0 + i * 4); | ||
| 870 | if (it & im) | ||
| 871 | return true; /* There is a pending interrupt */ | ||
| 872 | } | ||
| 873 | |||
| 874 | return false; | ||
| 875 | } | ||
| 876 | |||
| 877 | /* | ||
| 878 | * This function checks if the specified cpu is in in WFI. It's usage | ||
| 879 | * makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple | ||
| 880 | * function. Of course passing smp_processor_id() to this function will | ||
| 881 | * always return false... | ||
| 882 | */ | ||
| 883 | bool db8500_prcmu_is_cpu_in_wfi(int cpu) | ||
| 884 | { | ||
| 885 | return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : | ||
| 886 | PRCM_ARM_WFI_STANDBY_WFI0; | ||
| 887 | } | ||
| 888 | |||
| 889 | /* | ||
| 890 | * This function copies the gic SPI settings to the prcmu in order to | ||
| 891 | * monitor them and abort/finish the retention/off sequence or state. | ||
| 892 | */ | ||
| 893 | int db8500_prcmu_copy_gic_settings(void) | ||
| 894 | { | ||
| 895 | u32 er; /* Enable register */ | ||
| 896 | void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE); | ||
| 897 | int i; | ||
| 898 | |||
| 899 | /* We skip the STI and PPI */ | ||
| 900 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) { | ||
| 901 | er = readl_relaxed(dist_base + | ||
| 902 | GIC_DIST_ENABLE_SET + (i + 1) * 4); | ||
| 903 | writel(er, PRCM_ARMITMSK31TO0 + i * 4); | ||
| 904 | } | ||
| 905 | |||
| 906 | return 0; | ||
| 907 | } | ||
| 908 | |||
| 790 | /* This function should only be called while mb0_transfer.lock is held. */ | 909 | /* This function should only be called while mb0_transfer.lock is held. */ |
| 791 | static void config_wakeups(void) | 910 | static void config_wakeups(void) |
| 792 | { | 911 | { |
| @@ -909,23 +1028,23 @@ int db8500_prcmu_get_arm_opp(void) | |||
| 909 | } | 1028 | } |
| 910 | 1029 | ||
| 911 | /** | 1030 | /** |
| 912 | * prcmu_get_ddr_opp - get the current DDR OPP | 1031 | * db8500_prcmu_get_ddr_opp - get the current DDR OPP |
| 913 | * | 1032 | * |
| 914 | * Returns: the current DDR OPP | 1033 | * Returns: the current DDR OPP |
| 915 | */ | 1034 | */ |
| 916 | int prcmu_get_ddr_opp(void) | 1035 | int db8500_prcmu_get_ddr_opp(void) |
| 917 | { | 1036 | { |
| 918 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); | 1037 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); |
| 919 | } | 1038 | } |
| 920 | 1039 | ||
| 921 | /** | 1040 | /** |
| 922 | * set_ddr_opp - set the appropriate DDR OPP | 1041 | * db8500_set_ddr_opp - set the appropriate DDR OPP |
| 923 | * @opp: The new DDR operating point to which transition is to be made | 1042 | * @opp: The new DDR operating point to which transition is to be made |
| 924 | * Returns: 0 on success, non-zero on failure | 1043 | * Returns: 0 on success, non-zero on failure |
| 925 | * | 1044 | * |
| 926 | * This function sets the operating point of the DDR. | 1045 | * This function sets the operating point of the DDR. |
| 927 | */ | 1046 | */ |
| 928 | int prcmu_set_ddr_opp(u8 opp) | 1047 | int db8500_prcmu_set_ddr_opp(u8 opp) |
| 929 | { | 1048 | { |
| 930 | if (opp < DDR_100_OPP || opp > DDR_25_OPP) | 1049 | if (opp < DDR_100_OPP || opp > DDR_25_OPP) |
| 931 | return -EINVAL; | 1050 | return -EINVAL; |
| @@ -935,25 +1054,82 @@ int prcmu_set_ddr_opp(u8 opp) | |||
| 935 | 1054 | ||
| 936 | return 0; | 1055 | return 0; |
| 937 | } | 1056 | } |
| 1057 | |||
| 1058 | /* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ | ||
| 1059 | static void request_even_slower_clocks(bool enable) | ||
| 1060 | { | ||
| 1061 | void __iomem *clock_reg[] = { | ||
| 1062 | PRCM_ACLK_MGT, | ||
| 1063 | PRCM_DMACLK_MGT | ||
| 1064 | }; | ||
| 1065 | unsigned long flags; | ||
| 1066 | unsigned int i; | ||
| 1067 | |||
| 1068 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
| 1069 | |||
| 1070 | /* Grab the HW semaphore. */ | ||
| 1071 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
| 1072 | cpu_relax(); | ||
| 1073 | |||
| 1074 | for (i = 0; i < ARRAY_SIZE(clock_reg); i++) { | ||
| 1075 | u32 val; | ||
| 1076 | u32 div; | ||
| 1077 | |||
| 1078 | val = readl(clock_reg[i]); | ||
| 1079 | div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK); | ||
| 1080 | if (enable) { | ||
| 1081 | if ((div <= 1) || (div > 15)) { | ||
| 1082 | pr_err("prcmu: Bad clock divider %d in %s\n", | ||
| 1083 | div, __func__); | ||
| 1084 | goto unlock_and_return; | ||
| 1085 | } | ||
| 1086 | div <<= 1; | ||
| 1087 | } else { | ||
| 1088 | if (div <= 2) | ||
| 1089 | goto unlock_and_return; | ||
| 1090 | div >>= 1; | ||
| 1091 | } | ||
| 1092 | val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) | | ||
| 1093 | (div & PRCM_CLK_MGT_CLKPLLDIV_MASK)); | ||
| 1094 | writel(val, clock_reg[i]); | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | unlock_and_return: | ||
| 1098 | /* Release the HW semaphore. */ | ||
| 1099 | writel(0, PRCM_SEM); | ||
| 1100 | |||
| 1101 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
| 1102 | } | ||
| 1103 | |||
| 938 | /** | 1104 | /** |
| 939 | * set_ape_opp - set the appropriate APE OPP | 1105 | * db8500_set_ape_opp - set the appropriate APE OPP |
| 940 | * @opp: The new APE operating point to which transition is to be made | 1106 | * @opp: The new APE operating point to which transition is to be made |
| 941 | * Returns: 0 on success, non-zero on failure | 1107 | * Returns: 0 on success, non-zero on failure |
| 942 | * | 1108 | * |
| 943 | * This function sets the operating point of the APE. | 1109 | * This function sets the operating point of the APE. |
| 944 | */ | 1110 | */ |
| 945 | int prcmu_set_ape_opp(u8 opp) | 1111 | int db8500_prcmu_set_ape_opp(u8 opp) |
| 946 | { | 1112 | { |
| 947 | int r = 0; | 1113 | int r = 0; |
| 948 | 1114 | ||
| 1115 | if (opp == mb1_transfer.ape_opp) | ||
| 1116 | return 0; | ||
| 1117 | |||
| 949 | mutex_lock(&mb1_transfer.lock); | 1118 | mutex_lock(&mb1_transfer.lock); |
| 950 | 1119 | ||
| 1120 | if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP) | ||
| 1121 | request_even_slower_clocks(false); | ||
| 1122 | |||
| 1123 | if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP)) | ||
| 1124 | goto skip_message; | ||
| 1125 | |||
| 951 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 1126 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
| 952 | cpu_relax(); | 1127 | cpu_relax(); |
| 953 | 1128 | ||
| 954 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 1129 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
| 955 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); | 1130 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); |
| 956 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | 1131 | writeb(((opp == APE_50_PARTLY_25_OPP) ? APE_50_OPP : opp), |
| 1132 | (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | ||
| 957 | 1133 | ||
| 958 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | 1134 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); |
| 959 | wait_for_completion(&mb1_transfer.work); | 1135 | wait_for_completion(&mb1_transfer.work); |
| @@ -962,17 +1138,24 @@ int prcmu_set_ape_opp(u8 opp) | |||
| 962 | (mb1_transfer.ack.ape_opp != opp)) | 1138 | (mb1_transfer.ack.ape_opp != opp)) |
| 963 | r = -EIO; | 1139 | r = -EIO; |
| 964 | 1140 | ||
| 1141 | skip_message: | ||
| 1142 | if ((!r && (opp == APE_50_PARTLY_25_OPP)) || | ||
| 1143 | (r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP))) | ||
| 1144 | request_even_slower_clocks(true); | ||
| 1145 | if (!r) | ||
| 1146 | mb1_transfer.ape_opp = opp; | ||
| 1147 | |||
| 965 | mutex_unlock(&mb1_transfer.lock); | 1148 | mutex_unlock(&mb1_transfer.lock); |
| 966 | 1149 | ||
| 967 | return r; | 1150 | return r; |
| 968 | } | 1151 | } |
| 969 | 1152 | ||
| 970 | /** | 1153 | /** |
| 971 | * prcmu_get_ape_opp - get the current APE OPP | 1154 | * db8500_prcmu_get_ape_opp - get the current APE OPP |
| 972 | * | 1155 | * |
| 973 | * Returns: the current APE OPP | 1156 | * Returns: the current APE OPP |
| 974 | */ | 1157 | */ |
| 975 | int prcmu_get_ape_opp(void) | 1158 | int db8500_prcmu_get_ape_opp(void) |
| 976 | { | 1159 | { |
| 977 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); | 1160 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); |
| 978 | } | 1161 | } |
| @@ -1056,7 +1239,9 @@ static int request_pll(u8 clock, bool enable) | |||
| 1056 | { | 1239 | { |
| 1057 | int r = 0; | 1240 | int r = 0; |
| 1058 | 1241 | ||
| 1059 | if (clock == PRCMU_PLLSOC1) | 1242 | if (clock == PRCMU_PLLSOC0) |
| 1243 | clock = (enable ? PLL_SOC0_ON : PLL_SOC0_OFF); | ||
| 1244 | else if (clock == PRCMU_PLLSOC1) | ||
| 1060 | clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); | 1245 | clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); |
| 1061 | else | 1246 | else |
| 1062 | return -EINVAL; | 1247 | return -EINVAL; |
| @@ -1081,132 +1266,6 @@ static int request_pll(u8 clock, bool enable) | |||
| 1081 | } | 1266 | } |
| 1082 | 1267 | ||
| 1083 | /** | 1268 | /** |
| 1084 | * prcmu_set_hwacc - set the power state of a h/w accelerator | ||
| 1085 | * @hwacc_dev: The hardware accelerator (enum hw_acc_dev). | ||
| 1086 | * @state: The new power state (enum hw_acc_state). | ||
| 1087 | * | ||
| 1088 | * This function sets the power state of a hardware accelerator. | ||
| 1089 | * This function should not be called from interrupt context. | ||
| 1090 | * | ||
| 1091 | * NOTE! Deprecated, to be removed when all users switched over to use the | ||
| 1092 | * regulator framework API. | ||
| 1093 | */ | ||
| 1094 | int prcmu_set_hwacc(u16 hwacc_dev, u8 state) | ||
| 1095 | { | ||
| 1096 | int r = 0; | ||
| 1097 | bool ram_retention = false; | ||
| 1098 | bool enable, enable_ret; | ||
| 1099 | |||
| 1100 | /* check argument */ | ||
| 1101 | BUG_ON(hwacc_dev >= NUM_HW_ACC); | ||
| 1102 | |||
| 1103 | /* get state of switches */ | ||
| 1104 | enable = hwacc_enabled[hwacc_dev]; | ||
| 1105 | enable_ret = hwacc_ret_enabled[hwacc_dev]; | ||
| 1106 | |||
| 1107 | /* set flag if retention is possible */ | ||
| 1108 | switch (hwacc_dev) { | ||
| 1109 | case HW_ACC_SVAMMDSP: | ||
| 1110 | case HW_ACC_SIAMMDSP: | ||
| 1111 | case HW_ACC_ESRAM1: | ||
| 1112 | case HW_ACC_ESRAM2: | ||
| 1113 | case HW_ACC_ESRAM3: | ||
| 1114 | case HW_ACC_ESRAM4: | ||
| 1115 | ram_retention = true; | ||
| 1116 | break; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | /* check argument */ | ||
| 1120 | BUG_ON(state > HW_ON); | ||
| 1121 | BUG_ON(state == HW_OFF_RAMRET && !ram_retention); | ||
| 1122 | |||
| 1123 | /* modify enable flags */ | ||
| 1124 | switch (state) { | ||
| 1125 | case HW_OFF: | ||
| 1126 | enable_ret = false; | ||
| 1127 | enable = false; | ||
| 1128 | break; | ||
| 1129 | case HW_ON: | ||
| 1130 | enable = true; | ||
| 1131 | break; | ||
| 1132 | case HW_OFF_RAMRET: | ||
| 1133 | enable_ret = true; | ||
| 1134 | enable = false; | ||
| 1135 | break; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | /* get regulator (lazy) */ | ||
| 1139 | if (hwacc_regulator[hwacc_dev] == NULL) { | ||
| 1140 | hwacc_regulator[hwacc_dev] = regulator_get(NULL, | ||
| 1141 | hwacc_regulator_name[hwacc_dev]); | ||
| 1142 | if (IS_ERR(hwacc_regulator[hwacc_dev])) { | ||
| 1143 | pr_err("prcmu: failed to get supply %s\n", | ||
| 1144 | hwacc_regulator_name[hwacc_dev]); | ||
| 1145 | r = PTR_ERR(hwacc_regulator[hwacc_dev]); | ||
| 1146 | goto out; | ||
| 1147 | } | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | if (ram_retention) { | ||
| 1151 | if (hwacc_ret_regulator[hwacc_dev] == NULL) { | ||
| 1152 | hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL, | ||
| 1153 | hwacc_ret_regulator_name[hwacc_dev]); | ||
| 1154 | if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) { | ||
| 1155 | pr_err("prcmu: failed to get supply %s\n", | ||
| 1156 | hwacc_ret_regulator_name[hwacc_dev]); | ||
| 1157 | r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]); | ||
| 1158 | goto out; | ||
| 1159 | } | ||
| 1160 | } | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | /* set regulators */ | ||
| 1164 | if (ram_retention) { | ||
| 1165 | if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) { | ||
| 1166 | r = regulator_enable(hwacc_ret_regulator[hwacc_dev]); | ||
| 1167 | if (r < 0) { | ||
| 1168 | pr_err("prcmu_set_hwacc: ret enable failed\n"); | ||
| 1169 | goto out; | ||
| 1170 | } | ||
| 1171 | hwacc_ret_enabled[hwacc_dev] = true; | ||
| 1172 | } | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | if (enable && !hwacc_enabled[hwacc_dev]) { | ||
| 1176 | r = regulator_enable(hwacc_regulator[hwacc_dev]); | ||
| 1177 | if (r < 0) { | ||
| 1178 | pr_err("prcmu_set_hwacc: enable failed\n"); | ||
| 1179 | goto out; | ||
| 1180 | } | ||
| 1181 | hwacc_enabled[hwacc_dev] = true; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | if (!enable && hwacc_enabled[hwacc_dev]) { | ||
| 1185 | r = regulator_disable(hwacc_regulator[hwacc_dev]); | ||
| 1186 | if (r < 0) { | ||
| 1187 | pr_err("prcmu_set_hwacc: disable failed\n"); | ||
| 1188 | goto out; | ||
| 1189 | } | ||
| 1190 | hwacc_enabled[hwacc_dev] = false; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | if (ram_retention) { | ||
| 1194 | if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) { | ||
| 1195 | r = regulator_disable(hwacc_ret_regulator[hwacc_dev]); | ||
| 1196 | if (r < 0) { | ||
| 1197 | pr_err("prcmu_set_hwacc: ret disable failed\n"); | ||
| 1198 | goto out; | ||
| 1199 | } | ||
| 1200 | hwacc_ret_enabled[hwacc_dev] = false; | ||
| 1201 | } | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | out: | ||
| 1205 | return r; | ||
| 1206 | } | ||
| 1207 | EXPORT_SYMBOL(prcmu_set_hwacc); | ||
| 1208 | |||
| 1209 | /** | ||
| 1210 | * db8500_prcmu_set_epod - set the state of a EPOD (power domain) | 1269 | * db8500_prcmu_set_epod - set the state of a EPOD (power domain) |
| 1211 | * @epod_id: The EPOD to set | 1270 | * @epod_id: The EPOD to set |
| 1212 | * @epod_state: The new EPOD state | 1271 | * @epod_state: The new EPOD state |
| @@ -1375,7 +1434,7 @@ static int request_timclk(bool enable) | |||
| 1375 | return 0; | 1434 | return 0; |
| 1376 | } | 1435 | } |
| 1377 | 1436 | ||
| 1378 | static int request_reg_clock(u8 clock, bool enable) | 1437 | static int request_clock(u8 clock, bool enable) |
| 1379 | { | 1438 | { |
| 1380 | u32 val; | 1439 | u32 val; |
| 1381 | unsigned long flags; | 1440 | unsigned long flags; |
| @@ -1386,14 +1445,14 @@ static int request_reg_clock(u8 clock, bool enable) | |||
| 1386 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 1445 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
| 1387 | cpu_relax(); | 1446 | cpu_relax(); |
| 1388 | 1447 | ||
| 1389 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); | 1448 | val = readl(clk_mgt[clock].reg); |
| 1390 | if (enable) { | 1449 | if (enable) { |
| 1391 | val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); | 1450 | val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); |
| 1392 | } else { | 1451 | } else { |
| 1393 | clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); | 1452 | clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); |
| 1394 | val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); | 1453 | val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); |
| 1395 | } | 1454 | } |
| 1396 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); | 1455 | writel(val, clk_mgt[clock].reg); |
| 1397 | 1456 | ||
| 1398 | /* Release the HW semaphore. */ | 1457 | /* Release the HW semaphore. */ |
| 1399 | writel(0, PRCM_SEM); | 1458 | writel(0, PRCM_SEM); |
| @@ -1413,7 +1472,7 @@ static int request_sga_clock(u8 clock, bool enable) | |||
| 1413 | writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); | 1472 | writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); |
| 1414 | } | 1473 | } |
| 1415 | 1474 | ||
| 1416 | ret = request_reg_clock(clock, enable); | 1475 | ret = request_clock(clock, enable); |
| 1417 | 1476 | ||
| 1418 | if (!ret && !enable) { | 1477 | if (!ret && !enable) { |
| 1419 | val = readl(PRCM_CGATING_BYPASS); | 1478 | val = readl(PRCM_CGATING_BYPASS); |
| @@ -1423,6 +1482,78 @@ static int request_sga_clock(u8 clock, bool enable) | |||
| 1423 | return ret; | 1482 | return ret; |
| 1424 | } | 1483 | } |
| 1425 | 1484 | ||
| 1485 | static inline bool plldsi_locked(void) | ||
| 1486 | { | ||
| 1487 | return (readl(PRCM_PLLDSI_LOCKP) & | ||
| 1488 | (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 | | ||
| 1489 | PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) == | ||
| 1490 | (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 | | ||
| 1491 | PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3); | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | static int request_plldsi(bool enable) | ||
| 1495 | { | ||
| 1496 | int r = 0; | ||
| 1497 | u32 val; | ||
| 1498 | |||
| 1499 | writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP | | ||
| 1500 | PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), (enable ? | ||
| 1501 | PRCM_MMIP_LS_CLAMP_CLR : PRCM_MMIP_LS_CLAMP_SET)); | ||
| 1502 | |||
| 1503 | val = readl(PRCM_PLLDSI_ENABLE); | ||
| 1504 | if (enable) | ||
| 1505 | val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
| 1506 | else | ||
| 1507 | val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
| 1508 | writel(val, PRCM_PLLDSI_ENABLE); | ||
| 1509 | |||
| 1510 | if (enable) { | ||
| 1511 | unsigned int i; | ||
| 1512 | bool locked = plldsi_locked(); | ||
| 1513 | |||
| 1514 | for (i = 10; !locked && (i > 0); --i) { | ||
| 1515 | udelay(100); | ||
| 1516 | locked = plldsi_locked(); | ||
| 1517 | } | ||
| 1518 | if (locked) { | ||
| 1519 | writel(PRCM_APE_RESETN_DSIPLL_RESETN, | ||
| 1520 | PRCM_APE_RESETN_SET); | ||
| 1521 | } else { | ||
| 1522 | writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP | | ||
| 1523 | PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), | ||
| 1524 | PRCM_MMIP_LS_CLAMP_SET); | ||
| 1525 | val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
| 1526 | writel(val, PRCM_PLLDSI_ENABLE); | ||
| 1527 | r = -EAGAIN; | ||
| 1528 | } | ||
| 1529 | } else { | ||
| 1530 | writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR); | ||
| 1531 | } | ||
| 1532 | return r; | ||
| 1533 | } | ||
| 1534 | |||
| 1535 | static int request_dsiclk(u8 n, bool enable) | ||
| 1536 | { | ||
| 1537 | u32 val; | ||
| 1538 | |||
| 1539 | val = readl(PRCM_DSI_PLLOUT_SEL); | ||
| 1540 | val &= ~dsiclk[n].divsel_mask; | ||
| 1541 | val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) << | ||
| 1542 | dsiclk[n].divsel_shift); | ||
| 1543 | writel(val, PRCM_DSI_PLLOUT_SEL); | ||
| 1544 | return 0; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | static int request_dsiescclk(u8 n, bool enable) | ||
| 1548 | { | ||
| 1549 | u32 val; | ||
| 1550 | |||
| 1551 | val = readl(PRCM_DSITVCLK_DIV); | ||
| 1552 | enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en); | ||
| 1553 | writel(val, PRCM_DSITVCLK_DIV); | ||
| 1554 | return 0; | ||
| 1555 | } | ||
| 1556 | |||
| 1426 | /** | 1557 | /** |
| 1427 | * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. | 1558 | * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. |
| 1428 | * @clock: The clock for which the request is made. | 1559 | * @clock: The clock for which the request is made. |
| @@ -1433,21 +1564,435 @@ static int request_sga_clock(u8 clock, bool enable) | |||
| 1433 | */ | 1564 | */ |
| 1434 | int db8500_prcmu_request_clock(u8 clock, bool enable) | 1565 | int db8500_prcmu_request_clock(u8 clock, bool enable) |
| 1435 | { | 1566 | { |
| 1436 | switch(clock) { | 1567 | if (clock == PRCMU_SGACLK) |
| 1437 | case PRCMU_SGACLK: | ||
| 1438 | return request_sga_clock(clock, enable); | 1568 | return request_sga_clock(clock, enable); |
| 1439 | case PRCMU_TIMCLK: | 1569 | else if (clock < PRCMU_NUM_REG_CLOCKS) |
| 1570 | return request_clock(clock, enable); | ||
| 1571 | else if (clock == PRCMU_TIMCLK) | ||
| 1440 | return request_timclk(enable); | 1572 | return request_timclk(enable); |
| 1441 | case PRCMU_SYSCLK: | 1573 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) |
| 1574 | return request_dsiclk((clock - PRCMU_DSI0CLK), enable); | ||
| 1575 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
| 1576 | return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable); | ||
| 1577 | else if (clock == PRCMU_PLLDSI) | ||
| 1578 | return request_plldsi(enable); | ||
| 1579 | else if (clock == PRCMU_SYSCLK) | ||
| 1442 | return request_sysclk(enable); | 1580 | return request_sysclk(enable); |
| 1443 | case PRCMU_PLLSOC1: | 1581 | else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1)) |
| 1444 | return request_pll(clock, enable); | 1582 | return request_pll(clock, enable); |
| 1583 | else | ||
| 1584 | return -EINVAL; | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate, | ||
| 1588 | int branch) | ||
| 1589 | { | ||
| 1590 | u64 rate; | ||
| 1591 | u32 val; | ||
| 1592 | u32 d; | ||
| 1593 | u32 div = 1; | ||
| 1594 | |||
| 1595 | val = readl(reg); | ||
| 1596 | |||
| 1597 | rate = src_rate; | ||
| 1598 | rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT); | ||
| 1599 | |||
| 1600 | d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT); | ||
| 1601 | if (d > 1) | ||
| 1602 | div *= d; | ||
| 1603 | |||
| 1604 | d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT); | ||
| 1605 | if (d > 1) | ||
| 1606 | div *= d; | ||
| 1607 | |||
| 1608 | if (val & PRCM_PLL_FREQ_SELDIV2) | ||
| 1609 | div *= 2; | ||
| 1610 | |||
| 1611 | if ((branch == PLL_FIX) || ((branch == PLL_DIV) && | ||
| 1612 | (val & PRCM_PLL_FREQ_DIV2EN) && | ||
| 1613 | ((reg == PRCM_PLLSOC0_FREQ) || | ||
| 1614 | (reg == PRCM_PLLDDR_FREQ)))) | ||
| 1615 | div *= 2; | ||
| 1616 | |||
| 1617 | (void)do_div(rate, div); | ||
| 1618 | |||
| 1619 | return (unsigned long)rate; | ||
| 1620 | } | ||
| 1621 | |||
| 1622 | #define ROOT_CLOCK_RATE 38400000 | ||
| 1623 | |||
| 1624 | static unsigned long clock_rate(u8 clock) | ||
| 1625 | { | ||
| 1626 | u32 val; | ||
| 1627 | u32 pllsw; | ||
| 1628 | unsigned long rate = ROOT_CLOCK_RATE; | ||
| 1629 | |||
| 1630 | val = readl(clk_mgt[clock].reg); | ||
| 1631 | |||
| 1632 | if (val & PRCM_CLK_MGT_CLK38) { | ||
| 1633 | if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV)) | ||
| 1634 | rate /= 2; | ||
| 1635 | return rate; | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | val |= clk_mgt[clock].pllsw; | ||
| 1639 | pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); | ||
| 1640 | |||
| 1641 | if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0) | ||
| 1642 | rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch); | ||
| 1643 | else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1) | ||
| 1644 | rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch); | ||
| 1645 | else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR) | ||
| 1646 | rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch); | ||
| 1647 | else | ||
| 1648 | return 0; | ||
| 1649 | |||
| 1650 | if ((clock == PRCMU_SGACLK) && | ||
| 1651 | (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) { | ||
| 1652 | u64 r = (rate * 10); | ||
| 1653 | |||
| 1654 | (void)do_div(r, 25); | ||
| 1655 | return (unsigned long)r; | ||
| 1656 | } | ||
| 1657 | val &= PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
| 1658 | if (val) | ||
| 1659 | return rate / val; | ||
| 1660 | else | ||
| 1661 | return 0; | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | static unsigned long dsiclk_rate(u8 n) | ||
| 1665 | { | ||
| 1666 | u32 divsel; | ||
| 1667 | u32 div = 1; | ||
| 1668 | |||
| 1669 | divsel = readl(PRCM_DSI_PLLOUT_SEL); | ||
| 1670 | divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift); | ||
| 1671 | |||
| 1672 | if (divsel == PRCM_DSI_PLLOUT_SEL_OFF) | ||
| 1673 | divsel = dsiclk[n].divsel; | ||
| 1674 | |||
| 1675 | switch (divsel) { | ||
| 1676 | case PRCM_DSI_PLLOUT_SEL_PHI_4: | ||
| 1677 | div *= 2; | ||
| 1678 | case PRCM_DSI_PLLOUT_SEL_PHI_2: | ||
| 1679 | div *= 2; | ||
| 1680 | case PRCM_DSI_PLLOUT_SEL_PHI: | ||
| 1681 | return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
| 1682 | PLL_RAW) / div; | ||
| 1445 | default: | 1683 | default: |
| 1446 | break; | 1684 | return 0; |
| 1685 | } | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | static unsigned long dsiescclk_rate(u8 n) | ||
| 1689 | { | ||
| 1690 | u32 div; | ||
| 1691 | |||
| 1692 | div = readl(PRCM_DSITVCLK_DIV); | ||
| 1693 | div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift)); | ||
| 1694 | return clock_rate(PRCMU_TVCLK) / max((u32)1, div); | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | unsigned long prcmu_clock_rate(u8 clock) | ||
| 1698 | { | ||
| 1699 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
| 1700 | return clock_rate(clock); | ||
| 1701 | else if (clock == PRCMU_TIMCLK) | ||
| 1702 | return ROOT_CLOCK_RATE / 16; | ||
| 1703 | else if (clock == PRCMU_SYSCLK) | ||
| 1704 | return ROOT_CLOCK_RATE; | ||
| 1705 | else if (clock == PRCMU_PLLSOC0) | ||
| 1706 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
| 1707 | else if (clock == PRCMU_PLLSOC1) | ||
| 1708 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
| 1709 | else if (clock == PRCMU_PLLDDR) | ||
| 1710 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
| 1711 | else if (clock == PRCMU_PLLDSI) | ||
| 1712 | return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
| 1713 | PLL_RAW); | ||
| 1714 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
| 1715 | return dsiclk_rate(clock - PRCMU_DSI0CLK); | ||
| 1716 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
| 1717 | return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK); | ||
| 1718 | else | ||
| 1719 | return 0; | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | static unsigned long clock_source_rate(u32 clk_mgt_val, int branch) | ||
| 1723 | { | ||
| 1724 | if (clk_mgt_val & PRCM_CLK_MGT_CLK38) | ||
| 1725 | return ROOT_CLOCK_RATE; | ||
| 1726 | clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK; | ||
| 1727 | if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0) | ||
| 1728 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch); | ||
| 1729 | else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1) | ||
| 1730 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch); | ||
| 1731 | else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR) | ||
| 1732 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch); | ||
| 1733 | else | ||
| 1734 | return 0; | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | static u32 clock_divider(unsigned long src_rate, unsigned long rate) | ||
| 1738 | { | ||
| 1739 | u32 div; | ||
| 1740 | |||
| 1741 | div = (src_rate / rate); | ||
| 1742 | if (div == 0) | ||
| 1743 | return 1; | ||
| 1744 | if (rate < (src_rate / div)) | ||
| 1745 | div++; | ||
| 1746 | return div; | ||
| 1747 | } | ||
| 1748 | |||
| 1749 | static long round_clock_rate(u8 clock, unsigned long rate) | ||
| 1750 | { | ||
| 1751 | u32 val; | ||
| 1752 | u32 div; | ||
| 1753 | unsigned long src_rate; | ||
| 1754 | long rounded_rate; | ||
| 1755 | |||
| 1756 | val = readl(clk_mgt[clock].reg); | ||
| 1757 | src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), | ||
| 1758 | clk_mgt[clock].branch); | ||
| 1759 | div = clock_divider(src_rate, rate); | ||
| 1760 | if (val & PRCM_CLK_MGT_CLK38) { | ||
| 1761 | if (clk_mgt[clock].clk38div) { | ||
| 1762 | if (div > 2) | ||
| 1763 | div = 2; | ||
| 1764 | } else { | ||
| 1765 | div = 1; | ||
| 1766 | } | ||
| 1767 | } else if ((clock == PRCMU_SGACLK) && (div == 3)) { | ||
| 1768 | u64 r = (src_rate * 10); | ||
| 1769 | |||
| 1770 | (void)do_div(r, 25); | ||
| 1771 | if (r <= rate) | ||
| 1772 | return (unsigned long)r; | ||
| 1773 | } | ||
| 1774 | rounded_rate = (src_rate / min(div, (u32)31)); | ||
| 1775 | |||
| 1776 | return rounded_rate; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | #define MIN_PLL_VCO_RATE 600000000ULL | ||
| 1780 | #define MAX_PLL_VCO_RATE 1680640000ULL | ||
| 1781 | |||
| 1782 | static long round_plldsi_rate(unsigned long rate) | ||
| 1783 | { | ||
| 1784 | long rounded_rate = 0; | ||
| 1785 | unsigned long src_rate; | ||
| 1786 | unsigned long rem; | ||
| 1787 | u32 r; | ||
| 1788 | |||
| 1789 | src_rate = clock_rate(PRCMU_HDMICLK); | ||
| 1790 | rem = rate; | ||
| 1791 | |||
| 1792 | for (r = 7; (rem > 0) && (r > 0); r--) { | ||
| 1793 | u64 d; | ||
| 1794 | |||
| 1795 | d = (r * rate); | ||
| 1796 | (void)do_div(d, src_rate); | ||
| 1797 | if (d < 6) | ||
| 1798 | d = 6; | ||
| 1799 | else if (d > 255) | ||
| 1800 | d = 255; | ||
| 1801 | d *= src_rate; | ||
| 1802 | if (((2 * d) < (r * MIN_PLL_VCO_RATE)) || | ||
| 1803 | ((r * MAX_PLL_VCO_RATE) < (2 * d))) | ||
| 1804 | continue; | ||
| 1805 | (void)do_div(d, r); | ||
| 1806 | if (rate < d) { | ||
| 1807 | if (rounded_rate == 0) | ||
| 1808 | rounded_rate = (long)d; | ||
| 1809 | break; | ||
| 1810 | } | ||
| 1811 | if ((rate - d) < rem) { | ||
| 1812 | rem = (rate - d); | ||
| 1813 | rounded_rate = (long)d; | ||
| 1814 | } | ||
| 1815 | } | ||
| 1816 | return rounded_rate; | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | static long round_dsiclk_rate(unsigned long rate) | ||
| 1820 | { | ||
| 1821 | u32 div; | ||
| 1822 | unsigned long src_rate; | ||
| 1823 | long rounded_rate; | ||
| 1824 | |||
| 1825 | src_rate = pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
| 1826 | PLL_RAW); | ||
| 1827 | div = clock_divider(src_rate, rate); | ||
| 1828 | rounded_rate = (src_rate / ((div > 2) ? 4 : div)); | ||
| 1829 | |||
| 1830 | return rounded_rate; | ||
| 1831 | } | ||
| 1832 | |||
| 1833 | static long round_dsiescclk_rate(unsigned long rate) | ||
| 1834 | { | ||
| 1835 | u32 div; | ||
| 1836 | unsigned long src_rate; | ||
| 1837 | long rounded_rate; | ||
| 1838 | |||
| 1839 | src_rate = clock_rate(PRCMU_TVCLK); | ||
| 1840 | div = clock_divider(src_rate, rate); | ||
| 1841 | rounded_rate = (src_rate / min(div, (u32)255)); | ||
| 1842 | |||
| 1843 | return rounded_rate; | ||
| 1844 | } | ||
| 1845 | |||
| 1846 | long prcmu_round_clock_rate(u8 clock, unsigned long rate) | ||
| 1847 | { | ||
| 1848 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
| 1849 | return round_clock_rate(clock, rate); | ||
| 1850 | else if (clock == PRCMU_PLLDSI) | ||
| 1851 | return round_plldsi_rate(rate); | ||
| 1852 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
| 1853 | return round_dsiclk_rate(rate); | ||
| 1854 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
| 1855 | return round_dsiescclk_rate(rate); | ||
| 1856 | else | ||
| 1857 | return (long)prcmu_clock_rate(clock); | ||
| 1858 | } | ||
| 1859 | |||
| 1860 | static void set_clock_rate(u8 clock, unsigned long rate) | ||
| 1861 | { | ||
| 1862 | u32 val; | ||
| 1863 | u32 div; | ||
| 1864 | unsigned long src_rate; | ||
| 1865 | unsigned long flags; | ||
| 1866 | |||
| 1867 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
| 1868 | |||
| 1869 | /* Grab the HW semaphore. */ | ||
| 1870 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
| 1871 | cpu_relax(); | ||
| 1872 | |||
| 1873 | val = readl(clk_mgt[clock].reg); | ||
| 1874 | src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), | ||
| 1875 | clk_mgt[clock].branch); | ||
| 1876 | div = clock_divider(src_rate, rate); | ||
| 1877 | if (val & PRCM_CLK_MGT_CLK38) { | ||
| 1878 | if (clk_mgt[clock].clk38div) { | ||
| 1879 | if (div > 1) | ||
| 1880 | val |= PRCM_CLK_MGT_CLK38DIV; | ||
| 1881 | else | ||
| 1882 | val &= ~PRCM_CLK_MGT_CLK38DIV; | ||
| 1883 | } | ||
| 1884 | } else if (clock == PRCMU_SGACLK) { | ||
| 1885 | val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK | | ||
| 1886 | PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN); | ||
| 1887 | if (div == 3) { | ||
| 1888 | u64 r = (src_rate * 10); | ||
| 1889 | |||
| 1890 | (void)do_div(r, 25); | ||
| 1891 | if (r <= rate) { | ||
| 1892 | val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN; | ||
| 1893 | div = 0; | ||
| 1894 | } | ||
| 1895 | } | ||
| 1896 | val |= min(div, (u32)31); | ||
| 1897 | } else { | ||
| 1898 | val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
| 1899 | val |= min(div, (u32)31); | ||
| 1900 | } | ||
| 1901 | writel(val, clk_mgt[clock].reg); | ||
| 1902 | |||
| 1903 | /* Release the HW semaphore. */ | ||
| 1904 | writel(0, PRCM_SEM); | ||
| 1905 | |||
| 1906 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | static int set_plldsi_rate(unsigned long rate) | ||
| 1910 | { | ||
| 1911 | unsigned long src_rate; | ||
| 1912 | unsigned long rem; | ||
| 1913 | u32 pll_freq = 0; | ||
| 1914 | u32 r; | ||
| 1915 | |||
| 1916 | src_rate = clock_rate(PRCMU_HDMICLK); | ||
| 1917 | rem = rate; | ||
| 1918 | |||
| 1919 | for (r = 7; (rem > 0) && (r > 0); r--) { | ||
| 1920 | u64 d; | ||
| 1921 | u64 hwrate; | ||
| 1922 | |||
| 1923 | d = (r * rate); | ||
| 1924 | (void)do_div(d, src_rate); | ||
| 1925 | if (d < 6) | ||
| 1926 | d = 6; | ||
| 1927 | else if (d > 255) | ||
| 1928 | d = 255; | ||
| 1929 | hwrate = (d * src_rate); | ||
| 1930 | if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) || | ||
| 1931 | ((r * MAX_PLL_VCO_RATE) < (2 * hwrate))) | ||
| 1932 | continue; | ||
| 1933 | (void)do_div(hwrate, r); | ||
| 1934 | if (rate < hwrate) { | ||
| 1935 | if (pll_freq == 0) | ||
| 1936 | pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) | | ||
| 1937 | (r << PRCM_PLL_FREQ_R_SHIFT)); | ||
| 1938 | break; | ||
| 1939 | } | ||
| 1940 | if ((rate - hwrate) < rem) { | ||
| 1941 | rem = (rate - hwrate); | ||
| 1942 | pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) | | ||
| 1943 | (r << PRCM_PLL_FREQ_R_SHIFT)); | ||
| 1944 | } | ||
| 1447 | } | 1945 | } |
| 1946 | if (pll_freq == 0) | ||
| 1947 | return -EINVAL; | ||
| 1948 | |||
| 1949 | pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT); | ||
| 1950 | writel(pll_freq, PRCM_PLLDSI_FREQ); | ||
| 1951 | |||
| 1952 | return 0; | ||
| 1953 | } | ||
| 1954 | |||
| 1955 | static void set_dsiclk_rate(u8 n, unsigned long rate) | ||
| 1956 | { | ||
| 1957 | u32 val; | ||
| 1958 | u32 div; | ||
| 1959 | |||
| 1960 | div = clock_divider(pll_rate(PRCM_PLLDSI_FREQ, | ||
| 1961 | clock_rate(PRCMU_HDMICLK), PLL_RAW), rate); | ||
| 1962 | |||
| 1963 | dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI : | ||
| 1964 | (div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 : | ||
| 1965 | /* else */ PRCM_DSI_PLLOUT_SEL_PHI_4; | ||
| 1966 | |||
| 1967 | val = readl(PRCM_DSI_PLLOUT_SEL); | ||
| 1968 | val &= ~dsiclk[n].divsel_mask; | ||
| 1969 | val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift); | ||
| 1970 | writel(val, PRCM_DSI_PLLOUT_SEL); | ||
| 1971 | } | ||
| 1972 | |||
| 1973 | static void set_dsiescclk_rate(u8 n, unsigned long rate) | ||
| 1974 | { | ||
| 1975 | u32 val; | ||
| 1976 | u32 div; | ||
| 1977 | |||
| 1978 | div = clock_divider(clock_rate(PRCMU_TVCLK), rate); | ||
| 1979 | val = readl(PRCM_DSITVCLK_DIV); | ||
| 1980 | val &= ~dsiescclk[n].div_mask; | ||
| 1981 | val |= (min(div, (u32)255) << dsiescclk[n].div_shift); | ||
| 1982 | writel(val, PRCM_DSITVCLK_DIV); | ||
| 1983 | } | ||
| 1984 | |||
| 1985 | int prcmu_set_clock_rate(u8 clock, unsigned long rate) | ||
| 1986 | { | ||
| 1448 | if (clock < PRCMU_NUM_REG_CLOCKS) | 1987 | if (clock < PRCMU_NUM_REG_CLOCKS) |
| 1449 | return request_reg_clock(clock, enable); | 1988 | set_clock_rate(clock, rate); |
| 1450 | return -EINVAL; | 1989 | else if (clock == PRCMU_PLLDSI) |
| 1990 | return set_plldsi_rate(rate); | ||
| 1991 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
| 1992 | set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate); | ||
| 1993 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
| 1994 | set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate); | ||
| 1995 | return 0; | ||
| 1451 | } | 1996 | } |
| 1452 | 1997 | ||
| 1453 | int db8500_prcmu_config_esram0_deep_sleep(u8 state) | 1998 | int db8500_prcmu_config_esram0_deep_sleep(u8 state) |
| @@ -1476,7 +2021,7 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state) | |||
| 1476 | return 0; | 2021 | return 0; |
| 1477 | } | 2022 | } |
| 1478 | 2023 | ||
| 1479 | int prcmu_config_hotdog(u8 threshold) | 2024 | int db8500_prcmu_config_hotdog(u8 threshold) |
| 1480 | { | 2025 | { |
| 1481 | mutex_lock(&mb4_transfer.lock); | 2026 | mutex_lock(&mb4_transfer.lock); |
| 1482 | 2027 | ||
| @@ -1494,7 +2039,7 @@ int prcmu_config_hotdog(u8 threshold) | |||
| 1494 | return 0; | 2039 | return 0; |
| 1495 | } | 2040 | } |
| 1496 | 2041 | ||
| 1497 | int prcmu_config_hotmon(u8 low, u8 high) | 2042 | int db8500_prcmu_config_hotmon(u8 low, u8 high) |
| 1498 | { | 2043 | { |
| 1499 | mutex_lock(&mb4_transfer.lock); | 2044 | mutex_lock(&mb4_transfer.lock); |
| 1500 | 2045 | ||
| @@ -1533,7 +2078,7 @@ static int config_hot_period(u16 val) | |||
| 1533 | return 0; | 2078 | return 0; |
| 1534 | } | 2079 | } |
| 1535 | 2080 | ||
| 1536 | int prcmu_start_temp_sense(u16 cycles32k) | 2081 | int db8500_prcmu_start_temp_sense(u16 cycles32k) |
| 1537 | { | 2082 | { |
| 1538 | if (cycles32k == 0xFFFF) | 2083 | if (cycles32k == 0xFFFF) |
| 1539 | return -EINVAL; | 2084 | return -EINVAL; |
| @@ -1541,7 +2086,7 @@ int prcmu_start_temp_sense(u16 cycles32k) | |||
| 1541 | return config_hot_period(cycles32k); | 2086 | return config_hot_period(cycles32k); |
| 1542 | } | 2087 | } |
| 1543 | 2088 | ||
| 1544 | int prcmu_stop_temp_sense(void) | 2089 | int db8500_prcmu_stop_temp_sense(void) |
| 1545 | { | 2090 | { |
| 1546 | return config_hot_period(0xFFFF); | 2091 | return config_hot_period(0xFFFF); |
| 1547 | } | 2092 | } |
| @@ -1570,7 +2115,7 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) | |||
| 1570 | 2115 | ||
| 1571 | } | 2116 | } |
| 1572 | 2117 | ||
| 1573 | int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | 2118 | int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) |
| 1574 | { | 2119 | { |
| 1575 | BUG_ON(num == 0 || num > 0xf); | 2120 | BUG_ON(num == 0 || num > 0xf); |
| 1576 | return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, | 2121 | return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, |
| @@ -1578,17 +2123,17 @@ int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | |||
| 1578 | A9WDOG_AUTO_OFF_DIS); | 2123 | A9WDOG_AUTO_OFF_DIS); |
| 1579 | } | 2124 | } |
| 1580 | 2125 | ||
| 1581 | int prcmu_enable_a9wdog(u8 id) | 2126 | int db8500_prcmu_enable_a9wdog(u8 id) |
| 1582 | { | 2127 | { |
| 1583 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); | 2128 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); |
| 1584 | } | 2129 | } |
| 1585 | 2130 | ||
| 1586 | int prcmu_disable_a9wdog(u8 id) | 2131 | int db8500_prcmu_disable_a9wdog(u8 id) |
| 1587 | { | 2132 | { |
| 1588 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); | 2133 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); |
| 1589 | } | 2134 | } |
| 1590 | 2135 | ||
| 1591 | int prcmu_kick_a9wdog(u8 id) | 2136 | int db8500_prcmu_kick_a9wdog(u8 id) |
| 1592 | { | 2137 | { |
| 1593 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); | 2138 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); |
| 1594 | } | 2139 | } |
| @@ -1596,16 +2141,8 @@ int prcmu_kick_a9wdog(u8 id) | |||
| 1596 | /* | 2141 | /* |
| 1597 | * timeout is 28 bit, in ms. | 2142 | * timeout is 28 bit, in ms. |
| 1598 | */ | 2143 | */ |
| 1599 | #define MAX_WATCHDOG_TIMEOUT 131000 | 2144 | int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) |
| 1600 | int prcmu_load_a9wdog(u8 id, u32 timeout) | ||
| 1601 | { | 2145 | { |
| 1602 | if (timeout > MAX_WATCHDOG_TIMEOUT) | ||
| 1603 | /* | ||
| 1604 | * Due to calculation bug in prcmu fw, timeouts | ||
| 1605 | * can't be bigger than 131 seconds. | ||
| 1606 | */ | ||
| 1607 | return -EINVAL; | ||
| 1608 | |||
| 1609 | return prcmu_a9wdog(MB4H_A9WDOG_LOAD, | 2146 | return prcmu_a9wdog(MB4H_A9WDOG_LOAD, |
| 1610 | (id & A9WDOG_ID_MASK) | | 2147 | (id & A9WDOG_ID_MASK) | |
| 1611 | /* | 2148 | /* |
| @@ -1619,41 +2156,6 @@ int prcmu_load_a9wdog(u8 id, u32 timeout) | |||
| 1619 | } | 2156 | } |
| 1620 | 2157 | ||
| 1621 | /** | 2158 | /** |
| 1622 | * prcmu_set_clock_divider() - Configure the clock divider. | ||
| 1623 | * @clock: The clock for which the request is made. | ||
| 1624 | * @divider: The clock divider. (< 32) | ||
| 1625 | * | ||
| 1626 | * This function should only be used by the clock implementation. | ||
| 1627 | * Do not use it from any other place! | ||
| 1628 | */ | ||
| 1629 | int prcmu_set_clock_divider(u8 clock, u8 divider) | ||
| 1630 | { | ||
| 1631 | u32 val; | ||
| 1632 | unsigned long flags; | ||
| 1633 | |||
| 1634 | if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider)) | ||
| 1635 | return -EINVAL; | ||
| 1636 | |||
| 1637 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
| 1638 | |||
| 1639 | /* Grab the HW semaphore. */ | ||
| 1640 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
| 1641 | cpu_relax(); | ||
| 1642 | |||
| 1643 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); | ||
| 1644 | val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK); | ||
| 1645 | val |= (u32)divider; | ||
| 1646 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); | ||
| 1647 | |||
| 1648 | /* Release the HW semaphore. */ | ||
| 1649 | writel(0, PRCM_SEM); | ||
| 1650 | |||
| 1651 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
| 1652 | |||
| 1653 | return 0; | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | /** | ||
| 1657 | * prcmu_abb_read() - Read register value(s) from the ABB. | 2159 | * prcmu_abb_read() - Read register value(s) from the ABB. |
| 1658 | * @slave: The I2C slave address. | 2160 | * @slave: The I2C slave address. |
| 1659 | * @reg: The (start) register address. | 2161 | * @reg: The (start) register address. |
| @@ -1675,6 +2177,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
| 1675 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 2177 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
| 1676 | cpu_relax(); | 2178 | cpu_relax(); |
| 1677 | 2179 | ||
| 2180 | writeb(0, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5)); | ||
| 1678 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 2181 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
| 1679 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); | 2182 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); |
| 1680 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 2183 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
| @@ -1700,16 +2203,19 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
| 1700 | } | 2203 | } |
| 1701 | 2204 | ||
| 1702 | /** | 2205 | /** |
| 1703 | * prcmu_abb_write() - Write register value(s) to the ABB. | 2206 | * prcmu_abb_write_masked() - Write masked register value(s) to the ABB. |
| 1704 | * @slave: The I2C slave address. | 2207 | * @slave: The I2C slave address. |
| 1705 | * @reg: The (start) register address. | 2208 | * @reg: The (start) register address. |
| 1706 | * @value: The value(s) to write. | 2209 | * @value: The value(s) to write. |
| 2210 | * @mask: The mask(s) to use. | ||
| 1707 | * @size: The number of registers to write. | 2211 | * @size: The number of registers to write. |
| 1708 | * | 2212 | * |
| 1709 | * Reads register value(s) from the ABB. | 2213 | * Writes masked register value(s) to the ABB. |
| 2214 | * For each @value, only the bits set to 1 in the corresponding @mask | ||
| 2215 | * will be written. The other bits are not changed. | ||
| 1710 | * @size has to be 1 for the current firmware version. | 2216 | * @size has to be 1 for the current firmware version. |
| 1711 | */ | 2217 | */ |
| 1712 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | 2218 | int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) |
| 1713 | { | 2219 | { |
| 1714 | int r; | 2220 | int r; |
| 1715 | 2221 | ||
| @@ -1721,6 +2227,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
| 1721 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 2227 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
| 1722 | cpu_relax(); | 2228 | cpu_relax(); |
| 1723 | 2229 | ||
| 2230 | writeb(~*mask, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5)); | ||
| 1724 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 2231 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
| 1725 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); | 2232 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); |
| 1726 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 2233 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
| @@ -1743,6 +2250,23 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
| 1743 | } | 2250 | } |
| 1744 | 2251 | ||
| 1745 | /** | 2252 | /** |
| 2253 | * prcmu_abb_write() - Write register value(s) to the ABB. | ||
| 2254 | * @slave: The I2C slave address. | ||
| 2255 | * @reg: The (start) register address. | ||
| 2256 | * @value: The value(s) to write. | ||
| 2257 | * @size: The number of registers to write. | ||
| 2258 | * | ||
| 2259 | * Writes register value(s) to the ABB. | ||
| 2260 | * @size has to be 1 for the current firmware version. | ||
| 2261 | */ | ||
| 2262 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | ||
| 2263 | { | ||
| 2264 | u8 mask = ~0; | ||
| 2265 | |||
| 2266 | return prcmu_abb_write_masked(slave, reg, value, &mask, size); | ||
| 2267 | } | ||
| 2268 | |||
| 2269 | /** | ||
| 1746 | * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem | 2270 | * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem |
| 1747 | */ | 2271 | */ |
| 1748 | void prcmu_ac_wake_req(void) | 2272 | void prcmu_ac_wake_req(void) |
| @@ -1850,9 +2374,9 @@ u16 db8500_prcmu_get_reset_code(void) | |||
| 1850 | } | 2374 | } |
| 1851 | 2375 | ||
| 1852 | /** | 2376 | /** |
| 1853 | * prcmu_reset_modem - ask the PRCMU to reset modem | 2377 | * db8500_prcmu_reset_modem - ask the PRCMU to reset modem |
| 1854 | */ | 2378 | */ |
| 1855 | void prcmu_modem_reset(void) | 2379 | void db8500_prcmu_modem_reset(void) |
| 1856 | { | 2380 | { |
| 1857 | mutex_lock(&mb1_transfer.lock); | 2381 | mutex_lock(&mb1_transfer.lock); |
| 1858 | 2382 | ||
| @@ -2099,6 +2623,26 @@ static struct irq_chip prcmu_irq_chip = { | |||
| 2099 | .irq_unmask = prcmu_irq_unmask, | 2623 | .irq_unmask = prcmu_irq_unmask, |
| 2100 | }; | 2624 | }; |
| 2101 | 2625 | ||
| 2626 | static char *fw_project_name(u8 project) | ||
| 2627 | { | ||
| 2628 | switch (project) { | ||
| 2629 | case PRCMU_FW_PROJECT_U8500: | ||
| 2630 | return "U8500"; | ||
| 2631 | case PRCMU_FW_PROJECT_U8500_C2: | ||
| 2632 | return "U8500 C2"; | ||
| 2633 | case PRCMU_FW_PROJECT_U9500: | ||
| 2634 | return "U9500"; | ||
| 2635 | case PRCMU_FW_PROJECT_U9500_C2: | ||
| 2636 | return "U9500 C2"; | ||
| 2637 | case PRCMU_FW_PROJECT_U8520: | ||
| 2638 | return "U8520"; | ||
| 2639 | case PRCMU_FW_PROJECT_U8420: | ||
| 2640 | return "U8420"; | ||
| 2641 | default: | ||
| 2642 | return "Unknown"; | ||
| 2643 | } | ||
| 2644 | } | ||
| 2645 | |||
| 2102 | void __init db8500_prcmu_early_init(void) | 2646 | void __init db8500_prcmu_early_init(void) |
| 2103 | { | 2647 | { |
| 2104 | unsigned int i; | 2648 | unsigned int i; |
| @@ -2108,11 +2652,13 @@ void __init db8500_prcmu_early_init(void) | |||
| 2108 | if (tcpm_base != NULL) { | 2652 | if (tcpm_base != NULL) { |
| 2109 | u32 version; | 2653 | u32 version; |
| 2110 | version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); | 2654 | version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); |
| 2111 | prcmu_version.project_number = version & 0xFF; | 2655 | fw_info.version.project = version & 0xFF; |
| 2112 | prcmu_version.api_version = (version >> 8) & 0xFF; | 2656 | fw_info.version.api_version = (version >> 8) & 0xFF; |
| 2113 | prcmu_version.func_version = (version >> 16) & 0xFF; | 2657 | fw_info.version.func_version = (version >> 16) & 0xFF; |
| 2114 | prcmu_version.errata = (version >> 24) & 0xFF; | 2658 | fw_info.version.errata = (version >> 24) & 0xFF; |
| 2115 | pr_info("PRCMU firmware version %d.%d.%d\n", | 2659 | fw_info.valid = true; |
| 2660 | pr_info("PRCMU firmware: %s, version %d.%d.%d\n", | ||
| 2661 | fw_project_name(fw_info.version.project), | ||
| 2116 | (version >> 8) & 0xFF, (version >> 16) & 0xFF, | 2662 | (version >> 8) & 0xFF, (version >> 16) & 0xFF, |
| 2117 | (version >> 24) & 0xFF); | 2663 | (version >> 24) & 0xFF); |
| 2118 | iounmap(tcpm_base); | 2664 | iounmap(tcpm_base); |
| @@ -2130,6 +2676,7 @@ void __init db8500_prcmu_early_init(void) | |||
| 2130 | init_completion(&mb0_transfer.ac_wake_work); | 2676 | init_completion(&mb0_transfer.ac_wake_work); |
| 2131 | mutex_init(&mb1_transfer.lock); | 2677 | mutex_init(&mb1_transfer.lock); |
| 2132 | init_completion(&mb1_transfer.work); | 2678 | init_completion(&mb1_transfer.work); |
| 2679 | mb1_transfer.ape_opp = APE_NO_CHANGE; | ||
| 2133 | mutex_init(&mb2_transfer.lock); | 2680 | mutex_init(&mb2_transfer.lock); |
| 2134 | init_completion(&mb2_transfer.work); | 2681 | init_completion(&mb2_transfer.work); |
| 2135 | spin_lock_init(&mb2_transfer.auto_pm_lock); | 2682 | spin_lock_init(&mb2_transfer.auto_pm_lock); |
| @@ -2154,7 +2701,7 @@ void __init db8500_prcmu_early_init(void) | |||
| 2154 | } | 2701 | } |
| 2155 | } | 2702 | } |
| 2156 | 2703 | ||
| 2157 | static void __init db8500_prcmu_init_clkforce(void) | 2704 | static void __init init_prcm_registers(void) |
| 2158 | { | 2705 | { |
| 2159 | u32 val; | 2706 | u32 val; |
| 2160 | 2707 | ||
| @@ -2186,19 +2733,17 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { | |||
| 2186 | REGULATOR_SUPPLY("vcore", "uart1"), | 2733 | REGULATOR_SUPPLY("vcore", "uart1"), |
| 2187 | REGULATOR_SUPPLY("vcore", "uart2"), | 2734 | REGULATOR_SUPPLY("vcore", "uart2"), |
| 2188 | REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), | 2735 | REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), |
| 2736 | REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"), | ||
| 2189 | }; | 2737 | }; |
| 2190 | 2738 | ||
| 2191 | static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { | 2739 | static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { |
| 2192 | /* CG2900 and CW1200 power to off-chip peripherals */ | ||
| 2193 | REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"), | ||
| 2194 | REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"), | ||
| 2195 | REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), | 2740 | REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), |
| 2196 | /* AV8100 regulator */ | 2741 | /* AV8100 regulator */ |
| 2197 | REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), | 2742 | REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), |
| 2198 | }; | 2743 | }; |
| 2199 | 2744 | ||
| 2200 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { | 2745 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { |
| 2201 | REGULATOR_SUPPLY("vsupply", "b2r2.0"), | 2746 | REGULATOR_SUPPLY("vsupply", "b2r2_bus"), |
| 2202 | REGULATOR_SUPPLY("vsupply", "mcde"), | 2747 | REGULATOR_SUPPLY("vsupply", "mcde"), |
| 2203 | }; | 2748 | }; |
| 2204 | 2749 | ||
| @@ -2235,6 +2780,7 @@ static struct regulator_consumer_supply db8500_esram12_consumers[] = { | |||
| 2235 | static struct regulator_consumer_supply db8500_esram34_consumers[] = { | 2780 | static struct regulator_consumer_supply db8500_esram34_consumers[] = { |
| 2236 | REGULATOR_SUPPLY("v-esram34", "mcde"), | 2781 | REGULATOR_SUPPLY("v-esram34", "mcde"), |
| 2237 | REGULATOR_SUPPLY("esram34", "cm_control"), | 2782 | REGULATOR_SUPPLY("esram34", "cm_control"), |
| 2783 | REGULATOR_SUPPLY("lcla_esram", "dma40.0"), | ||
| 2238 | }; | 2784 | }; |
| 2239 | 2785 | ||
| 2240 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | 2786 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { |
| @@ -2291,7 +2837,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
| 2291 | }, | 2837 | }, |
| 2292 | }, | 2838 | }, |
| 2293 | [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { | 2839 | [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { |
| 2294 | .supply_regulator = "db8500-vape", | 2840 | /* dependency to u8500-vape is handled outside regulator framework */ |
| 2295 | .constraints = { | 2841 | .constraints = { |
| 2296 | .name = "db8500-sva-mmdsp", | 2842 | .name = "db8500-sva-mmdsp", |
| 2297 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2843 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
| @@ -2307,7 +2853,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
| 2307 | }, | 2853 | }, |
| 2308 | }, | 2854 | }, |
| 2309 | [DB8500_REGULATOR_SWITCH_SVAPIPE] = { | 2855 | [DB8500_REGULATOR_SWITCH_SVAPIPE] = { |
| 2310 | .supply_regulator = "db8500-vape", | 2856 | /* dependency to u8500-vape is handled outside regulator framework */ |
| 2311 | .constraints = { | 2857 | .constraints = { |
| 2312 | .name = "db8500-sva-pipe", | 2858 | .name = "db8500-sva-pipe", |
| 2313 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2859 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
| @@ -2316,7 +2862,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
| 2316 | .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), | 2862 | .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), |
| 2317 | }, | 2863 | }, |
| 2318 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { | 2864 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { |
| 2319 | .supply_regulator = "db8500-vape", | 2865 | /* dependency to u8500-vape is handled outside regulator framework */ |
| 2320 | .constraints = { | 2866 | .constraints = { |
| 2321 | .name = "db8500-sia-mmdsp", | 2867 | .name = "db8500-sia-mmdsp", |
| 2322 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2868 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
| @@ -2331,7 +2877,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
| 2331 | }, | 2877 | }, |
| 2332 | }, | 2878 | }, |
| 2333 | [DB8500_REGULATOR_SWITCH_SIAPIPE] = { | 2879 | [DB8500_REGULATOR_SWITCH_SIAPIPE] = { |
| 2334 | .supply_regulator = "db8500-vape", | 2880 | /* dependency to u8500-vape is handled outside regulator framework */ |
| 2335 | .constraints = { | 2881 | .constraints = { |
| 2336 | .name = "db8500-sia-pipe", | 2882 | .name = "db8500-sia-pipe", |
| 2337 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2883 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
| @@ -2359,7 +2905,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
| 2359 | .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), | 2905 | .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), |
| 2360 | }, | 2906 | }, |
| 2361 | [DB8500_REGULATOR_SWITCH_ESRAM12] = { | 2907 | [DB8500_REGULATOR_SWITCH_ESRAM12] = { |
| 2362 | .supply_regulator = "db8500-vape", | 2908 | /* |
| 2909 | * esram12 is set in retention and supplied by Vsafe when Vape is off, | ||
| 2910 | * no need to hold Vape | ||
| 2911 | */ | ||
| 2363 | .constraints = { | 2912 | .constraints = { |
| 2364 | .name = "db8500-esram12", | 2913 | .name = "db8500-esram12", |
| 2365 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2914 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
| @@ -2374,7 +2923,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
| 2374 | }, | 2923 | }, |
| 2375 | }, | 2924 | }, |
| 2376 | [DB8500_REGULATOR_SWITCH_ESRAM34] = { | 2925 | [DB8500_REGULATOR_SWITCH_ESRAM34] = { |
| 2377 | .supply_regulator = "db8500-vape", | 2926 | /* |
| 2927 | * esram34 is set in retention and supplied by Vsafe when Vape is off, | ||
| 2928 | * no need to hold Vape | ||
| 2929 | */ | ||
| 2378 | .constraints = { | 2930 | .constraints = { |
| 2379 | .name = "db8500-esram34", | 2931 | .name = "db8500-esram34", |
| 2380 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2932 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
| @@ -2412,7 +2964,7 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev) | |||
| 2412 | if (ux500_is_svp()) | 2964 | if (ux500_is_svp()) |
| 2413 | return -ENODEV; | 2965 | return -ENODEV; |
| 2414 | 2966 | ||
| 2415 | db8500_prcmu_init_clkforce(); | 2967 | init_prcm_registers(); |
| 2416 | 2968 | ||
| 2417 | /* Clean up the mailbox interrupts after pre-kernel code. */ | 2969 | /* Clean up the mailbox interrupts after pre-kernel code. */ |
| 2418 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); | 2970 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); |
diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index ec22e9f15d32..3a0bf91d7780 100644 --- a/drivers/mfd/dbx500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h | |||
| @@ -17,41 +17,41 @@ | |||
| 17 | 17 | ||
| 18 | #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) | 18 | #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) |
| 19 | 19 | ||
| 20 | #define PRCM_SVACLK_MGT_OFF 0x008 | 20 | #define PRCM_CLK_MGT(_offset) (void __iomem *)(IO_ADDRESS(U8500_PRCMU_BASE) \ |
| 21 | #define PRCM_SIACLK_MGT_OFF 0x00C | 21 | + _offset) |
| 22 | #define PRCM_SGACLK_MGT_OFF 0x014 | 22 | #define PRCM_ACLK_MGT PRCM_CLK_MGT(0x004) |
| 23 | #define PRCM_UARTCLK_MGT_OFF 0x018 | 23 | #define PRCM_SVACLK_MGT PRCM_CLK_MGT(0x008) |
| 24 | #define PRCM_MSP02CLK_MGT_OFF 0x01C | 24 | #define PRCM_SIACLK_MGT PRCM_CLK_MGT(0x00C) |
| 25 | #define PRCM_I2CCLK_MGT_OFF 0x020 | 25 | #define PRCM_SGACLK_MGT PRCM_CLK_MGT(0x014) |
| 26 | #define PRCM_SDMMCCLK_MGT_OFF 0x024 | 26 | #define PRCM_UARTCLK_MGT PRCM_CLK_MGT(0x018) |
| 27 | #define PRCM_SLIMCLK_MGT_OFF 0x028 | 27 | #define PRCM_MSP02CLK_MGT PRCM_CLK_MGT(0x01C) |
| 28 | #define PRCM_PER1CLK_MGT_OFF 0x02C | 28 | #define PRCM_I2CCLK_MGT PRCM_CLK_MGT(0x020) |
| 29 | #define PRCM_PER2CLK_MGT_OFF 0x030 | 29 | #define PRCM_SDMMCCLK_MGT PRCM_CLK_MGT(0x024) |
| 30 | #define PRCM_PER3CLK_MGT_OFF 0x034 | 30 | #define PRCM_SLIMCLK_MGT PRCM_CLK_MGT(0x028) |
| 31 | #define PRCM_PER5CLK_MGT_OFF 0x038 | 31 | #define PRCM_PER1CLK_MGT PRCM_CLK_MGT(0x02C) |
| 32 | #define PRCM_PER6CLK_MGT_OFF 0x03C | 32 | #define PRCM_PER2CLK_MGT PRCM_CLK_MGT(0x030) |
| 33 | #define PRCM_PER7CLK_MGT_OFF 0x040 | 33 | #define PRCM_PER3CLK_MGT PRCM_CLK_MGT(0x034) |
| 34 | #define PRCM_PWMCLK_MGT_OFF 0x044 /* for DB5500 */ | 34 | #define PRCM_PER5CLK_MGT PRCM_CLK_MGT(0x038) |
| 35 | #define PRCM_IRDACLK_MGT_OFF 0x048 /* for DB5500 */ | 35 | #define PRCM_PER6CLK_MGT PRCM_CLK_MGT(0x03C) |
| 36 | #define PRCM_IRRCCLK_MGT_OFF 0x04C /* for DB5500 */ | 36 | #define PRCM_PER7CLK_MGT PRCM_CLK_MGT(0x040) |
| 37 | #define PRCM_LCDCLK_MGT_OFF 0x044 | 37 | #define PRCM_LCDCLK_MGT PRCM_CLK_MGT(0x044) |
| 38 | #define PRCM_BMLCLK_MGT_OFF 0x04C | 38 | #define PRCM_BMLCLK_MGT PRCM_CLK_MGT(0x04C) |
| 39 | #define PRCM_HSITXCLK_MGT_OFF 0x050 | 39 | #define PRCM_HSITXCLK_MGT PRCM_CLK_MGT(0x050) |
| 40 | #define PRCM_HSIRXCLK_MGT_OFF 0x054 | 40 | #define PRCM_HSIRXCLK_MGT PRCM_CLK_MGT(0x054) |
| 41 | #define PRCM_HDMICLK_MGT_OFF 0x058 | 41 | #define PRCM_HDMICLK_MGT PRCM_CLK_MGT(0x058) |
| 42 | #define PRCM_APEATCLK_MGT_OFF 0x05C | 42 | #define PRCM_APEATCLK_MGT PRCM_CLK_MGT(0x05C) |
| 43 | #define PRCM_APETRACECLK_MGT_OFF 0x060 | 43 | #define PRCM_APETRACECLK_MGT PRCM_CLK_MGT(0x060) |
| 44 | #define PRCM_MCDECLK_MGT_OFF 0x064 | 44 | #define PRCM_MCDECLK_MGT PRCM_CLK_MGT(0x064) |
| 45 | #define PRCM_IPI2CCLK_MGT_OFF 0x068 | 45 | #define PRCM_IPI2CCLK_MGT PRCM_CLK_MGT(0x068) |
| 46 | #define PRCM_DSIALTCLK_MGT_OFF 0x06C | 46 | #define PRCM_DSIALTCLK_MGT PRCM_CLK_MGT(0x06C) |
| 47 | #define PRCM_DMACLK_MGT_OFF 0x074 | 47 | #define PRCM_DMACLK_MGT PRCM_CLK_MGT(0x074) |
| 48 | #define PRCM_B2R2CLK_MGT_OFF 0x078 | 48 | #define PRCM_B2R2CLK_MGT PRCM_CLK_MGT(0x078) |
| 49 | #define PRCM_TVCLK_MGT_OFF 0x07C | 49 | #define PRCM_TVCLK_MGT PRCM_CLK_MGT(0x07C) |
| 50 | #define PRCM_UNIPROCLK_MGT_OFF 0x278 | 50 | #define PRCM_UNIPROCLK_MGT PRCM_CLK_MGT(0x278) |
| 51 | #define PRCM_SSPCLK_MGT_OFF 0x280 | 51 | #define PRCM_SSPCLK_MGT PRCM_CLK_MGT(0x280) |
| 52 | #define PRCM_RNGCLK_MGT_OFF 0x284 | 52 | #define PRCM_RNGCLK_MGT PRCM_CLK_MGT(0x284) |
| 53 | #define PRCM_UICCCLK_MGT_OFF 0x27C | 53 | #define PRCM_UICCCLK_MGT PRCM_CLK_MGT(0x27C) |
| 54 | #define PRCM_MSP1CLK_MGT_OFF 0x288 | 54 | #define PRCM_MSP1CLK_MGT PRCM_CLK_MGT(0x288) |
| 55 | 55 | ||
| 56 | #define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) | 56 | #define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) |
| 57 | #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f | 57 | #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f |
| @@ -79,6 +79,8 @@ | |||
| 79 | 79 | ||
| 80 | /* ARM WFI Standby signal register */ | 80 | /* ARM WFI Standby signal register */ |
| 81 | #define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) | 81 | #define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) |
| 82 | #define PRCM_ARM_WFI_STANDBY_WFI0 0x08 | ||
| 83 | #define PRCM_ARM_WFI_STANDBY_WFI1 0x10 | ||
| 82 | #define PRCM_IOCR (_PRCMU_BASE + 0x310) | 84 | #define PRCM_IOCR (_PRCMU_BASE + 0x310) |
| 83 | #define PRCM_IOCR_IOFORCE 0x1 | 85 | #define PRCM_IOCR_IOFORCE 0x1 |
| 84 | 86 | ||
| @@ -131,20 +133,58 @@ | |||
| 131 | #define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420) | 133 | #define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420) |
| 132 | #define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424) | 134 | #define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424) |
| 133 | 135 | ||
| 136 | #define PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP BIT(11) | ||
| 137 | #define PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI BIT(22) | ||
| 138 | |||
| 134 | /* PRCMU clock/PLL/reset registers */ | 139 | /* PRCMU clock/PLL/reset registers */ |
| 140 | #define PRCM_PLLSOC0_FREQ (_PRCMU_BASE + 0x080) | ||
| 141 | #define PRCM_PLLSOC1_FREQ (_PRCMU_BASE + 0x084) | ||
| 142 | #define PRCM_PLLDDR_FREQ (_PRCMU_BASE + 0x08C) | ||
| 143 | #define PRCM_PLL_FREQ_D_SHIFT 0 | ||
| 144 | #define PRCM_PLL_FREQ_D_MASK BITS(0, 7) | ||
| 145 | #define PRCM_PLL_FREQ_N_SHIFT 8 | ||
| 146 | #define PRCM_PLL_FREQ_N_MASK BITS(8, 13) | ||
| 147 | #define PRCM_PLL_FREQ_R_SHIFT 16 | ||
| 148 | #define PRCM_PLL_FREQ_R_MASK BITS(16, 18) | ||
| 149 | #define PRCM_PLL_FREQ_SELDIV2 BIT(24) | ||
| 150 | #define PRCM_PLL_FREQ_DIV2EN BIT(25) | ||
| 151 | |||
| 135 | #define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) | 152 | #define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) |
| 136 | #define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) | 153 | #define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) |
| 137 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) | 154 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) |
| 138 | #define PRCM_LCDCLK_MGT (_PRCMU_BASE + PRCM_LCDCLK_MGT_OFF) | ||
| 139 | #define PRCM_MCDECLK_MGT (_PRCMU_BASE + PRCM_MCDECLK_MGT_OFF) | ||
| 140 | #define PRCM_HDMICLK_MGT (_PRCMU_BASE + PRCM_HDMICLK_MGT_OFF) | ||
| 141 | #define PRCM_TVCLK_MGT (_PRCMU_BASE + PRCM_TVCLK_MGT_OFF) | ||
| 142 | #define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) | 155 | #define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) |
| 143 | #define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) | 156 | #define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) |
| 144 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) | 157 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) |
| 145 | #define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) | 158 | #define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) |
| 146 | #define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) | 159 | #define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) |
| 147 | 160 | ||
| 161 | #define PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE BIT(0) | ||
| 162 | |||
| 163 | #define PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 BIT(0) | ||
| 164 | #define PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3 BIT(1) | ||
| 165 | |||
| 166 | #define PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT 0 | ||
| 167 | #define PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK BITS(0, 2) | ||
| 168 | #define PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT 8 | ||
| 169 | #define PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK BITS(8, 10) | ||
| 170 | |||
| 171 | #define PRCM_DSI_PLLOUT_SEL_OFF 0 | ||
| 172 | #define PRCM_DSI_PLLOUT_SEL_PHI 1 | ||
| 173 | #define PRCM_DSI_PLLOUT_SEL_PHI_2 2 | ||
| 174 | #define PRCM_DSI_PLLOUT_SEL_PHI_4 3 | ||
| 175 | |||
| 176 | #define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT 0 | ||
| 177 | #define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK BITS(0, 7) | ||
| 178 | #define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT 8 | ||
| 179 | #define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK BITS(8, 15) | ||
| 180 | #define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT 16 | ||
| 181 | #define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK BITS(16, 23) | ||
| 182 | #define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN BIT(24) | ||
| 183 | #define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN BIT(25) | ||
| 184 | #define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN BIT(26) | ||
| 185 | |||
| 186 | #define PRCM_APE_RESETN_DSIPLL_RESETN BIT(14) | ||
| 187 | |||
| 148 | #define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC) | 188 | #define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC) |
| 149 | #define PRCM_CLKOCR_CLKOUT0_REF_CLK (1 << 0) | 189 | #define PRCM_CLKOCR_CLKOUT0_REF_CLK (1 << 0) |
| 150 | #define PRCM_CLKOCR_CLKOUT0_MASK BITS(0, 13) | 190 | #define PRCM_CLKOCR_CLKOUT0_MASK BITS(0, 13) |
| @@ -183,9 +223,15 @@ | |||
| 183 | #define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) | 223 | #define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) |
| 184 | #define PRCM_CLKOCR_CLK1TYPE BIT(28) | 224 | #define PRCM_CLKOCR_CLK1TYPE BIT(28) |
| 185 | 225 | ||
| 186 | #define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) | 226 | #define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) |
| 187 | #define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) | 227 | #define PRCM_CLK_MGT_CLKPLLSW_SOC0 BIT(5) |
| 188 | #define PRCM_CLK_MGT_CLKEN BIT(8) | 228 | #define PRCM_CLK_MGT_CLKPLLSW_SOC1 BIT(6) |
| 229 | #define PRCM_CLK_MGT_CLKPLLSW_DDR BIT(7) | ||
| 230 | #define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) | ||
| 231 | #define PRCM_CLK_MGT_CLKEN BIT(8) | ||
| 232 | #define PRCM_CLK_MGT_CLK38 BIT(9) | ||
| 233 | #define PRCM_CLK_MGT_CLK38DIV BIT(11) | ||
| 234 | #define PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN BIT(12) | ||
| 189 | 235 | ||
| 190 | /* GPIOCR register */ | 236 | /* GPIOCR register */ |
| 191 | #define PRCM_GPIOCR_SPI2_SELECT BIT(23) | 237 | #define PRCM_GPIOCR_SPI2_SELECT BIT(23) |
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 7122386b4e3c..9fd4f63c45cc 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c | |||
| @@ -560,6 +560,8 @@ EXPORT_SYMBOL(mc13xxx_get_flags); | |||
| 560 | 560 | ||
| 561 | #define MC13XXX_ADC1_CHAN0_SHIFT 5 | 561 | #define MC13XXX_ADC1_CHAN0_SHIFT 5 |
| 562 | #define MC13XXX_ADC1_CHAN1_SHIFT 8 | 562 | #define MC13XXX_ADC1_CHAN1_SHIFT 8 |
| 563 | #define MC13783_ADC1_ATO_SHIFT 11 | ||
| 564 | #define MC13783_ADC1_ATOX (1 << 19) | ||
| 563 | 565 | ||
| 564 | struct mc13xxx_adcdone_data { | 566 | struct mc13xxx_adcdone_data { |
| 565 | struct mc13xxx *mc13xxx; | 567 | struct mc13xxx *mc13xxx; |
| @@ -580,7 +582,8 @@ static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data) | |||
| 580 | #define MC13XXX_ADC_WORKING (1 << 0) | 582 | #define MC13XXX_ADC_WORKING (1 << 0) |
| 581 | 583 | ||
| 582 | int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode, | 584 | int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode, |
| 583 | unsigned int channel, unsigned int *sample) | 585 | unsigned int channel, u8 ato, bool atox, |
| 586 | unsigned int *sample) | ||
| 584 | { | 587 | { |
| 585 | u32 adc0, adc1, old_adc0; | 588 | u32 adc0, adc1, old_adc0; |
| 586 | int i, ret; | 589 | int i, ret; |
| @@ -631,6 +634,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode, | |||
| 631 | return -EINVAL; | 634 | return -EINVAL; |
| 632 | } | 635 | } |
| 633 | 636 | ||
| 637 | adc1 |= ato << MC13783_ADC1_ATO_SHIFT; | ||
| 638 | if (atox) | ||
| 639 | adc1 |= MC13783_ADC1_ATOX; | ||
| 634 | dev_dbg(&mc13xxx->spidev->dev, "%s: request irq\n", __func__); | 640 | dev_dbg(&mc13xxx->spidev->dev, "%s: request irq\n", __func__); |
| 635 | mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE, | 641 | mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE, |
| 636 | mc13xxx_handler_adcdone, __func__, &adcdone_data); | 642 | mc13xxx_handler_adcdone, __func__, &adcdone_data); |
| @@ -813,7 +819,8 @@ err_revision: | |||
| 813 | mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); | 819 | mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); |
| 814 | 820 | ||
| 815 | if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN) | 821 | if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN) |
| 816 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); | 822 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-ts", |
| 823 | &pdata->touch, sizeof(pdata->touch)); | ||
| 817 | 824 | ||
| 818 | if (pdata) { | 825 | if (pdata) { |
| 819 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", | 826 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 411f523d4878..ffc3d48676ae 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
| @@ -162,7 +162,7 @@ int mfd_add_devices(struct device *parent, int id, | |||
| 162 | atomic_t *cnts; | 162 | atomic_t *cnts; |
| 163 | 163 | ||
| 164 | /* initialize reference counting for all cells */ | 164 | /* initialize reference counting for all cells */ |
| 165 | cnts = kcalloc(sizeof(*cnts), n_devs, GFP_KERNEL); | 165 | cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL); |
| 166 | if (!cnts) | 166 | if (!cnts) |
| 167 | return -ENOMEM; | 167 | return -ENOMEM; |
| 168 | 168 | ||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 68ac2c55d5ae..95a2e546a489 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c | |||
| @@ -170,7 +170,7 @@ struct usbhs_hcd_omap { | |||
| 170 | /*-------------------------------------------------------------------------*/ | 170 | /*-------------------------------------------------------------------------*/ |
| 171 | 171 | ||
| 172 | const char usbhs_driver_name[] = USBHS_DRIVER_NAME; | 172 | const char usbhs_driver_name[] = USBHS_DRIVER_NAME; |
| 173 | static u64 usbhs_dmamask = ~(u32)0; | 173 | static u64 usbhs_dmamask = DMA_BIT_MASK(32); |
| 174 | 174 | ||
| 175 | /*-------------------------------------------------------------------------*/ | 175 | /*-------------------------------------------------------------------------*/ |
| 176 | 176 | ||
| @@ -223,7 +223,7 @@ static struct platform_device *omap_usbhs_alloc_child(const char *name, | |||
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | child->dev.dma_mask = &usbhs_dmamask; | 225 | child->dev.dma_mask = &usbhs_dmamask; |
| 226 | child->dev.coherent_dma_mask = 0xffffffff; | 226 | dma_set_coherent_mask(&child->dev, DMA_BIT_MASK(32)); |
| 227 | child->dev.parent = dev; | 227 | child->dev.parent = dev; |
| 228 | 228 | ||
| 229 | ret = platform_device_add(child); | 229 | ret = platform_device_add(child); |
| @@ -799,14 +799,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) | |||
| 799 | 799 | ||
| 800 | platform_set_drvdata(pdev, omap); | 800 | platform_set_drvdata(pdev, omap); |
| 801 | 801 | ||
| 802 | omap_usbhs_init(dev); | ||
| 802 | ret = omap_usbhs_alloc_children(pdev); | 803 | ret = omap_usbhs_alloc_children(pdev); |
| 803 | if (ret) { | 804 | if (ret) { |
| 804 | dev_err(dev, "omap_usbhs_alloc_children failed\n"); | 805 | dev_err(dev, "omap_usbhs_alloc_children failed\n"); |
| 805 | goto err_alloc; | 806 | goto err_alloc; |
| 806 | } | 807 | } |
| 807 | 808 | ||
| 808 | omap_usbhs_init(dev); | ||
| 809 | |||
| 810 | goto end_probe; | 809 | goto end_probe; |
| 811 | 810 | ||
| 812 | err_alloc: | 811 | err_alloc: |
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index ff1a7e741ecd..189c2f07b83f 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
| @@ -46,13 +46,7 @@ EXPORT_SYMBOL_GPL(pcf50633_read_block); | |||
| 46 | int pcf50633_write_block(struct pcf50633 *pcf , u8 reg, | 46 | int pcf50633_write_block(struct pcf50633 *pcf , u8 reg, |
| 47 | int nr_regs, u8 *data) | 47 | int nr_regs, u8 *data) |
| 48 | { | 48 | { |
| 49 | int ret; | 49 | return regmap_raw_write(pcf->regmap, reg, data, nr_regs); |
| 50 | |||
| 51 | ret = regmap_raw_write(pcf->regmap, reg, data, nr_regs); | ||
| 52 | if (ret != 0) | ||
| 53 | return ret; | ||
| 54 | |||
| 55 | return nr_regs; | ||
| 56 | } | 50 | } |
| 57 | EXPORT_SYMBOL_GPL(pcf50633_write_block); | 51 | EXPORT_SYMBOL_GPL(pcf50633_write_block); |
| 58 | 52 | ||
diff --git a/drivers/mfd/pcf50633-gpio.c b/drivers/mfd/pcf50633-gpio.c index 9ab19a8f669d..d02ddf2ebd63 100644 --- a/drivers/mfd/pcf50633-gpio.c +++ b/drivers/mfd/pcf50633-gpio.c | |||
| @@ -19,32 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/mfd/pcf50633/core.h> | 20 | #include <linux/mfd/pcf50633/core.h> |
| 21 | #include <linux/mfd/pcf50633/gpio.h> | 21 | #include <linux/mfd/pcf50633/gpio.h> |
| 22 | 22 | #include <linux/mfd/pcf50633/pmic.h> | |
| 23 | enum pcf50633_regulator_id { | ||
| 24 | PCF50633_REGULATOR_AUTO, | ||
| 25 | PCF50633_REGULATOR_DOWN1, | ||
| 26 | PCF50633_REGULATOR_DOWN2, | ||
| 27 | PCF50633_REGULATOR_LDO1, | ||
| 28 | PCF50633_REGULATOR_LDO2, | ||
| 29 | PCF50633_REGULATOR_LDO3, | ||
| 30 | PCF50633_REGULATOR_LDO4, | ||
| 31 | PCF50633_REGULATOR_LDO5, | ||
| 32 | PCF50633_REGULATOR_LDO6, | ||
| 33 | PCF50633_REGULATOR_HCLDO, | ||
| 34 | PCF50633_REGULATOR_MEMLDO, | ||
| 35 | }; | ||
| 36 | |||
| 37 | #define PCF50633_REG_AUTOOUT 0x1a | ||
| 38 | #define PCF50633_REG_DOWN1OUT 0x1e | ||
| 39 | #define PCF50633_REG_DOWN2OUT 0x22 | ||
| 40 | #define PCF50633_REG_MEMLDOOUT 0x26 | ||
| 41 | #define PCF50633_REG_LDO1OUT 0x2d | ||
| 42 | #define PCF50633_REG_LDO2OUT 0x2f | ||
| 43 | #define PCF50633_REG_LDO3OUT 0x31 | ||
| 44 | #define PCF50633_REG_LDO4OUT 0x33 | ||
| 45 | #define PCF50633_REG_LDO5OUT 0x35 | ||
| 46 | #define PCF50633_REG_LDO6OUT 0x37 | ||
| 47 | #define PCF50633_REG_HCLDOOUT 0x39 | ||
| 48 | 23 | ||
| 49 | static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = { | 24 | static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = { |
| 50 | [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT, | 25 | [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT, |
diff --git a/drivers/mfd/pcf50633-irq.c b/drivers/mfd/pcf50633-irq.c index 048a3b903b01..498286cbb530 100644 --- a/drivers/mfd/pcf50633-irq.c +++ b/drivers/mfd/pcf50633-irq.c | |||
| @@ -19,12 +19,7 @@ | |||
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | 20 | ||
| 21 | #include <linux/mfd/pcf50633/core.h> | 21 | #include <linux/mfd/pcf50633/core.h> |
| 22 | 22 | #include <linux/mfd/pcf50633/mbc.h> | |
| 23 | /* Two MBCS registers used during cold start */ | ||
| 24 | #define PCF50633_REG_MBCS1 0x4b | ||
| 25 | #define PCF50633_REG_MBCS2 0x4c | ||
| 26 | #define PCF50633_MBCS1_USBPRES 0x01 | ||
| 27 | #define PCF50633_MBCS1_ADAPTPRES 0x01 | ||
| 28 | 23 | ||
| 29 | int pcf50633_register_irq(struct pcf50633 *pcf, int irq, | 24 | int pcf50633_register_irq(struct pcf50633 *pcf, int irq, |
| 30 | void (*handler) (int, void *), void *data) | 25 | void (*handler) (int, void *), void *data) |
diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c new file mode 100644 index 000000000000..fa6f80fad5f1 --- /dev/null +++ b/drivers/mfd/rc5t583-irq.c | |||
| @@ -0,0 +1,408 @@ | |||
| 1 | /* | ||
| 2 | * Interrupt driver for RICOH583 power management chip. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * Author: Laxman dewangan <ldewangan@nvidia.com> | ||
| 6 | * | ||
| 7 | * based on code | ||
| 8 | * Copyright (C) 2011 RICOH COMPANY,LTD | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms and conditions of the GNU General Public License, | ||
| 12 | * version 2, as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 17 | * more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/irq.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/i2c.h> | ||
| 27 | #include <linux/mfd/rc5t583.h> | ||
| 28 | |||
| 29 | enum int_type { | ||
| 30 | SYS_INT = 0x1, | ||
| 31 | DCDC_INT = 0x2, | ||
| 32 | RTC_INT = 0x4, | ||
| 33 | ADC_INT = 0x8, | ||
| 34 | GPIO_INT = 0x10, | ||
| 35 | }; | ||
| 36 | |||
| 37 | static int gpedge_add[] = { | ||
| 38 | RC5T583_GPIO_GPEDGE2, | ||
| 39 | RC5T583_GPIO_GPEDGE2 | ||
| 40 | }; | ||
| 41 | |||
| 42 | static int irq_en_add[] = { | ||
| 43 | RC5T583_INT_EN_SYS1, | ||
| 44 | RC5T583_INT_EN_SYS2, | ||
| 45 | RC5T583_INT_EN_DCDC, | ||
| 46 | RC5T583_INT_EN_RTC, | ||
| 47 | RC5T583_INT_EN_ADC1, | ||
| 48 | RC5T583_INT_EN_ADC2, | ||
| 49 | RC5T583_INT_EN_ADC3, | ||
| 50 | RC5T583_GPIO_EN_INT | ||
| 51 | }; | ||
| 52 | |||
| 53 | static int irq_mon_add[] = { | ||
| 54 | RC5T583_INT_MON_SYS1, | ||
| 55 | RC5T583_INT_MON_SYS2, | ||
| 56 | RC5T583_INT_MON_DCDC, | ||
| 57 | RC5T583_INT_MON_RTC, | ||
| 58 | RC5T583_INT_IR_ADCL, | ||
| 59 | RC5T583_INT_IR_ADCH, | ||
| 60 | RC5T583_INT_IR_ADCEND, | ||
| 61 | RC5T583_INT_IR_GPIOF, | ||
| 62 | RC5T583_INT_IR_GPIOR | ||
| 63 | }; | ||
| 64 | |||
| 65 | static int irq_clr_add[] = { | ||
| 66 | RC5T583_INT_IR_SYS1, | ||
| 67 | RC5T583_INT_IR_SYS2, | ||
| 68 | RC5T583_INT_IR_DCDC, | ||
| 69 | RC5T583_INT_IR_RTC, | ||
| 70 | RC5T583_INT_IR_ADCL, | ||
| 71 | RC5T583_INT_IR_ADCH, | ||
| 72 | RC5T583_INT_IR_ADCEND, | ||
| 73 | RC5T583_INT_IR_GPIOF, | ||
| 74 | RC5T583_INT_IR_GPIOR | ||
| 75 | }; | ||
| 76 | |||
| 77 | static int main_int_type[] = { | ||
| 78 | SYS_INT, | ||
| 79 | SYS_INT, | ||
| 80 | DCDC_INT, | ||
| 81 | RTC_INT, | ||
| 82 | ADC_INT, | ||
| 83 | ADC_INT, | ||
| 84 | ADC_INT, | ||
| 85 | GPIO_INT, | ||
| 86 | GPIO_INT, | ||
| 87 | }; | ||
| 88 | |||
| 89 | struct rc5t583_irq_data { | ||
| 90 | u8 int_type; | ||
| 91 | u8 master_bit; | ||
| 92 | u8 int_en_bit; | ||
| 93 | u8 mask_reg_index; | ||
| 94 | int grp_index; | ||
| 95 | }; | ||
| 96 | |||
| 97 | #define RC5T583_IRQ(_int_type, _master_bit, _grp_index, \ | ||
| 98 | _int_bit, _mask_ind) \ | ||
| 99 | { \ | ||
| 100 | .int_type = _int_type, \ | ||
| 101 | .master_bit = _master_bit, \ | ||
| 102 | .grp_index = _grp_index, \ | ||
| 103 | .int_en_bit = _int_bit, \ | ||
| 104 | .mask_reg_index = _mask_ind, \ | ||
| 105 | } | ||
| 106 | |||
| 107 | static const struct rc5t583_irq_data rc5t583_irqs[RC5T583_MAX_IRQS] = { | ||
| 108 | [RC5T583_IRQ_ONKEY] = RC5T583_IRQ(SYS_INT, 0, 0, 0, 0), | ||
| 109 | [RC5T583_IRQ_ACOK] = RC5T583_IRQ(SYS_INT, 0, 1, 1, 0), | ||
| 110 | [RC5T583_IRQ_LIDOPEN] = RC5T583_IRQ(SYS_INT, 0, 2, 2, 0), | ||
| 111 | [RC5T583_IRQ_PREOT] = RC5T583_IRQ(SYS_INT, 0, 3, 3, 0), | ||
| 112 | [RC5T583_IRQ_CLKSTP] = RC5T583_IRQ(SYS_INT, 0, 4, 4, 0), | ||
| 113 | [RC5T583_IRQ_ONKEY_OFF] = RC5T583_IRQ(SYS_INT, 0, 5, 5, 0), | ||
| 114 | [RC5T583_IRQ_WD] = RC5T583_IRQ(SYS_INT, 0, 7, 7, 0), | ||
| 115 | [RC5T583_IRQ_EN_PWRREQ1] = RC5T583_IRQ(SYS_INT, 0, 8, 0, 1), | ||
| 116 | [RC5T583_IRQ_EN_PWRREQ2] = RC5T583_IRQ(SYS_INT, 0, 9, 1, 1), | ||
| 117 | [RC5T583_IRQ_PRE_VINDET] = RC5T583_IRQ(SYS_INT, 0, 10, 2, 1), | ||
| 118 | |||
| 119 | [RC5T583_IRQ_DC0LIM] = RC5T583_IRQ(DCDC_INT, 1, 0, 0, 2), | ||
| 120 | [RC5T583_IRQ_DC1LIM] = RC5T583_IRQ(DCDC_INT, 1, 1, 1, 2), | ||
| 121 | [RC5T583_IRQ_DC2LIM] = RC5T583_IRQ(DCDC_INT, 1, 2, 2, 2), | ||
| 122 | [RC5T583_IRQ_DC3LIM] = RC5T583_IRQ(DCDC_INT, 1, 3, 3, 2), | ||
| 123 | |||
| 124 | [RC5T583_IRQ_CTC] = RC5T583_IRQ(RTC_INT, 2, 0, 0, 3), | ||
| 125 | [RC5T583_IRQ_YALE] = RC5T583_IRQ(RTC_INT, 2, 5, 5, 3), | ||
| 126 | [RC5T583_IRQ_DALE] = RC5T583_IRQ(RTC_INT, 2, 6, 6, 3), | ||
| 127 | [RC5T583_IRQ_WALE] = RC5T583_IRQ(RTC_INT, 2, 7, 7, 3), | ||
| 128 | |||
| 129 | [RC5T583_IRQ_AIN1L] = RC5T583_IRQ(ADC_INT, 3, 0, 0, 4), | ||
| 130 | [RC5T583_IRQ_AIN2L] = RC5T583_IRQ(ADC_INT, 3, 1, 1, 4), | ||
| 131 | [RC5T583_IRQ_AIN3L] = RC5T583_IRQ(ADC_INT, 3, 2, 2, 4), | ||
| 132 | [RC5T583_IRQ_VBATL] = RC5T583_IRQ(ADC_INT, 3, 3, 3, 4), | ||
| 133 | [RC5T583_IRQ_VIN3L] = RC5T583_IRQ(ADC_INT, 3, 4, 4, 4), | ||
| 134 | [RC5T583_IRQ_VIN8L] = RC5T583_IRQ(ADC_INT, 3, 5, 5, 4), | ||
| 135 | [RC5T583_IRQ_AIN1H] = RC5T583_IRQ(ADC_INT, 3, 6, 0, 5), | ||
| 136 | [RC5T583_IRQ_AIN2H] = RC5T583_IRQ(ADC_INT, 3, 7, 1, 5), | ||
| 137 | [RC5T583_IRQ_AIN3H] = RC5T583_IRQ(ADC_INT, 3, 8, 2, 5), | ||
| 138 | [RC5T583_IRQ_VBATH] = RC5T583_IRQ(ADC_INT, 3, 9, 3, 5), | ||
| 139 | [RC5T583_IRQ_VIN3H] = RC5T583_IRQ(ADC_INT, 3, 10, 4, 5), | ||
| 140 | [RC5T583_IRQ_VIN8H] = RC5T583_IRQ(ADC_INT, 3, 11, 5, 5), | ||
| 141 | [RC5T583_IRQ_ADCEND] = RC5T583_IRQ(ADC_INT, 3, 12, 0, 6), | ||
| 142 | |||
| 143 | [RC5T583_IRQ_GPIO0] = RC5T583_IRQ(GPIO_INT, 4, 0, 0, 7), | ||
| 144 | [RC5T583_IRQ_GPIO1] = RC5T583_IRQ(GPIO_INT, 4, 1, 1, 7), | ||
| 145 | [RC5T583_IRQ_GPIO2] = RC5T583_IRQ(GPIO_INT, 4, 2, 2, 7), | ||
| 146 | [RC5T583_IRQ_GPIO3] = RC5T583_IRQ(GPIO_INT, 4, 3, 3, 7), | ||
| 147 | [RC5T583_IRQ_GPIO4] = RC5T583_IRQ(GPIO_INT, 4, 4, 4, 7), | ||
| 148 | [RC5T583_IRQ_GPIO5] = RC5T583_IRQ(GPIO_INT, 4, 5, 5, 7), | ||
| 149 | [RC5T583_IRQ_GPIO6] = RC5T583_IRQ(GPIO_INT, 4, 6, 6, 7), | ||
| 150 | [RC5T583_IRQ_GPIO7] = RC5T583_IRQ(GPIO_INT, 4, 7, 7, 7), | ||
| 151 | }; | ||
| 152 | |||
| 153 | static void rc5t583_irq_lock(struct irq_data *irq_data) | ||
| 154 | { | ||
| 155 | struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data); | ||
| 156 | mutex_lock(&rc5t583->irq_lock); | ||
| 157 | } | ||
| 158 | |||
| 159 | static void rc5t583_irq_unmask(struct irq_data *irq_data) | ||
| 160 | { | ||
| 161 | struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data); | ||
| 162 | unsigned int __irq = irq_data->irq - rc5t583->irq_base; | ||
| 163 | const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq]; | ||
| 164 | |||
| 165 | rc5t583->group_irq_en[data->grp_index] |= 1 << data->grp_index; | ||
| 166 | rc5t583->intc_inten_reg |= 1 << data->master_bit; | ||
| 167 | rc5t583->irq_en_reg[data->mask_reg_index] |= 1 << data->int_en_bit; | ||
| 168 | } | ||
| 169 | |||
| 170 | static void rc5t583_irq_mask(struct irq_data *irq_data) | ||
| 171 | { | ||
| 172 | struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data); | ||
| 173 | unsigned int __irq = irq_data->irq - rc5t583->irq_base; | ||
| 174 | const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq]; | ||
| 175 | |||
| 176 | rc5t583->group_irq_en[data->grp_index] &= ~(1 << data->grp_index); | ||
| 177 | if (!rc5t583->group_irq_en[data->grp_index]) | ||
| 178 | rc5t583->intc_inten_reg &= ~(1 << data->master_bit); | ||
| 179 | |||
| 180 | rc5t583->irq_en_reg[data->mask_reg_index] &= ~(1 << data->int_en_bit); | ||
| 181 | } | ||
| 182 | |||
| 183 | static int rc5t583_irq_set_type(struct irq_data *irq_data, unsigned int type) | ||
| 184 | { | ||
| 185 | struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data); | ||
| 186 | unsigned int __irq = irq_data->irq - rc5t583->irq_base; | ||
| 187 | const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq]; | ||
| 188 | int val = 0; | ||
| 189 | int gpedge_index; | ||
| 190 | int gpedge_bit_pos; | ||
| 191 | |||
| 192 | /* Supporting only trigger level inetrrupt */ | ||
| 193 | if ((data->int_type & GPIO_INT) && (type & IRQ_TYPE_EDGE_BOTH)) { | ||
| 194 | gpedge_index = data->int_en_bit / 4; | ||
| 195 | gpedge_bit_pos = data->int_en_bit % 4; | ||
| 196 | |||
| 197 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
| 198 | val |= 0x2; | ||
| 199 | |||
| 200 | if (type & IRQ_TYPE_EDGE_RISING) | ||
| 201 | val |= 0x1; | ||
| 202 | |||
| 203 | rc5t583->gpedge_reg[gpedge_index] &= ~(3 << gpedge_bit_pos); | ||
| 204 | rc5t583->gpedge_reg[gpedge_index] |= (val << gpedge_bit_pos); | ||
| 205 | rc5t583_irq_unmask(irq_data); | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | return -EINVAL; | ||
| 209 | } | ||
| 210 | |||
| 211 | static void rc5t583_irq_sync_unlock(struct irq_data *irq_data) | ||
| 212 | { | ||
| 213 | struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data); | ||
| 214 | int i; | ||
| 215 | int ret; | ||
| 216 | |||
| 217 | for (i = 0; i < ARRAY_SIZE(rc5t583->gpedge_reg); i++) { | ||
| 218 | ret = rc5t583_write(rc5t583->dev, gpedge_add[i], | ||
| 219 | rc5t583->gpedge_reg[i]); | ||
| 220 | if (ret < 0) | ||
| 221 | dev_warn(rc5t583->dev, | ||
| 222 | "Error in writing reg 0x%02x error: %d\n", | ||
| 223 | gpedge_add[i], ret); | ||
| 224 | } | ||
| 225 | |||
| 226 | for (i = 0; i < ARRAY_SIZE(rc5t583->irq_en_reg); i++) { | ||
| 227 | ret = rc5t583_write(rc5t583->dev, irq_en_add[i], | ||
| 228 | rc5t583->irq_en_reg[i]); | ||
| 229 | if (ret < 0) | ||
| 230 | dev_warn(rc5t583->dev, | ||
| 231 | "Error in writing reg 0x%02x error: %d\n", | ||
| 232 | irq_en_add[i], ret); | ||
| 233 | } | ||
| 234 | |||
| 235 | ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN, | ||
| 236 | rc5t583->intc_inten_reg); | ||
| 237 | if (ret < 0) | ||
| 238 | dev_warn(rc5t583->dev, | ||
| 239 | "Error in writing reg 0x%02x error: %d\n", | ||
| 240 | RC5T583_INTC_INTEN, ret); | ||
| 241 | |||
| 242 | mutex_unlock(&rc5t583->irq_lock); | ||
| 243 | } | ||
| 244 | #ifdef CONFIG_PM_SLEEP | ||
| 245 | static int rc5t583_irq_set_wake(struct irq_data *irq_data, unsigned int on) | ||
| 246 | { | ||
| 247 | struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data); | ||
| 248 | return irq_set_irq_wake(rc5t583->chip_irq, on); | ||
| 249 | } | ||
| 250 | #else | ||
| 251 | #define rc5t583_irq_set_wake NULL | ||
| 252 | #endif | ||
| 253 | |||
| 254 | static irqreturn_t rc5t583_irq(int irq, void *data) | ||
| 255 | { | ||
| 256 | struct rc5t583 *rc5t583 = data; | ||
| 257 | uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS]; | ||
| 258 | uint8_t master_int; | ||
| 259 | int i; | ||
| 260 | int ret; | ||
| 261 | unsigned int rtc_int_sts = 0; | ||
| 262 | |||
| 263 | /* Clear the status */ | ||
| 264 | for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++) | ||
| 265 | int_sts[i] = 0; | ||
| 266 | |||
| 267 | ret = rc5t583_read(rc5t583->dev, RC5T583_INTC_INTMON, &master_int); | ||
| 268 | if (ret < 0) { | ||
| 269 | dev_err(rc5t583->dev, | ||
| 270 | "Error in reading reg 0x%02x error: %d\n", | ||
| 271 | RC5T583_INTC_INTMON, ret); | ||
| 272 | return IRQ_HANDLED; | ||
| 273 | } | ||
| 274 | |||
| 275 | for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; ++i) { | ||
| 276 | if (!(master_int & main_int_type[i])) | ||
| 277 | continue; | ||
| 278 | |||
| 279 | ret = rc5t583_read(rc5t583->dev, irq_mon_add[i], &int_sts[i]); | ||
| 280 | if (ret < 0) { | ||
| 281 | dev_warn(rc5t583->dev, | ||
| 282 | "Error in reading reg 0x%02x error: %d\n", | ||
| 283 | irq_mon_add[i], ret); | ||
| 284 | int_sts[i] = 0; | ||
| 285 | continue; | ||
| 286 | } | ||
| 287 | |||
| 288 | if (main_int_type[i] & RTC_INT) { | ||
| 289 | rtc_int_sts = 0; | ||
| 290 | if (int_sts[i] & 0x1) | ||
| 291 | rtc_int_sts |= BIT(6); | ||
| 292 | if (int_sts[i] & 0x2) | ||
| 293 | rtc_int_sts |= BIT(7); | ||
| 294 | if (int_sts[i] & 0x4) | ||
| 295 | rtc_int_sts |= BIT(0); | ||
| 296 | if (int_sts[i] & 0x8) | ||
| 297 | rtc_int_sts |= BIT(5); | ||
| 298 | } | ||
| 299 | |||
| 300 | ret = rc5t583_write(rc5t583->dev, irq_clr_add[i], | ||
| 301 | ~int_sts[i]); | ||
| 302 | if (ret < 0) | ||
| 303 | dev_warn(rc5t583->dev, | ||
| 304 | "Error in reading reg 0x%02x error: %d\n", | ||
| 305 | irq_clr_add[i], ret); | ||
| 306 | |||
| 307 | if (main_int_type[i] & RTC_INT) | ||
| 308 | int_sts[i] = rtc_int_sts; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* Merge gpio interrupts for rising and falling case*/ | ||
| 312 | int_sts[7] |= int_sts[8]; | ||
| 313 | |||
| 314 | /* Call interrupt handler if enabled */ | ||
| 315 | for (i = 0; i < RC5T583_MAX_IRQS; ++i) { | ||
| 316 | const struct rc5t583_irq_data *data = &rc5t583_irqs[i]; | ||
| 317 | if ((int_sts[data->mask_reg_index] & (1 << data->int_en_bit)) && | ||
| 318 | (rc5t583->group_irq_en[data->master_bit] & | ||
| 319 | (1 << data->grp_index))) | ||
| 320 | handle_nested_irq(rc5t583->irq_base + i); | ||
| 321 | } | ||
| 322 | |||
| 323 | return IRQ_HANDLED; | ||
| 324 | } | ||
| 325 | |||
| 326 | static struct irq_chip rc5t583_irq_chip = { | ||
| 327 | .name = "rc5t583-irq", | ||
| 328 | .irq_mask = rc5t583_irq_mask, | ||
| 329 | .irq_unmask = rc5t583_irq_unmask, | ||
| 330 | .irq_bus_lock = rc5t583_irq_lock, | ||
| 331 | .irq_bus_sync_unlock = rc5t583_irq_sync_unlock, | ||
| 332 | .irq_set_type = rc5t583_irq_set_type, | ||
| 333 | .irq_set_wake = rc5t583_irq_set_wake, | ||
| 334 | }; | ||
| 335 | |||
| 336 | int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base) | ||
| 337 | { | ||
| 338 | int i, ret; | ||
| 339 | |||
| 340 | if (!irq_base) { | ||
| 341 | dev_warn(rc5t583->dev, "No interrupt support on IRQ base\n"); | ||
| 342 | return -EINVAL; | ||
| 343 | } | ||
| 344 | |||
| 345 | mutex_init(&rc5t583->irq_lock); | ||
| 346 | |||
| 347 | /* Initailize all int register to 0 */ | ||
| 348 | for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++) { | ||
| 349 | ret = rc5t583_write(rc5t583->dev, irq_en_add[i], | ||
| 350 | rc5t583->irq_en_reg[i]); | ||
| 351 | if (ret < 0) | ||
| 352 | dev_warn(rc5t583->dev, | ||
| 353 | "Error in writing reg 0x%02x error: %d\n", | ||
| 354 | irq_en_add[i], ret); | ||
| 355 | } | ||
| 356 | |||
| 357 | for (i = 0; i < RC5T583_MAX_GPEDGE_REG; i++) { | ||
| 358 | ret = rc5t583_write(rc5t583->dev, gpedge_add[i], | ||
| 359 | rc5t583->gpedge_reg[i]); | ||
| 360 | if (ret < 0) | ||
| 361 | dev_warn(rc5t583->dev, | ||
| 362 | "Error in writing reg 0x%02x error: %d\n", | ||
| 363 | gpedge_add[i], ret); | ||
| 364 | } | ||
| 365 | |||
| 366 | ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN, 0x0); | ||
| 367 | if (ret < 0) | ||
| 368 | dev_warn(rc5t583->dev, | ||
| 369 | "Error in writing reg 0x%02x error: %d\n", | ||
| 370 | RC5T583_INTC_INTEN, ret); | ||
| 371 | |||
| 372 | /* Clear all interrupts in case they woke up active. */ | ||
| 373 | for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++) { | ||
| 374 | ret = rc5t583_write(rc5t583->dev, irq_clr_add[i], 0); | ||
| 375 | if (ret < 0) | ||
| 376 | dev_warn(rc5t583->dev, | ||
| 377 | "Error in writing reg 0x%02x error: %d\n", | ||
| 378 | irq_clr_add[i], ret); | ||
| 379 | } | ||
| 380 | |||
| 381 | rc5t583->irq_base = irq_base; | ||
| 382 | rc5t583->chip_irq = irq; | ||
| 383 | |||
| 384 | for (i = 0; i < RC5T583_MAX_IRQS; i++) { | ||
| 385 | int __irq = i + rc5t583->irq_base; | ||
| 386 | irq_set_chip_data(__irq, rc5t583); | ||
| 387 | irq_set_chip_and_handler(__irq, &rc5t583_irq_chip, | ||
| 388 | handle_simple_irq); | ||
| 389 | irq_set_nested_thread(__irq, 1); | ||
| 390 | #ifdef CONFIG_ARM | ||
| 391 | set_irq_flags(__irq, IRQF_VALID); | ||
| 392 | #endif | ||
| 393 | } | ||
| 394 | |||
| 395 | ret = request_threaded_irq(irq, NULL, rc5t583_irq, IRQF_ONESHOT, | ||
| 396 | "rc5t583", rc5t583); | ||
| 397 | if (ret < 0) | ||
| 398 | dev_err(rc5t583->dev, | ||
| 399 | "Error in registering interrupt error: %d\n", ret); | ||
| 400 | return ret; | ||
| 401 | } | ||
| 402 | |||
| 403 | int rc5t583_irq_exit(struct rc5t583 *rc5t583) | ||
| 404 | { | ||
| 405 | if (rc5t583->chip_irq) | ||
| 406 | free_irq(rc5t583->chip_irq, rc5t583); | ||
| 407 | return 0; | ||
| 408 | } | ||
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c new file mode 100644 index 000000000000..99ef944c621d --- /dev/null +++ b/drivers/mfd/rc5t583.c | |||
| @@ -0,0 +1,386 @@ | |||
| 1 | /* | ||
| 2 | * Core driver access RC5T583 power management chip. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * Author: Laxman dewangan <ldewangan@nvidia.com> | ||
| 6 | * | ||
| 7 | * Based on code | ||
| 8 | * Copyright (C) 2011 RICOH COMPANY,LTD | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms and conditions of the GNU General Public License, | ||
| 12 | * version 2, as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 17 | * more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/irq.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/err.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/i2c.h> | ||
| 31 | #include <linux/mfd/core.h> | ||
| 32 | #include <linux/mfd/rc5t583.h> | ||
| 33 | #include <linux/regmap.h> | ||
| 34 | |||
| 35 | #define RICOH_ONOFFSEL_REG 0x10 | ||
| 36 | #define RICOH_SWCTL_REG 0x5E | ||
| 37 | |||
| 38 | struct deepsleep_control_data { | ||
| 39 | u8 reg_add; | ||
| 40 | u8 ds_pos_bit; | ||
| 41 | }; | ||
| 42 | |||
| 43 | #define DEEPSLEEP_INIT(_id, _reg, _pos) \ | ||
| 44 | { \ | ||
| 45 | .reg_add = RC5T583_##_reg, \ | ||
| 46 | .ds_pos_bit = _pos, \ | ||
| 47 | } | ||
| 48 | |||
| 49 | static struct deepsleep_control_data deepsleep_data[] = { | ||
| 50 | DEEPSLEEP_INIT(DC0, SLPSEQ1, 0), | ||
| 51 | DEEPSLEEP_INIT(DC1, SLPSEQ1, 4), | ||
| 52 | DEEPSLEEP_INIT(DC2, SLPSEQ2, 0), | ||
| 53 | DEEPSLEEP_INIT(DC3, SLPSEQ2, 4), | ||
| 54 | DEEPSLEEP_INIT(LDO0, SLPSEQ3, 0), | ||
| 55 | DEEPSLEEP_INIT(LDO1, SLPSEQ3, 4), | ||
| 56 | DEEPSLEEP_INIT(LDO2, SLPSEQ4, 0), | ||
| 57 | DEEPSLEEP_INIT(LDO3, SLPSEQ4, 4), | ||
| 58 | DEEPSLEEP_INIT(LDO4, SLPSEQ5, 0), | ||
| 59 | DEEPSLEEP_INIT(LDO5, SLPSEQ5, 4), | ||
| 60 | DEEPSLEEP_INIT(LDO6, SLPSEQ6, 0), | ||
| 61 | DEEPSLEEP_INIT(LDO7, SLPSEQ6, 4), | ||
| 62 | DEEPSLEEP_INIT(LDO8, SLPSEQ7, 0), | ||
| 63 | DEEPSLEEP_INIT(LDO9, SLPSEQ7, 4), | ||
| 64 | DEEPSLEEP_INIT(PSO0, SLPSEQ8, 0), | ||
| 65 | DEEPSLEEP_INIT(PSO1, SLPSEQ8, 4), | ||
| 66 | DEEPSLEEP_INIT(PSO2, SLPSEQ9, 0), | ||
| 67 | DEEPSLEEP_INIT(PSO3, SLPSEQ9, 4), | ||
| 68 | DEEPSLEEP_INIT(PSO4, SLPSEQ10, 0), | ||
| 69 | DEEPSLEEP_INIT(PSO5, SLPSEQ10, 4), | ||
| 70 | DEEPSLEEP_INIT(PSO6, SLPSEQ11, 0), | ||
| 71 | DEEPSLEEP_INIT(PSO7, SLPSEQ11, 4), | ||
| 72 | }; | ||
| 73 | |||
| 74 | #define EXT_PWR_REQ \ | ||
| 75 | (RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL) | ||
| 76 | |||
| 77 | static struct mfd_cell rc5t583_subdevs[] = { | ||
| 78 | {.name = "rc5t583-regulator",}, | ||
| 79 | {.name = "rc5t583-rtc", }, | ||
| 80 | {.name = "rc5t583-key", } | ||
| 81 | }; | ||
| 82 | |||
| 83 | int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val) | ||
| 84 | { | ||
| 85 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev); | ||
| 86 | return regmap_write(rc5t583->regmap, reg, val); | ||
| 87 | } | ||
| 88 | |||
| 89 | int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val) | ||
| 90 | { | ||
| 91 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev); | ||
| 92 | unsigned int ival; | ||
| 93 | int ret; | ||
| 94 | ret = regmap_read(rc5t583->regmap, reg, &ival); | ||
| 95 | if (!ret) | ||
| 96 | *val = (uint8_t)ival; | ||
| 97 | return ret; | ||
| 98 | } | ||
| 99 | |||
| 100 | int rc5t583_set_bits(struct device *dev, unsigned int reg, | ||
| 101 | unsigned int bit_mask) | ||
| 102 | { | ||
| 103 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev); | ||
| 104 | return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask); | ||
| 105 | } | ||
| 106 | |||
| 107 | int rc5t583_clear_bits(struct device *dev, unsigned int reg, | ||
| 108 | unsigned int bit_mask) | ||
| 109 | { | ||
| 110 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev); | ||
| 111 | return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0); | ||
| 112 | } | ||
| 113 | |||
| 114 | int rc5t583_update(struct device *dev, unsigned int reg, | ||
| 115 | unsigned int val, unsigned int mask) | ||
| 116 | { | ||
| 117 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev); | ||
| 118 | return regmap_update_bits(rc5t583->regmap, reg, mask, val); | ||
| 119 | } | ||
| 120 | |||
| 121 | static int __rc5t583_set_ext_pwrreq1_control(struct device *dev, | ||
| 122 | int id, int ext_pwr, int slots) | ||
| 123 | { | ||
| 124 | int ret; | ||
| 125 | uint8_t sleepseq_val; | ||
| 126 | unsigned int en_bit; | ||
| 127 | unsigned int slot_bit; | ||
| 128 | |||
| 129 | if (id == RC5T583_DS_DC0) { | ||
| 130 | dev_err(dev, "PWRREQ1 is invalid control for rail %d\n", id); | ||
| 131 | return -EINVAL; | ||
| 132 | } | ||
| 133 | |||
| 134 | en_bit = deepsleep_data[id].ds_pos_bit; | ||
| 135 | slot_bit = en_bit + 1; | ||
| 136 | ret = rc5t583_read(dev, deepsleep_data[id].reg_add, &sleepseq_val); | ||
| 137 | if (ret < 0) { | ||
| 138 | dev_err(dev, "Error in reading reg 0x%x\n", | ||
| 139 | deepsleep_data[id].reg_add); | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | sleepseq_val &= ~(0xF << en_bit); | ||
| 144 | sleepseq_val |= BIT(en_bit); | ||
| 145 | sleepseq_val |= ((slots & 0x7) << slot_bit); | ||
| 146 | ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(1)); | ||
| 147 | if (ret < 0) { | ||
| 148 | dev_err(dev, "Error in updating the 0x%02x register\n", | ||
| 149 | RICOH_ONOFFSEL_REG); | ||
| 150 | return ret; | ||
| 151 | } | ||
| 152 | |||
| 153 | ret = rc5t583_write(dev, deepsleep_data[id].reg_add, sleepseq_val); | ||
| 154 | if (ret < 0) { | ||
| 155 | dev_err(dev, "Error in writing reg 0x%x\n", | ||
| 156 | deepsleep_data[id].reg_add); | ||
| 157 | return ret; | ||
| 158 | } | ||
| 159 | |||
| 160 | if (id == RC5T583_DS_LDO4) { | ||
| 161 | ret = rc5t583_write(dev, RICOH_SWCTL_REG, 0x1); | ||
| 162 | if (ret < 0) | ||
| 163 | dev_err(dev, "Error in writing reg 0x%x\n", | ||
| 164 | RICOH_SWCTL_REG); | ||
| 165 | } | ||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int __rc5t583_set_ext_pwrreq2_control(struct device *dev, | ||
| 170 | int id, int ext_pwr) | ||
| 171 | { | ||
| 172 | int ret; | ||
| 173 | |||
| 174 | if (id != RC5T583_DS_DC0) { | ||
| 175 | dev_err(dev, "PWRREQ2 is invalid control for rail %d\n", id); | ||
| 176 | return -EINVAL; | ||
| 177 | } | ||
| 178 | |||
| 179 | ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(2)); | ||
| 180 | if (ret < 0) | ||
| 181 | dev_err(dev, "Error in updating the ONOFFSEL 0x10 register\n"); | ||
| 182 | return ret; | ||
| 183 | } | ||
| 184 | |||
| 185 | int rc5t583_ext_power_req_config(struct device *dev, int ds_id, | ||
| 186 | int ext_pwr_req, int deepsleep_slot_nr) | ||
| 187 | { | ||
| 188 | if ((ext_pwr_req & EXT_PWR_REQ) == EXT_PWR_REQ) | ||
| 189 | return -EINVAL; | ||
| 190 | |||
| 191 | if (ext_pwr_req & RC5T583_EXT_PWRREQ1_CONTROL) | ||
| 192 | return __rc5t583_set_ext_pwrreq1_control(dev, ds_id, | ||
| 193 | ext_pwr_req, deepsleep_slot_nr); | ||
| 194 | |||
| 195 | if (ext_pwr_req & RC5T583_EXT_PWRREQ2_CONTROL) | ||
| 196 | return __rc5t583_set_ext_pwrreq2_control(dev, | ||
| 197 | ds_id, ext_pwr_req); | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583, | ||
| 202 | struct rc5t583_platform_data *pdata) | ||
| 203 | { | ||
| 204 | int ret; | ||
| 205 | int i; | ||
| 206 | uint8_t on_off_val = 0; | ||
| 207 | |||
| 208 | /* Clear ONOFFSEL register */ | ||
| 209 | if (pdata->enable_shutdown) | ||
| 210 | on_off_val = 0x1; | ||
| 211 | |||
| 212 | ret = rc5t583_write(rc5t583->dev, RICOH_ONOFFSEL_REG, on_off_val); | ||
| 213 | if (ret < 0) | ||
| 214 | dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n", | ||
| 215 | RICOH_ONOFFSEL_REG, ret); | ||
| 216 | |||
| 217 | ret = rc5t583_write(rc5t583->dev, RICOH_SWCTL_REG, 0x0); | ||
| 218 | if (ret < 0) | ||
| 219 | dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n", | ||
| 220 | RICOH_SWCTL_REG, ret); | ||
| 221 | |||
| 222 | /* Clear sleep sequence register */ | ||
| 223 | for (i = RC5T583_SLPSEQ1; i <= RC5T583_SLPSEQ11; ++i) { | ||
| 224 | ret = rc5t583_write(rc5t583->dev, i, 0x0); | ||
| 225 | if (ret < 0) | ||
| 226 | dev_warn(rc5t583->dev, | ||
| 227 | "Error in writing reg 0x%02x error: %d\n", | ||
| 228 | i, ret); | ||
| 229 | } | ||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | static bool volatile_reg(struct device *dev, unsigned int reg) | ||
| 234 | { | ||
| 235 | /* Enable caching in interrupt registers */ | ||
| 236 | switch (reg) { | ||
| 237 | case RC5T583_INT_EN_SYS1: | ||
| 238 | case RC5T583_INT_EN_SYS2: | ||
| 239 | case RC5T583_INT_EN_DCDC: | ||
| 240 | case RC5T583_INT_EN_RTC: | ||
| 241 | case RC5T583_INT_EN_ADC1: | ||
| 242 | case RC5T583_INT_EN_ADC2: | ||
| 243 | case RC5T583_INT_EN_ADC3: | ||
| 244 | case RC5T583_GPIO_GPEDGE1: | ||
| 245 | case RC5T583_GPIO_GPEDGE2: | ||
| 246 | case RC5T583_GPIO_EN_INT: | ||
| 247 | return false; | ||
| 248 | |||
| 249 | case RC5T583_GPIO_MON_IOIN: | ||
| 250 | /* This is gpio input register */ | ||
| 251 | return true; | ||
| 252 | |||
| 253 | default: | ||
| 254 | /* Enable caching in gpio registers */ | ||
| 255 | if ((reg >= RC5T583_GPIO_IOSEL) && | ||
| 256 | (reg <= RC5T583_GPIO_GPOFUNC)) | ||
| 257 | return false; | ||
| 258 | |||
| 259 | /* Enable caching in sleep seq registers */ | ||
| 260 | if ((reg >= RC5T583_SLPSEQ1) && (reg <= RC5T583_SLPSEQ11)) | ||
| 261 | return false; | ||
| 262 | |||
| 263 | /* Enable caching of regulator registers */ | ||
| 264 | if ((reg >= RC5T583_REG_DC0CTL) && (reg <= RC5T583_REG_SR3CTL)) | ||
| 265 | return false; | ||
| 266 | if ((reg >= RC5T583_REG_LDOEN1) && | ||
| 267 | (reg <= RC5T583_REG_LDO9DAC_DS)) | ||
| 268 | return false; | ||
| 269 | |||
| 270 | break; | ||
| 271 | } | ||
| 272 | |||
| 273 | return true; | ||
| 274 | } | ||
| 275 | |||
| 276 | static const struct regmap_config rc5t583_regmap_config = { | ||
| 277 | .reg_bits = 8, | ||
| 278 | .val_bits = 8, | ||
| 279 | .volatile_reg = volatile_reg, | ||
| 280 | .max_register = RC5T583_MAX_REGS, | ||
| 281 | .num_reg_defaults_raw = RC5T583_MAX_REGS, | ||
| 282 | .cache_type = REGCACHE_RBTREE, | ||
| 283 | }; | ||
| 284 | |||
| 285 | static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c, | ||
| 286 | const struct i2c_device_id *id) | ||
| 287 | { | ||
| 288 | struct rc5t583 *rc5t583; | ||
| 289 | struct rc5t583_platform_data *pdata = i2c->dev.platform_data; | ||
| 290 | int ret; | ||
| 291 | bool irq_init_success = false; | ||
| 292 | |||
| 293 | if (!pdata) { | ||
| 294 | dev_err(&i2c->dev, "Err: Platform data not found\n"); | ||
| 295 | return -EINVAL; | ||
| 296 | } | ||
| 297 | |||
| 298 | rc5t583 = devm_kzalloc(&i2c->dev, sizeof(struct rc5t583), GFP_KERNEL); | ||
| 299 | if (!rc5t583) { | ||
| 300 | dev_err(&i2c->dev, "Memory allocation failed\n"); | ||
| 301 | return -ENOMEM; | ||
| 302 | } | ||
| 303 | |||
| 304 | rc5t583->dev = &i2c->dev; | ||
| 305 | i2c_set_clientdata(i2c, rc5t583); | ||
| 306 | |||
| 307 | rc5t583->regmap = regmap_init_i2c(i2c, &rc5t583_regmap_config); | ||
| 308 | if (IS_ERR(rc5t583->regmap)) { | ||
| 309 | ret = PTR_ERR(rc5t583->regmap); | ||
| 310 | dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret); | ||
| 311 | return ret; | ||
| 312 | } | ||
| 313 | |||
| 314 | ret = rc5t583_clear_ext_power_req(rc5t583, pdata); | ||
| 315 | if (ret < 0) | ||
| 316 | goto err_irq_init; | ||
| 317 | |||
| 318 | if (i2c->irq) { | ||
| 319 | ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base); | ||
| 320 | /* Still continue with waring if irq init fails */ | ||
| 321 | if (ret) | ||
| 322 | dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret); | ||
| 323 | else | ||
| 324 | irq_init_success = true; | ||
| 325 | } | ||
| 326 | |||
| 327 | ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, | ||
| 328 | ARRAY_SIZE(rc5t583_subdevs), NULL, 0); | ||
| 329 | if (ret) { | ||
| 330 | dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret); | ||
| 331 | goto err_add_devs; | ||
| 332 | } | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | |||
| 336 | err_add_devs: | ||
| 337 | if (irq_init_success) | ||
| 338 | rc5t583_irq_exit(rc5t583); | ||
| 339 | err_irq_init: | ||
| 340 | regmap_exit(rc5t583->regmap); | ||
| 341 | return ret; | ||
| 342 | } | ||
| 343 | |||
| 344 | static int __devexit rc5t583_i2c_remove(struct i2c_client *i2c) | ||
| 345 | { | ||
| 346 | struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c); | ||
| 347 | |||
| 348 | mfd_remove_devices(rc5t583->dev); | ||
| 349 | rc5t583_irq_exit(rc5t583); | ||
| 350 | regmap_exit(rc5t583->regmap); | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | static const struct i2c_device_id rc5t583_i2c_id[] = { | ||
| 355 | {.name = "rc5t583", .driver_data = 0}, | ||
| 356 | {} | ||
| 357 | }; | ||
| 358 | |||
| 359 | MODULE_DEVICE_TABLE(i2c, rc5t583_i2c_id); | ||
| 360 | |||
| 361 | static struct i2c_driver rc5t583_i2c_driver = { | ||
| 362 | .driver = { | ||
| 363 | .name = "rc5t583", | ||
| 364 | .owner = THIS_MODULE, | ||
| 365 | }, | ||
| 366 | .probe = rc5t583_i2c_probe, | ||
| 367 | .remove = __devexit_p(rc5t583_i2c_remove), | ||
| 368 | .id_table = rc5t583_i2c_id, | ||
| 369 | }; | ||
| 370 | |||
| 371 | static int __init rc5t583_i2c_init(void) | ||
| 372 | { | ||
| 373 | return i2c_add_driver(&rc5t583_i2c_driver); | ||
| 374 | } | ||
| 375 | subsys_initcall(rc5t583_i2c_init); | ||
| 376 | |||
| 377 | static void __exit rc5t583_i2c_exit(void) | ||
| 378 | { | ||
| 379 | i2c_del_driver(&rc5t583_i2c_driver); | ||
| 380 | } | ||
| 381 | |||
| 382 | module_exit(rc5t583_i2c_exit); | ||
| 383 | |||
| 384 | MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); | ||
| 385 | MODULE_DESCRIPTION("RICOH RC5T583 power management system device driver"); | ||
| 386 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/s5m-core.c b/drivers/mfd/s5m-core.c index caadabeed8e9..48949d998d10 100644 --- a/drivers/mfd/s5m-core.c +++ b/drivers/mfd/s5m-core.c | |||
| @@ -26,7 +26,27 @@ | |||
| 26 | #include <linux/mfd/s5m87xx/s5m-rtc.h> | 26 | #include <linux/mfd/s5m87xx/s5m-rtc.h> |
| 27 | #include <linux/regmap.h> | 27 | #include <linux/regmap.h> |
| 28 | 28 | ||
| 29 | static struct mfd_cell s5m87xx_devs[] = { | 29 | static struct mfd_cell s5m8751_devs[] = { |
| 30 | { | ||
| 31 | .name = "s5m8751-pmic", | ||
| 32 | }, { | ||
| 33 | .name = "s5m-charger", | ||
| 34 | }, { | ||
| 35 | .name = "s5m8751-codec", | ||
| 36 | }, | ||
| 37 | }; | ||
| 38 | |||
| 39 | static struct mfd_cell s5m8763_devs[] = { | ||
| 40 | { | ||
| 41 | .name = "s5m8763-pmic", | ||
| 42 | }, { | ||
| 43 | .name = "s5m-rtc", | ||
| 44 | }, { | ||
| 45 | .name = "s5m-charger", | ||
| 46 | }, | ||
| 47 | }; | ||
| 48 | |||
| 49 | static struct mfd_cell s5m8767_devs[] = { | ||
| 30 | { | 50 | { |
| 31 | .name = "s5m8767-pmic", | 51 | .name = "s5m8767-pmic", |
| 32 | }, { | 52 | }, { |
| @@ -42,7 +62,7 @@ EXPORT_SYMBOL_GPL(s5m_reg_read); | |||
| 42 | 62 | ||
| 43 | int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf) | 63 | int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf) |
| 44 | { | 64 | { |
| 45 | return regmap_bulk_read(s5m87xx->regmap, reg, buf, count);; | 65 | return regmap_bulk_read(s5m87xx->regmap, reg, buf, count); |
| 46 | } | 66 | } |
| 47 | EXPORT_SYMBOL_GPL(s5m_bulk_read); | 67 | EXPORT_SYMBOL_GPL(s5m_bulk_read); |
| 48 | 68 | ||
| @@ -54,7 +74,7 @@ EXPORT_SYMBOL_GPL(s5m_reg_write); | |||
| 54 | 74 | ||
| 55 | int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf) | 75 | int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf) |
| 56 | { | 76 | { |
| 57 | return regmap_raw_write(s5m87xx->regmap, reg, buf, count * sizeof(u16)); | 77 | return regmap_raw_write(s5m87xx->regmap, reg, buf, count); |
| 58 | } | 78 | } |
| 59 | EXPORT_SYMBOL_GPL(s5m_bulk_write); | 79 | EXPORT_SYMBOL_GPL(s5m_bulk_write); |
| 60 | 80 | ||
| @@ -74,10 +94,10 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c, | |||
| 74 | { | 94 | { |
| 75 | struct s5m_platform_data *pdata = i2c->dev.platform_data; | 95 | struct s5m_platform_data *pdata = i2c->dev.platform_data; |
| 76 | struct s5m87xx_dev *s5m87xx; | 96 | struct s5m87xx_dev *s5m87xx; |
| 77 | int ret = 0; | 97 | int ret; |
| 78 | int error; | ||
| 79 | 98 | ||
| 80 | s5m87xx = kzalloc(sizeof(struct s5m87xx_dev), GFP_KERNEL); | 99 | s5m87xx = devm_kzalloc(&i2c->dev, sizeof(struct s5m87xx_dev), |
| 100 | GFP_KERNEL); | ||
| 81 | if (s5m87xx == NULL) | 101 | if (s5m87xx == NULL) |
| 82 | return -ENOMEM; | 102 | return -ENOMEM; |
| 83 | 103 | ||
| @@ -96,9 +116,9 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c, | |||
| 96 | 116 | ||
| 97 | s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config); | 117 | s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config); |
| 98 | if (IS_ERR(s5m87xx->regmap)) { | 118 | if (IS_ERR(s5m87xx->regmap)) { |
| 99 | error = PTR_ERR(s5m87xx->regmap); | 119 | ret = PTR_ERR(s5m87xx->regmap); |
| 100 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 120 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
| 101 | error); | 121 | ret); |
| 102 | goto err; | 122 | goto err; |
| 103 | } | 123 | } |
| 104 | 124 | ||
| @@ -112,9 +132,23 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c, | |||
| 112 | 132 | ||
| 113 | pm_runtime_set_active(s5m87xx->dev); | 133 | pm_runtime_set_active(s5m87xx->dev); |
| 114 | 134 | ||
| 115 | ret = mfd_add_devices(s5m87xx->dev, -1, | 135 | switch (s5m87xx->device_type) { |
| 116 | s5m87xx_devs, ARRAY_SIZE(s5m87xx_devs), | 136 | case S5M8751X: |
| 117 | NULL, 0); | 137 | ret = mfd_add_devices(s5m87xx->dev, -1, s5m8751_devs, |
| 138 | ARRAY_SIZE(s5m8751_devs), NULL, 0); | ||
| 139 | break; | ||
| 140 | case S5M8763X: | ||
| 141 | ret = mfd_add_devices(s5m87xx->dev, -1, s5m8763_devs, | ||
| 142 | ARRAY_SIZE(s5m8763_devs), NULL, 0); | ||
| 143 | break; | ||
| 144 | case S5M8767X: | ||
| 145 | ret = mfd_add_devices(s5m87xx->dev, -1, s5m8767_devs, | ||
| 146 | ARRAY_SIZE(s5m8767_devs), NULL, 0); | ||
| 147 | break; | ||
| 148 | default: | ||
| 149 | /* If this happens the probe function is problem */ | ||
| 150 | BUG(); | ||
| 151 | } | ||
| 118 | 152 | ||
| 119 | if (ret < 0) | 153 | if (ret < 0) |
| 120 | goto err; | 154 | goto err; |
| @@ -126,7 +160,6 @@ err: | |||
| 126 | s5m_irq_exit(s5m87xx); | 160 | s5m_irq_exit(s5m87xx); |
| 127 | i2c_unregister_device(s5m87xx->rtc); | 161 | i2c_unregister_device(s5m87xx->rtc); |
| 128 | regmap_exit(s5m87xx->regmap); | 162 | regmap_exit(s5m87xx->regmap); |
| 129 | kfree(s5m87xx); | ||
| 130 | return ret; | 163 | return ret; |
| 131 | } | 164 | } |
| 132 | 165 | ||
| @@ -138,7 +171,6 @@ static int s5m87xx_i2c_remove(struct i2c_client *i2c) | |||
| 138 | s5m_irq_exit(s5m87xx); | 171 | s5m_irq_exit(s5m87xx); |
| 139 | i2c_unregister_device(s5m87xx->rtc); | 172 | i2c_unregister_device(s5m87xx->rtc); |
| 140 | regmap_exit(s5m87xx->regmap); | 173 | regmap_exit(s5m87xx->regmap); |
| 141 | kfree(s5m87xx); | ||
| 142 | return 0; | 174 | return 0; |
| 143 | } | 175 | } |
| 144 | 176 | ||
diff --git a/drivers/mfd/s5m-irq.c b/drivers/mfd/s5m-irq.c index de76dfb6f0ad..0236676085cf 100644 --- a/drivers/mfd/s5m-irq.c +++ b/drivers/mfd/s5m-irq.c | |||
| @@ -342,7 +342,10 @@ int s5m_irq_resume(struct s5m87xx_dev *s5m87xx) | |||
| 342 | s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx); | 342 | s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx); |
| 343 | break; | 343 | break; |
| 344 | default: | 344 | default: |
| 345 | break; | 345 | dev_err(s5m87xx->dev, |
| 346 | "Unknown device type %d\n", | ||
| 347 | s5m87xx->device_type); | ||
| 348 | return -EINVAL; | ||
| 346 | 349 | ||
| 347 | } | 350 | } |
| 348 | } | 351 | } |
| @@ -444,7 +447,9 @@ int s5m_irq_init(struct s5m87xx_dev *s5m87xx) | |||
| 444 | } | 447 | } |
| 445 | break; | 448 | break; |
| 446 | default: | 449 | default: |
| 447 | break; | 450 | dev_err(s5m87xx->dev, |
| 451 | "Unknown device type %d\n", s5m87xx->device_type); | ||
| 452 | return -EINVAL; | ||
| 448 | } | 453 | } |
| 449 | 454 | ||
| 450 | if (!s5m87xx->ono) | 455 | if (!s5m87xx->ono) |
| @@ -467,12 +472,15 @@ int s5m_irq_init(struct s5m87xx_dev *s5m87xx) | |||
| 467 | IRQF_ONESHOT, "s5m87xx-ono", s5m87xx); | 472 | IRQF_ONESHOT, "s5m87xx-ono", s5m87xx); |
| 468 | break; | 473 | break; |
| 469 | default: | 474 | default: |
| 475 | ret = -EINVAL; | ||
| 470 | break; | 476 | break; |
| 471 | } | 477 | } |
| 472 | 478 | ||
| 473 | if (ret) | 479 | if (ret) { |
| 474 | dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n", | 480 | dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n", |
| 475 | s5m87xx->ono, ret); | 481 | s5m87xx->ono, ret); |
| 482 | return ret; | ||
| 483 | } | ||
| 476 | 484 | ||
| 477 | return 0; | 485 | return 0; |
| 478 | } | 486 | } |
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index f4d86117f44a..d927dd49acb3 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
| @@ -387,14 +387,6 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to) | |||
| 387 | 387 | ||
| 388 | EXPORT_SYMBOL_GPL(sm501_unit_power); | 388 | EXPORT_SYMBOL_GPL(sm501_unit_power); |
| 389 | 389 | ||
| 390 | |||
| 391 | /* Perform a rounded division. */ | ||
| 392 | static long sm501fb_round_div(long num, long denom) | ||
| 393 | { | ||
| 394 | /* n / d + 1 / 2 = (2n + d) / 2d */ | ||
| 395 | return (2 * num + denom) / (2 * denom); | ||
| 396 | } | ||
| 397 | |||
| 398 | /* clock value structure. */ | 390 | /* clock value structure. */ |
| 399 | struct sm501_clock { | 391 | struct sm501_clock { |
| 400 | unsigned long mclk; | 392 | unsigned long mclk; |
| @@ -428,7 +420,7 @@ static int sm501_calc_clock(unsigned long freq, | |||
| 428 | /* try all 8 shift values.*/ | 420 | /* try all 8 shift values.*/ |
| 429 | for (shift = 0; shift < 8; shift++) { | 421 | for (shift = 0; shift < 8; shift++) { |
| 430 | /* Calculate difference to requested clock */ | 422 | /* Calculate difference to requested clock */ |
| 431 | diff = sm501fb_round_div(mclk, divider << shift) - freq; | 423 | diff = DIV_ROUND_CLOSEST(mclk, divider << shift) - freq; |
| 432 | if (diff < 0) | 424 | if (diff < 0) |
| 433 | diff = -diff; | 425 | diff = -diff; |
| 434 | 426 | ||
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index e07947e56b2a..2dd8d49cb30b 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c | |||
| @@ -298,6 +298,11 @@ static struct mfd_cell stmpe_gpio_cell = { | |||
| 298 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), | 298 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), |
| 299 | }; | 299 | }; |
| 300 | 300 | ||
| 301 | static struct mfd_cell stmpe_gpio_cell_noirq = { | ||
| 302 | .name = "stmpe-gpio", | ||
| 303 | /* gpio cell resources consist of an irq only so no resources here */ | ||
| 304 | }; | ||
| 305 | |||
| 301 | /* | 306 | /* |
| 302 | * Keypad (1601, 2401, 2403) | 307 | * Keypad (1601, 2401, 2403) |
| 303 | */ | 308 | */ |
| @@ -346,6 +351,13 @@ static struct stmpe_variant_block stmpe801_blocks[] = { | |||
| 346 | }, | 351 | }, |
| 347 | }; | 352 | }; |
| 348 | 353 | ||
| 354 | static struct stmpe_variant_block stmpe801_blocks_noirq[] = { | ||
| 355 | { | ||
| 356 | .cell = &stmpe_gpio_cell_noirq, | ||
| 357 | .block = STMPE_BLOCK_GPIO, | ||
| 358 | }, | ||
| 359 | }; | ||
| 360 | |||
| 349 | static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks, | 361 | static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks, |
| 350 | bool enable) | 362 | bool enable) |
| 351 | { | 363 | { |
| @@ -367,6 +379,17 @@ static struct stmpe_variant_info stmpe801 = { | |||
| 367 | .enable = stmpe801_enable, | 379 | .enable = stmpe801_enable, |
| 368 | }; | 380 | }; |
| 369 | 381 | ||
| 382 | static struct stmpe_variant_info stmpe801_noirq = { | ||
| 383 | .name = "stmpe801", | ||
| 384 | .id_val = STMPE801_ID, | ||
| 385 | .id_mask = 0xffff, | ||
| 386 | .num_gpios = 8, | ||
| 387 | .regs = stmpe801_regs, | ||
| 388 | .blocks = stmpe801_blocks_noirq, | ||
| 389 | .num_blocks = ARRAY_SIZE(stmpe801_blocks_noirq), | ||
| 390 | .enable = stmpe801_enable, | ||
| 391 | }; | ||
| 392 | |||
| 370 | /* | 393 | /* |
| 371 | * Touchscreen (STMPE811 or STMPE610) | 394 | * Touchscreen (STMPE811 or STMPE610) |
| 372 | */ | 395 | */ |
| @@ -712,7 +735,7 @@ static struct stmpe_variant_info stmpe2403 = { | |||
| 712 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ | 735 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ |
| 713 | }; | 736 | }; |
| 714 | 737 | ||
| 715 | static struct stmpe_variant_info *stmpe_variant_info[] = { | 738 | static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = { |
| 716 | [STMPE610] = &stmpe610, | 739 | [STMPE610] = &stmpe610, |
| 717 | [STMPE801] = &stmpe801, | 740 | [STMPE801] = &stmpe801, |
| 718 | [STMPE811] = &stmpe811, | 741 | [STMPE811] = &stmpe811, |
| @@ -721,6 +744,16 @@ static struct stmpe_variant_info *stmpe_variant_info[] = { | |||
| 721 | [STMPE2403] = &stmpe2403, | 744 | [STMPE2403] = &stmpe2403, |
| 722 | }; | 745 | }; |
| 723 | 746 | ||
| 747 | /* | ||
| 748 | * These devices can be connected in a 'no-irq' configuration - the irq pin | ||
| 749 | * is not used and the device cannot interrupt the CPU. Here we only list | ||
| 750 | * devices which support this configuration - the driver will fail probing | ||
| 751 | * for any devices not listed here which are configured in this way. | ||
| 752 | */ | ||
| 753 | static struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = { | ||
| 754 | [STMPE801] = &stmpe801_noirq, | ||
| 755 | }; | ||
| 756 | |||
| 724 | static irqreturn_t stmpe_irq(int irq, void *data) | 757 | static irqreturn_t stmpe_irq(int irq, void *data) |
| 725 | { | 758 | { |
| 726 | struct stmpe *stmpe = data; | 759 | struct stmpe *stmpe = data; |
| @@ -864,7 +897,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) | |||
| 864 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; | 897 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; |
| 865 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; | 898 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; |
| 866 | struct stmpe_variant_info *variant = stmpe->variant; | 899 | struct stmpe_variant_info *variant = stmpe->variant; |
| 867 | u8 icr; | 900 | u8 icr = 0; |
| 868 | unsigned int id; | 901 | unsigned int id; |
| 869 | u8 data[2]; | 902 | u8 data[2]; |
| 870 | int ret; | 903 | int ret; |
| @@ -887,31 +920,33 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) | |||
| 887 | if (ret) | 920 | if (ret) |
| 888 | return ret; | 921 | return ret; |
| 889 | 922 | ||
| 890 | if (id == STMPE801_ID) | 923 | if (stmpe->irq >= 0) { |
| 891 | icr = STMPE801_REG_SYS_CTRL_INT_EN; | ||
| 892 | else | ||
| 893 | icr = STMPE_ICR_LSB_GIM; | ||
| 894 | |||
| 895 | /* STMPE801 doesn't support Edge interrupts */ | ||
| 896 | if (id != STMPE801_ID) { | ||
| 897 | if (irq_trigger == IRQF_TRIGGER_FALLING || | ||
| 898 | irq_trigger == IRQF_TRIGGER_RISING) | ||
| 899 | icr |= STMPE_ICR_LSB_EDGE; | ||
| 900 | } | ||
| 901 | |||
| 902 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
| 903 | irq_trigger == IRQF_TRIGGER_HIGH) { | ||
| 904 | if (id == STMPE801_ID) | 924 | if (id == STMPE801_ID) |
| 905 | icr |= STMPE801_REG_SYS_CTRL_INT_HI; | 925 | icr = STMPE801_REG_SYS_CTRL_INT_EN; |
| 906 | else | 926 | else |
| 907 | icr |= STMPE_ICR_LSB_HIGH; | 927 | icr = STMPE_ICR_LSB_GIM; |
| 908 | } | ||
| 909 | 928 | ||
| 910 | if (stmpe->pdata->irq_invert_polarity) { | 929 | /* STMPE801 doesn't support Edge interrupts */ |
| 911 | if (id == STMPE801_ID) | 930 | if (id != STMPE801_ID) { |
| 912 | icr ^= STMPE801_REG_SYS_CTRL_INT_HI; | 931 | if (irq_trigger == IRQF_TRIGGER_FALLING || |
| 913 | else | 932 | irq_trigger == IRQF_TRIGGER_RISING) |
| 914 | icr ^= STMPE_ICR_LSB_HIGH; | 933 | icr |= STMPE_ICR_LSB_EDGE; |
| 934 | } | ||
| 935 | |||
| 936 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
| 937 | irq_trigger == IRQF_TRIGGER_HIGH) { | ||
| 938 | if (id == STMPE801_ID) | ||
| 939 | icr |= STMPE801_REG_SYS_CTRL_INT_HI; | ||
| 940 | else | ||
| 941 | icr |= STMPE_ICR_LSB_HIGH; | ||
| 942 | } | ||
| 943 | |||
| 944 | if (stmpe->pdata->irq_invert_polarity) { | ||
| 945 | if (id == STMPE801_ID) | ||
| 946 | icr ^= STMPE801_REG_SYS_CTRL_INT_HI; | ||
| 947 | else | ||
| 948 | icr ^= STMPE_ICR_LSB_HIGH; | ||
| 949 | } | ||
| 915 | } | 950 | } |
| 916 | 951 | ||
| 917 | if (stmpe->pdata->autosleep) { | 952 | if (stmpe->pdata->autosleep) { |
| @@ -1001,19 +1036,38 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum) | |||
| 1001 | stmpe->irq = ci->irq; | 1036 | stmpe->irq = ci->irq; |
| 1002 | } | 1037 | } |
| 1003 | 1038 | ||
| 1039 | if (stmpe->irq < 0) { | ||
| 1040 | /* use alternate variant info for no-irq mode, if supported */ | ||
| 1041 | dev_info(stmpe->dev, | ||
| 1042 | "%s configured in no-irq mode by platform data\n", | ||
| 1043 | stmpe->variant->name); | ||
| 1044 | if (!stmpe_noirq_variant_info[stmpe->partnum]) { | ||
| 1045 | dev_err(stmpe->dev, | ||
| 1046 | "%s does not support no-irq mode!\n", | ||
| 1047 | stmpe->variant->name); | ||
| 1048 | ret = -ENODEV; | ||
| 1049 | goto free_gpio; | ||
| 1050 | } | ||
| 1051 | stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum]; | ||
| 1052 | } | ||
| 1053 | |||
| 1004 | ret = stmpe_chip_init(stmpe); | 1054 | ret = stmpe_chip_init(stmpe); |
| 1005 | if (ret) | 1055 | if (ret) |
| 1006 | goto free_gpio; | 1056 | goto free_gpio; |
| 1007 | 1057 | ||
| 1008 | ret = stmpe_irq_init(stmpe); | 1058 | if (stmpe->irq >= 0) { |
| 1009 | if (ret) | 1059 | ret = stmpe_irq_init(stmpe); |
| 1010 | goto free_gpio; | 1060 | if (ret) |
| 1061 | goto free_gpio; | ||
| 1011 | 1062 | ||
| 1012 | ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq, | 1063 | ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq, |
| 1013 | pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe); | 1064 | pdata->irq_trigger | IRQF_ONESHOT, |
| 1014 | if (ret) { | 1065 | "stmpe", stmpe); |
| 1015 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret); | 1066 | if (ret) { |
| 1016 | goto out_removeirq; | 1067 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", |
| 1068 | ret); | ||
| 1069 | goto out_removeirq; | ||
| 1070 | } | ||
| 1017 | } | 1071 | } |
| 1018 | 1072 | ||
| 1019 | ret = stmpe_devices_init(stmpe); | 1073 | ret = stmpe_devices_init(stmpe); |
| @@ -1026,9 +1080,11 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum) | |||
| 1026 | 1080 | ||
| 1027 | out_removedevs: | 1081 | out_removedevs: |
| 1028 | mfd_remove_devices(stmpe->dev); | 1082 | mfd_remove_devices(stmpe->dev); |
| 1029 | free_irq(stmpe->irq, stmpe); | 1083 | if (stmpe->irq >= 0) |
| 1084 | free_irq(stmpe->irq, stmpe); | ||
| 1030 | out_removeirq: | 1085 | out_removeirq: |
| 1031 | stmpe_irq_remove(stmpe); | 1086 | if (stmpe->irq >= 0) |
| 1087 | stmpe_irq_remove(stmpe); | ||
| 1032 | free_gpio: | 1088 | free_gpio: |
| 1033 | if (pdata->irq_over_gpio) | 1089 | if (pdata->irq_over_gpio) |
| 1034 | gpio_free(pdata->irq_gpio); | 1090 | gpio_free(pdata->irq_gpio); |
| @@ -1041,8 +1097,10 @@ int stmpe_remove(struct stmpe *stmpe) | |||
| 1041 | { | 1097 | { |
| 1042 | mfd_remove_devices(stmpe->dev); | 1098 | mfd_remove_devices(stmpe->dev); |
| 1043 | 1099 | ||
| 1044 | free_irq(stmpe->irq, stmpe); | 1100 | if (stmpe->irq >= 0) { |
| 1045 | stmpe_irq_remove(stmpe); | 1101 | free_irq(stmpe->irq, stmpe); |
| 1102 | stmpe_irq_remove(stmpe); | ||
| 1103 | } | ||
| 1046 | 1104 | ||
| 1047 | if (stmpe->pdata->irq_over_gpio) | 1105 | if (stmpe->pdata->irq_over_gpio) |
| 1048 | gpio_free(stmpe->pdata->irq_gpio); | 1106 | gpio_free(stmpe->pdata->irq_gpio); |
| @@ -1057,7 +1115,7 @@ static int stmpe_suspend(struct device *dev) | |||
| 1057 | { | 1115 | { |
| 1058 | struct stmpe *stmpe = dev_get_drvdata(dev); | 1116 | struct stmpe *stmpe = dev_get_drvdata(dev); |
| 1059 | 1117 | ||
| 1060 | if (device_may_wakeup(dev)) | 1118 | if (stmpe->irq >= 0 && device_may_wakeup(dev)) |
| 1061 | enable_irq_wake(stmpe->irq); | 1119 | enable_irq_wake(stmpe->irq); |
| 1062 | 1120 | ||
| 1063 | return 0; | 1121 | return 0; |
| @@ -1067,7 +1125,7 @@ static int stmpe_resume(struct device *dev) | |||
| 1067 | { | 1125 | { |
| 1068 | struct stmpe *stmpe = dev_get_drvdata(dev); | 1126 | struct stmpe *stmpe = dev_get_drvdata(dev); |
| 1069 | 1127 | ||
| 1070 | if (device_may_wakeup(dev)) | 1128 | if (stmpe->irq >= 0 && device_may_wakeup(dev)) |
| 1071 | disable_irq_wake(stmpe->irq); | 1129 | disable_irq_wake(stmpe->irq); |
| 1072 | 1130 | ||
| 1073 | return 0; | 1131 | return 0; |
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c new file mode 100644 index 000000000000..a66d4df51293 --- /dev/null +++ b/drivers/mfd/tps65090.c | |||
| @@ -0,0 +1,387 @@ | |||
| 1 | /* | ||
| 2 | * Core driver for TI TPS65090 PMIC family | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | |||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | |||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | |||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/irq.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/mutex.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/i2c.h> | ||
| 26 | #include <linux/mfd/core.h> | ||
| 27 | #include <linux/mfd/tps65090.h> | ||
| 28 | #include <linux/regmap.h> | ||
| 29 | #include <linux/err.h> | ||
| 30 | |||
| 31 | #define NUM_INT_REG 2 | ||
| 32 | #define TOTAL_NUM_REG 0x18 | ||
| 33 | |||
| 34 | /* interrupt status registers */ | ||
| 35 | #define TPS65090_INT_STS 0x0 | ||
| 36 | #define TPS65090_INT_STS2 0x1 | ||
| 37 | |||
| 38 | /* interrupt mask registers */ | ||
| 39 | #define TPS65090_INT_MSK 0x2 | ||
| 40 | #define TPS65090_INT_MSK2 0x3 | ||
| 41 | |||
| 42 | struct tps65090_irq_data { | ||
| 43 | u8 mask_reg; | ||
| 44 | u8 mask_pos; | ||
| 45 | }; | ||
| 46 | |||
| 47 | #define TPS65090_IRQ(_reg, _mask_pos) \ | ||
| 48 | { \ | ||
| 49 | .mask_reg = (_reg), \ | ||
| 50 | .mask_pos = (_mask_pos), \ | ||
| 51 | } | ||
| 52 | |||
| 53 | static const struct tps65090_irq_data tps65090_irqs[] = { | ||
| 54 | [0] = TPS65090_IRQ(0, 0), | ||
| 55 | [1] = TPS65090_IRQ(0, 1), | ||
| 56 | [2] = TPS65090_IRQ(0, 2), | ||
| 57 | [3] = TPS65090_IRQ(0, 3), | ||
| 58 | [4] = TPS65090_IRQ(0, 4), | ||
| 59 | [5] = TPS65090_IRQ(0, 5), | ||
| 60 | [6] = TPS65090_IRQ(0, 6), | ||
| 61 | [7] = TPS65090_IRQ(0, 7), | ||
| 62 | [8] = TPS65090_IRQ(1, 0), | ||
| 63 | [9] = TPS65090_IRQ(1, 1), | ||
| 64 | [10] = TPS65090_IRQ(1, 2), | ||
| 65 | [11] = TPS65090_IRQ(1, 3), | ||
| 66 | [12] = TPS65090_IRQ(1, 4), | ||
| 67 | [13] = TPS65090_IRQ(1, 5), | ||
| 68 | [14] = TPS65090_IRQ(1, 6), | ||
| 69 | [15] = TPS65090_IRQ(1, 7), | ||
| 70 | }; | ||
| 71 | |||
| 72 | static struct mfd_cell tps65090s[] = { | ||
| 73 | { | ||
| 74 | .name = "tps65910-pmic", | ||
| 75 | }, | ||
| 76 | { | ||
| 77 | .name = "tps65910-regulator", | ||
| 78 | }, | ||
| 79 | }; | ||
| 80 | |||
| 81 | struct tps65090 { | ||
| 82 | struct mutex lock; | ||
| 83 | struct device *dev; | ||
| 84 | struct i2c_client *client; | ||
| 85 | struct regmap *rmap; | ||
| 86 | struct irq_chip irq_chip; | ||
| 87 | struct mutex irq_lock; | ||
| 88 | int irq_base; | ||
| 89 | unsigned int id; | ||
| 90 | }; | ||
| 91 | |||
| 92 | int tps65090_write(struct device *dev, int reg, uint8_t val) | ||
| 93 | { | ||
| 94 | struct tps65090 *tps = dev_get_drvdata(dev); | ||
| 95 | return regmap_write(tps->rmap, reg, val); | ||
| 96 | } | ||
| 97 | EXPORT_SYMBOL_GPL(tps65090_write); | ||
| 98 | |||
| 99 | int tps65090_read(struct device *dev, int reg, uint8_t *val) | ||
| 100 | { | ||
| 101 | struct tps65090 *tps = dev_get_drvdata(dev); | ||
| 102 | unsigned int temp_val; | ||
| 103 | int ret; | ||
| 104 | ret = regmap_read(tps->rmap, reg, &temp_val); | ||
| 105 | if (!ret) | ||
| 106 | *val = temp_val; | ||
| 107 | return ret; | ||
| 108 | } | ||
| 109 | EXPORT_SYMBOL_GPL(tps65090_read); | ||
| 110 | |||
| 111 | int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num) | ||
| 112 | { | ||
| 113 | struct tps65090 *tps = dev_get_drvdata(dev); | ||
| 114 | return regmap_update_bits(tps->rmap, reg, BIT(bit_num), ~0u); | ||
| 115 | } | ||
| 116 | EXPORT_SYMBOL_GPL(tps65090_set_bits); | ||
| 117 | |||
| 118 | int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num) | ||
| 119 | { | ||
| 120 | struct tps65090 *tps = dev_get_drvdata(dev); | ||
| 121 | return regmap_update_bits(tps->rmap, reg, BIT(bit_num), 0u); | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL_GPL(tps65090_clr_bits); | ||
| 124 | |||
| 125 | static void tps65090_irq_lock(struct irq_data *data) | ||
| 126 | { | ||
| 127 | struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data); | ||
| 128 | |||
| 129 | mutex_lock(&tps65090->irq_lock); | ||
| 130 | } | ||
| 131 | |||
| 132 | static void tps65090_irq_mask(struct irq_data *irq_data) | ||
| 133 | { | ||
| 134 | struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data); | ||
| 135 | unsigned int __irq = irq_data->hwirq; | ||
| 136 | const struct tps65090_irq_data *data = &tps65090_irqs[__irq]; | ||
| 137 | |||
| 138 | tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg), | ||
| 139 | data->mask_pos); | ||
| 140 | } | ||
| 141 | |||
| 142 | static void tps65090_irq_unmask(struct irq_data *irq_data) | ||
| 143 | { | ||
| 144 | struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data); | ||
| 145 | unsigned int __irq = irq_data->irq - tps65090->irq_base; | ||
| 146 | const struct tps65090_irq_data *data = &tps65090_irqs[__irq]; | ||
| 147 | |||
| 148 | tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg), | ||
| 149 | data->mask_pos); | ||
| 150 | } | ||
| 151 | |||
| 152 | static void tps65090_irq_sync_unlock(struct irq_data *data) | ||
| 153 | { | ||
| 154 | struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data); | ||
| 155 | |||
| 156 | mutex_unlock(&tps65090->irq_lock); | ||
| 157 | } | ||
| 158 | |||
| 159 | static irqreturn_t tps65090_irq(int irq, void *data) | ||
| 160 | { | ||
| 161 | struct tps65090 *tps65090 = data; | ||
| 162 | int ret = 0; | ||
| 163 | u8 status, mask; | ||
| 164 | unsigned long int acks = 0; | ||
| 165 | int i; | ||
| 166 | |||
| 167 | for (i = 0; i < NUM_INT_REG; i++) { | ||
| 168 | ret = tps65090_read(tps65090->dev, TPS65090_INT_MSK + i, &mask); | ||
| 169 | if (ret < 0) { | ||
| 170 | dev_err(tps65090->dev, | ||
| 171 | "failed to read mask reg [addr:%d]\n", | ||
| 172 | TPS65090_INT_MSK + i); | ||
| 173 | return IRQ_NONE; | ||
| 174 | } | ||
| 175 | ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + i, | ||
| 176 | &status); | ||
| 177 | if (ret < 0) { | ||
| 178 | dev_err(tps65090->dev, | ||
| 179 | "failed to read status reg [addr:%d]\n", | ||
| 180 | TPS65090_INT_STS + i); | ||
| 181 | return IRQ_NONE; | ||
| 182 | } | ||
| 183 | if (status) { | ||
| 184 | /* Ack only those interrupts which are not masked */ | ||
| 185 | status &= (~mask); | ||
| 186 | ret = tps65090_write(tps65090->dev, | ||
| 187 | TPS65090_INT_STS + i, status); | ||
| 188 | if (ret < 0) { | ||
| 189 | dev_err(tps65090->dev, | ||
| 190 | "failed to write interrupt status\n"); | ||
| 191 | return IRQ_NONE; | ||
| 192 | } | ||
| 193 | acks |= (status << (i * 8)); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | for_each_set_bit(i, &acks, ARRAY_SIZE(tps65090_irqs)) | ||
| 198 | handle_nested_irq(tps65090->irq_base + i); | ||
| 199 | return acks ? IRQ_HANDLED : IRQ_NONE; | ||
| 200 | } | ||
| 201 | |||
| 202 | static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq, | ||
| 203 | int irq_base) | ||
| 204 | { | ||
| 205 | int i, ret; | ||
| 206 | |||
| 207 | if (!irq_base) { | ||
| 208 | dev_err(tps65090->dev, "IRQ base not set\n"); | ||
| 209 | return -EINVAL; | ||
| 210 | } | ||
| 211 | |||
| 212 | mutex_init(&tps65090->irq_lock); | ||
| 213 | |||
| 214 | for (i = 0; i < NUM_INT_REG; i++) | ||
| 215 | tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, 0xFF); | ||
| 216 | |||
| 217 | for (i = 0; i < NUM_INT_REG; i++) | ||
| 218 | tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff); | ||
| 219 | |||
| 220 | tps65090->irq_base = irq_base; | ||
| 221 | tps65090->irq_chip.name = "tps65090"; | ||
| 222 | tps65090->irq_chip.irq_mask = tps65090_irq_mask; | ||
| 223 | tps65090->irq_chip.irq_unmask = tps65090_irq_unmask; | ||
| 224 | tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock; | ||
| 225 | tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock; | ||
| 226 | |||
| 227 | for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) { | ||
| 228 | int __irq = i + tps65090->irq_base; | ||
| 229 | irq_set_chip_data(__irq, tps65090); | ||
| 230 | irq_set_chip_and_handler(__irq, &tps65090->irq_chip, | ||
| 231 | handle_simple_irq); | ||
| 232 | irq_set_nested_thread(__irq, 1); | ||
| 233 | #ifdef CONFIG_ARM | ||
| 234 | set_irq_flags(__irq, IRQF_VALID); | ||
| 235 | #endif | ||
| 236 | } | ||
| 237 | |||
| 238 | ret = request_threaded_irq(irq, NULL, tps65090_irq, IRQF_ONESHOT, | ||
| 239 | "tps65090", tps65090); | ||
| 240 | if (!ret) { | ||
| 241 | device_init_wakeup(tps65090->dev, 1); | ||
| 242 | enable_irq_wake(irq); | ||
| 243 | } | ||
| 244 | |||
| 245 | return ret; | ||
| 246 | } | ||
| 247 | |||
| 248 | static bool is_volatile_reg(struct device *dev, unsigned int reg) | ||
| 249 | { | ||
| 250 | if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS)) | ||
| 251 | return true; | ||
| 252 | else | ||
| 253 | return false; | ||
| 254 | } | ||
| 255 | |||
| 256 | static const struct regmap_config tps65090_regmap_config = { | ||
| 257 | .reg_bits = 8, | ||
| 258 | .val_bits = 8, | ||
| 259 | .max_register = TOTAL_NUM_REG, | ||
| 260 | .num_reg_defaults_raw = TOTAL_NUM_REG, | ||
| 261 | .cache_type = REGCACHE_RBTREE, | ||
| 262 | .volatile_reg = is_volatile_reg, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static int __devinit tps65090_i2c_probe(struct i2c_client *client, | ||
| 266 | const struct i2c_device_id *id) | ||
| 267 | { | ||
| 268 | struct tps65090_platform_data *pdata = client->dev.platform_data; | ||
| 269 | struct tps65090 *tps65090; | ||
| 270 | int ret; | ||
| 271 | |||
| 272 | if (!pdata) { | ||
| 273 | dev_err(&client->dev, "tps65090 requires platform data\n"); | ||
| 274 | return -EINVAL; | ||
| 275 | } | ||
| 276 | |||
| 277 | tps65090 = devm_kzalloc(&client->dev, sizeof(struct tps65090), | ||
| 278 | GFP_KERNEL); | ||
| 279 | if (tps65090 == NULL) | ||
| 280 | return -ENOMEM; | ||
| 281 | |||
| 282 | tps65090->client = client; | ||
| 283 | tps65090->dev = &client->dev; | ||
| 284 | i2c_set_clientdata(client, tps65090); | ||
| 285 | |||
| 286 | mutex_init(&tps65090->lock); | ||
| 287 | |||
| 288 | if (client->irq) { | ||
| 289 | ret = tps65090_irq_init(tps65090, client->irq, pdata->irq_base); | ||
| 290 | if (ret) { | ||
| 291 | dev_err(&client->dev, "IRQ init failed with err: %d\n", | ||
| 292 | ret); | ||
| 293 | goto err_exit; | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | tps65090->rmap = regmap_init_i2c(tps65090->client, | ||
| 298 | &tps65090_regmap_config); | ||
| 299 | if (IS_ERR(tps65090->rmap)) { | ||
| 300 | dev_err(&client->dev, "regmap_init failed with err: %ld\n", | ||
| 301 | PTR_ERR(tps65090->rmap)); | ||
| 302 | goto err_irq_exit; | ||
| 303 | }; | ||
| 304 | |||
| 305 | ret = mfd_add_devices(tps65090->dev, -1, tps65090s, | ||
| 306 | ARRAY_SIZE(tps65090s), NULL, 0); | ||
| 307 | if (ret) { | ||
| 308 | dev_err(&client->dev, "add mfd devices failed with err: %d\n", | ||
| 309 | ret); | ||
| 310 | goto err_regmap_exit; | ||
| 311 | } | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | |||
| 315 | err_regmap_exit: | ||
| 316 | regmap_exit(tps65090->rmap); | ||
| 317 | |||
| 318 | err_irq_exit: | ||
| 319 | if (client->irq) | ||
| 320 | free_irq(client->irq, tps65090); | ||
| 321 | err_exit: | ||
| 322 | return ret; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int __devexit tps65090_i2c_remove(struct i2c_client *client) | ||
| 326 | { | ||
| 327 | struct tps65090 *tps65090 = i2c_get_clientdata(client); | ||
| 328 | |||
| 329 | mfd_remove_devices(tps65090->dev); | ||
| 330 | regmap_exit(tps65090->rmap); | ||
| 331 | if (client->irq) | ||
| 332 | free_irq(client->irq, tps65090); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | #ifdef CONFIG_PM | ||
| 338 | static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state) | ||
| 339 | { | ||
| 340 | if (client->irq) | ||
| 341 | disable_irq(client->irq); | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | static int tps65090_i2c_resume(struct i2c_client *client) | ||
| 346 | { | ||
| 347 | if (client->irq) | ||
| 348 | enable_irq(client->irq); | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | #endif | ||
| 352 | |||
| 353 | static const struct i2c_device_id tps65090_id_table[] = { | ||
| 354 | { "tps65090", 0 }, | ||
| 355 | { }, | ||
| 356 | }; | ||
| 357 | MODULE_DEVICE_TABLE(i2c, tps65090_id_table); | ||
| 358 | |||
| 359 | static struct i2c_driver tps65090_driver = { | ||
| 360 | .driver = { | ||
| 361 | .name = "tps65090", | ||
| 362 | .owner = THIS_MODULE, | ||
| 363 | }, | ||
| 364 | .probe = tps65090_i2c_probe, | ||
| 365 | .remove = __devexit_p(tps65090_i2c_remove), | ||
| 366 | #ifdef CONFIG_PM | ||
| 367 | .suspend = tps65090_i2c_suspend, | ||
| 368 | .resume = tps65090_i2c_resume, | ||
| 369 | #endif | ||
| 370 | .id_table = tps65090_id_table, | ||
| 371 | }; | ||
| 372 | |||
| 373 | static int __init tps65090_init(void) | ||
| 374 | { | ||
| 375 | return i2c_add_driver(&tps65090_driver); | ||
| 376 | } | ||
| 377 | subsys_initcall(tps65090_init); | ||
| 378 | |||
| 379 | static void __exit tps65090_exit(void) | ||
| 380 | { | ||
| 381 | i2c_del_driver(&tps65090_driver); | ||
| 382 | } | ||
| 383 | module_exit(tps65090_exit); | ||
| 384 | |||
| 385 | MODULE_DESCRIPTION("TPS65090 core driver"); | ||
| 386 | MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); | ||
| 387 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c new file mode 100644 index 000000000000..f7d854e4cc62 --- /dev/null +++ b/drivers/mfd/tps65217.c | |||
| @@ -0,0 +1,242 @@ | |||
| 1 | /* | ||
| 2 | * tps65217.c | ||
| 3 | * | ||
| 4 | * TPS65217 chip family multi-function driver | ||
| 5 | * | ||
| 6 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License as | ||
| 10 | * published by the Free Software Foundation version 2. | ||
| 11 | * | ||
| 12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 13 | * kind, whether express or implied; without even the implied warranty | ||
| 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/device.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/i2c.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/regmap.h> | ||
| 26 | #include <linux/err.h> | ||
| 27 | |||
| 28 | #include <linux/mfd/core.h> | ||
| 29 | #include <linux/mfd/tps65217.h> | ||
| 30 | |||
| 31 | /** | ||
| 32 | * tps65217_reg_read: Read a single tps65217 register. | ||
| 33 | * | ||
| 34 | * @tps: Device to read from. | ||
| 35 | * @reg: Register to read. | ||
| 36 | * @val: Contians the value | ||
| 37 | */ | ||
| 38 | int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, | ||
| 39 | unsigned int *val) | ||
| 40 | { | ||
| 41 | return regmap_read(tps->regmap, reg, val); | ||
| 42 | } | ||
| 43 | EXPORT_SYMBOL_GPL(tps65217_reg_read); | ||
| 44 | |||
| 45 | /** | ||
| 46 | * tps65217_reg_write: Write a single tps65217 register. | ||
| 47 | * | ||
| 48 | * @tps65217: Device to write to. | ||
| 49 | * @reg: Register to write to. | ||
| 50 | * @val: Value to write. | ||
| 51 | * @level: Password protected level | ||
| 52 | */ | ||
| 53 | int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, | ||
| 54 | unsigned int val, unsigned int level) | ||
| 55 | { | ||
| 56 | int ret; | ||
| 57 | unsigned int xor_reg_val; | ||
| 58 | |||
| 59 | switch (level) { | ||
| 60 | case TPS65217_PROTECT_NONE: | ||
| 61 | return regmap_write(tps->regmap, reg, val); | ||
| 62 | case TPS65217_PROTECT_L1: | ||
| 63 | xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK; | ||
| 64 | ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, | ||
| 65 | xor_reg_val); | ||
| 66 | if (ret < 0) | ||
| 67 | return ret; | ||
| 68 | |||
| 69 | return regmap_write(tps->regmap, reg, val); | ||
| 70 | case TPS65217_PROTECT_L2: | ||
| 71 | xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK; | ||
| 72 | ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, | ||
| 73 | xor_reg_val); | ||
| 74 | if (ret < 0) | ||
| 75 | return ret; | ||
| 76 | ret = regmap_write(tps->regmap, reg, val); | ||
| 77 | if (ret < 0) | ||
| 78 | return ret; | ||
| 79 | ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, | ||
| 80 | xor_reg_val); | ||
| 81 | if (ret < 0) | ||
| 82 | return ret; | ||
| 83 | return regmap_write(tps->regmap, reg, val); | ||
| 84 | default: | ||
| 85 | return -EINVAL; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(tps65217_reg_write); | ||
| 89 | |||
| 90 | /** | ||
| 91 | * tps65217_update_bits: Modify bits w.r.t mask, val and level. | ||
| 92 | * | ||
| 93 | * @tps65217: Device to write to. | ||
| 94 | * @reg: Register to read-write to. | ||
| 95 | * @mask: Mask. | ||
| 96 | * @val: Value to write. | ||
| 97 | * @level: Password protected level | ||
| 98 | */ | ||
| 99 | int tps65217_update_bits(struct tps65217 *tps, unsigned int reg, | ||
| 100 | unsigned int mask, unsigned int val, unsigned int level) | ||
| 101 | { | ||
| 102 | int ret; | ||
| 103 | unsigned int data; | ||
| 104 | |||
| 105 | ret = tps65217_reg_read(tps, reg, &data); | ||
| 106 | if (ret) { | ||
| 107 | dev_err(tps->dev, "Read from reg 0x%x failed\n", reg); | ||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | |||
| 111 | data &= ~mask; | ||
| 112 | data |= val & mask; | ||
| 113 | |||
| 114 | ret = tps65217_reg_write(tps, reg, data, level); | ||
| 115 | if (ret) | ||
| 116 | dev_err(tps->dev, "Write for reg 0x%x failed\n", reg); | ||
| 117 | |||
| 118 | return ret; | ||
| 119 | } | ||
| 120 | |||
| 121 | int tps65217_set_bits(struct tps65217 *tps, unsigned int reg, | ||
| 122 | unsigned int mask, unsigned int val, unsigned int level) | ||
| 123 | { | ||
| 124 | return tps65217_update_bits(tps, reg, mask, val, level); | ||
| 125 | } | ||
| 126 | EXPORT_SYMBOL_GPL(tps65217_set_bits); | ||
| 127 | |||
| 128 | int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, | ||
| 129 | unsigned int mask, unsigned int level) | ||
| 130 | { | ||
| 131 | return tps65217_update_bits(tps, reg, mask, 0, level); | ||
| 132 | } | ||
| 133 | EXPORT_SYMBOL_GPL(tps65217_clear_bits); | ||
| 134 | |||
| 135 | static struct regmap_config tps65217_regmap_config = { | ||
| 136 | .reg_bits = 8, | ||
| 137 | .val_bits = 8, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static int __devinit tps65217_probe(struct i2c_client *client, | ||
| 141 | const struct i2c_device_id *ids) | ||
| 142 | { | ||
| 143 | struct tps65217 *tps; | ||
| 144 | struct tps65217_board *pdata = client->dev.platform_data; | ||
| 145 | int i, ret; | ||
| 146 | unsigned int version; | ||
| 147 | |||
| 148 | tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); | ||
| 149 | if (!tps) | ||
| 150 | return -ENOMEM; | ||
| 151 | |||
| 152 | tps->pdata = pdata; | ||
| 153 | tps->regmap = regmap_init_i2c(client, &tps65217_regmap_config); | ||
| 154 | if (IS_ERR(tps->regmap)) { | ||
| 155 | ret = PTR_ERR(tps->regmap); | ||
| 156 | dev_err(tps->dev, "Failed to allocate register map: %d\n", | ||
| 157 | ret); | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | i2c_set_clientdata(client, tps); | ||
| 162 | tps->dev = &client->dev; | ||
| 163 | |||
| 164 | ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); | ||
| 165 | if (ret < 0) { | ||
| 166 | dev_err(tps->dev, "Failed to read revision" | ||
| 167 | " register: %d\n", ret); | ||
| 168 | goto err_regmap; | ||
| 169 | } | ||
| 170 | |||
| 171 | dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n", | ||
| 172 | (version & TPS65217_CHIPID_CHIP_MASK) >> 4, | ||
| 173 | version & TPS65217_CHIPID_REV_MASK); | ||
| 174 | |||
| 175 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { | ||
| 176 | struct platform_device *pdev; | ||
| 177 | |||
| 178 | pdev = platform_device_alloc("tps65217-pmic", i); | ||
| 179 | if (!pdev) { | ||
| 180 | dev_err(tps->dev, "Cannot create regulator %d\n", i); | ||
| 181 | continue; | ||
| 182 | } | ||
| 183 | |||
| 184 | pdev->dev.parent = tps->dev; | ||
| 185 | platform_device_add_data(pdev, &pdata->tps65217_init_data[i], | ||
| 186 | sizeof(pdata->tps65217_init_data[i])); | ||
| 187 | tps->regulator_pdev[i] = pdev; | ||
| 188 | |||
| 189 | platform_device_add(pdev); | ||
| 190 | } | ||
| 191 | |||
| 192 | return 0; | ||
| 193 | |||
| 194 | err_regmap: | ||
| 195 | regmap_exit(tps->regmap); | ||
| 196 | |||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int __devexit tps65217_remove(struct i2c_client *client) | ||
| 201 | { | ||
| 202 | struct tps65217 *tps = i2c_get_clientdata(client); | ||
| 203 | int i; | ||
| 204 | |||
| 205 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) | ||
| 206 | platform_device_unregister(tps->regulator_pdev[i]); | ||
| 207 | |||
| 208 | regmap_exit(tps->regmap); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static const struct i2c_device_id tps65217_id_table[] = { | ||
| 214 | {"tps65217", 0xF0}, | ||
| 215 | {/* end of list */} | ||
| 216 | }; | ||
| 217 | MODULE_DEVICE_TABLE(i2c, tps65217_id_table); | ||
| 218 | |||
| 219 | static struct i2c_driver tps65217_driver = { | ||
| 220 | .driver = { | ||
| 221 | .name = "tps65217", | ||
| 222 | }, | ||
| 223 | .id_table = tps65217_id_table, | ||
| 224 | .probe = tps65217_probe, | ||
| 225 | .remove = __devexit_p(tps65217_remove), | ||
| 226 | }; | ||
| 227 | |||
| 228 | static int __init tps65217_init(void) | ||
| 229 | { | ||
| 230 | return i2c_add_driver(&tps65217_driver); | ||
| 231 | } | ||
| 232 | subsys_initcall(tps65217_init); | ||
| 233 | |||
| 234 | static void __exit tps65217_exit(void) | ||
| 235 | { | ||
| 236 | i2c_del_driver(&tps65217_driver); | ||
| 237 | } | ||
| 238 | module_exit(tps65217_exit); | ||
| 239 | |||
| 240 | MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>"); | ||
| 241 | MODULE_DESCRIPTION("TPS65217 chip family multi-function driver"); | ||
| 242 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/tps65910-irq.c b/drivers/mfd/tps65910-irq.c index 95c0d7978bec..c9ed5c00a621 100644 --- a/drivers/mfd/tps65910-irq.c +++ b/drivers/mfd/tps65910-irq.c | |||
| @@ -145,12 +145,23 @@ static void tps65910_irq_disable(struct irq_data *data) | |||
| 145 | tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq)); | 145 | tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq)); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | #ifdef CONFIG_PM_SLEEP | ||
| 149 | static int tps65910_irq_set_wake(struct irq_data *data, unsigned int enable) | ||
| 150 | { | ||
| 151 | struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); | ||
| 152 | return irq_set_irq_wake(tps65910->chip_irq, enable); | ||
| 153 | } | ||
| 154 | #else | ||
| 155 | #define tps65910_irq_set_wake NULL | ||
| 156 | #endif | ||
| 157 | |||
| 148 | static struct irq_chip tps65910_irq_chip = { | 158 | static struct irq_chip tps65910_irq_chip = { |
| 149 | .name = "tps65910", | 159 | .name = "tps65910", |
| 150 | .irq_bus_lock = tps65910_irq_lock, | 160 | .irq_bus_lock = tps65910_irq_lock, |
| 151 | .irq_bus_sync_unlock = tps65910_irq_sync_unlock, | 161 | .irq_bus_sync_unlock = tps65910_irq_sync_unlock, |
| 152 | .irq_disable = tps65910_irq_disable, | 162 | .irq_disable = tps65910_irq_disable, |
| 153 | .irq_enable = tps65910_irq_enable, | 163 | .irq_enable = tps65910_irq_enable, |
| 164 | .irq_set_wake = tps65910_irq_set_wake, | ||
| 154 | }; | 165 | }; |
| 155 | 166 | ||
| 156 | int tps65910_irq_init(struct tps65910 *tps65910, int irq, | 167 | int tps65910_irq_init(struct tps65910 *tps65910, int irq, |
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 4392f6bca156..bf2b25ebf2ca 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c | |||
| @@ -16,10 +16,12 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/err.h> | ||
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 20 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
| 21 | #include <linux/gpio.h> | 22 | #include <linux/gpio.h> |
| 22 | #include <linux/mfd/core.h> | 23 | #include <linux/mfd/core.h> |
| 24 | #include <linux/regmap.h> | ||
| 23 | #include <linux/mfd/tps65910.h> | 25 | #include <linux/mfd/tps65910.h> |
| 24 | 26 | ||
| 25 | static struct mfd_cell tps65910s[] = { | 27 | static struct mfd_cell tps65910s[] = { |
| @@ -38,99 +40,56 @@ static struct mfd_cell tps65910s[] = { | |||
| 38 | static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, | 40 | static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, |
| 39 | int bytes, void *dest) | 41 | int bytes, void *dest) |
| 40 | { | 42 | { |
| 41 | struct i2c_client *i2c = tps65910->i2c_client; | 43 | return regmap_bulk_read(tps65910->regmap, reg, dest, bytes); |
| 42 | struct i2c_msg xfer[2]; | ||
| 43 | int ret; | ||
| 44 | |||
| 45 | /* Write register */ | ||
| 46 | xfer[0].addr = i2c->addr; | ||
| 47 | xfer[0].flags = 0; | ||
| 48 | xfer[0].len = 1; | ||
| 49 | xfer[0].buf = ® | ||
| 50 | |||
| 51 | /* Read data */ | ||
| 52 | xfer[1].addr = i2c->addr; | ||
| 53 | xfer[1].flags = I2C_M_RD; | ||
| 54 | xfer[1].len = bytes; | ||
| 55 | xfer[1].buf = dest; | ||
| 56 | |||
| 57 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
| 58 | if (ret == 2) | ||
| 59 | ret = 0; | ||
| 60 | else if (ret >= 0) | ||
| 61 | ret = -EIO; | ||
| 62 | |||
| 63 | return ret; | ||
| 64 | } | 44 | } |
| 65 | 45 | ||
| 66 | static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, | 46 | static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, |
| 67 | int bytes, void *src) | 47 | int bytes, void *src) |
| 68 | { | 48 | { |
| 69 | struct i2c_client *i2c = tps65910->i2c_client; | 49 | return regmap_bulk_write(tps65910->regmap, reg, src, bytes); |
| 70 | /* we add 1 byte for device register */ | ||
| 71 | u8 msg[TPS65910_MAX_REGISTER + 1]; | ||
| 72 | int ret; | ||
| 73 | |||
| 74 | if (bytes > TPS65910_MAX_REGISTER) | ||
| 75 | return -EINVAL; | ||
| 76 | |||
| 77 | msg[0] = reg; | ||
| 78 | memcpy(&msg[1], src, bytes); | ||
| 79 | |||
| 80 | ret = i2c_master_send(i2c, msg, bytes + 1); | ||
| 81 | if (ret < 0) | ||
| 82 | return ret; | ||
| 83 | if (ret != bytes + 1) | ||
| 84 | return -EIO; | ||
| 85 | return 0; | ||
| 86 | } | 50 | } |
| 87 | 51 | ||
| 88 | int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) | 52 | int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) |
| 89 | { | 53 | { |
| 90 | u8 data; | 54 | return regmap_update_bits(tps65910->regmap, reg, mask, mask); |
| 91 | int err; | ||
| 92 | |||
| 93 | mutex_lock(&tps65910->io_mutex); | ||
| 94 | err = tps65910_i2c_read(tps65910, reg, 1, &data); | ||
| 95 | if (err) { | ||
| 96 | dev_err(tps65910->dev, "read from reg %x failed\n", reg); | ||
| 97 | goto out; | ||
| 98 | } | ||
| 99 | |||
| 100 | data |= mask; | ||
| 101 | err = tps65910_i2c_write(tps65910, reg, 1, &data); | ||
| 102 | if (err) | ||
| 103 | dev_err(tps65910->dev, "write to reg %x failed\n", reg); | ||
| 104 | |||
| 105 | out: | ||
| 106 | mutex_unlock(&tps65910->io_mutex); | ||
| 107 | return err; | ||
| 108 | } | 55 | } |
| 109 | EXPORT_SYMBOL_GPL(tps65910_set_bits); | 56 | EXPORT_SYMBOL_GPL(tps65910_set_bits); |
| 110 | 57 | ||
| 111 | int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) | 58 | int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) |
| 112 | { | 59 | { |
| 113 | u8 data; | 60 | return regmap_update_bits(tps65910->regmap, reg, mask, 0); |
| 114 | int err; | ||
| 115 | |||
| 116 | mutex_lock(&tps65910->io_mutex); | ||
| 117 | err = tps65910_i2c_read(tps65910, reg, 1, &data); | ||
| 118 | if (err) { | ||
| 119 | dev_err(tps65910->dev, "read from reg %x failed\n", reg); | ||
| 120 | goto out; | ||
| 121 | } | ||
| 122 | |||
| 123 | data &= ~mask; | ||
| 124 | err = tps65910_i2c_write(tps65910, reg, 1, &data); | ||
| 125 | if (err) | ||
| 126 | dev_err(tps65910->dev, "write to reg %x failed\n", reg); | ||
| 127 | |||
| 128 | out: | ||
| 129 | mutex_unlock(&tps65910->io_mutex); | ||
| 130 | return err; | ||
| 131 | } | 61 | } |
| 132 | EXPORT_SYMBOL_GPL(tps65910_clear_bits); | 62 | EXPORT_SYMBOL_GPL(tps65910_clear_bits); |
| 133 | 63 | ||
| 64 | static bool is_volatile_reg(struct device *dev, unsigned int reg) | ||
| 65 | { | ||
| 66 | struct tps65910 *tps65910 = dev_get_drvdata(dev); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Caching all regulator registers. | ||
| 70 | * All regualator register address range is same for | ||
| 71 | * TPS65910 and TPS65911 | ||
| 72 | */ | ||
| 73 | if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) { | ||
| 74 | /* Check for non-existing register */ | ||
| 75 | if (tps65910_chip_id(tps65910) == TPS65910) | ||
| 76 | if ((reg == TPS65911_VDDCTRL_OP) || | ||
| 77 | (reg == TPS65911_VDDCTRL_SR)) | ||
| 78 | return true; | ||
| 79 | return false; | ||
| 80 | } | ||
| 81 | return true; | ||
| 82 | } | ||
| 83 | |||
| 84 | static const struct regmap_config tps65910_regmap_config = { | ||
| 85 | .reg_bits = 8, | ||
| 86 | .val_bits = 8, | ||
| 87 | .volatile_reg = is_volatile_reg, | ||
| 88 | .max_register = TPS65910_MAX_REGISTER, | ||
| 89 | .num_reg_defaults_raw = TPS65910_MAX_REGISTER, | ||
| 90 | .cache_type = REGCACHE_RBTREE, | ||
| 91 | }; | ||
| 92 | |||
| 134 | static int tps65910_i2c_probe(struct i2c_client *i2c, | 93 | static int tps65910_i2c_probe(struct i2c_client *i2c, |
| 135 | const struct i2c_device_id *id) | 94 | const struct i2c_device_id *id) |
| 136 | { | 95 | { |
| @@ -161,6 +120,13 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, | |||
| 161 | tps65910->write = tps65910_i2c_write; | 120 | tps65910->write = tps65910_i2c_write; |
| 162 | mutex_init(&tps65910->io_mutex); | 121 | mutex_init(&tps65910->io_mutex); |
| 163 | 122 | ||
| 123 | tps65910->regmap = regmap_init_i2c(i2c, &tps65910_regmap_config); | ||
| 124 | if (IS_ERR(tps65910->regmap)) { | ||
| 125 | ret = PTR_ERR(tps65910->regmap); | ||
| 126 | dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret); | ||
| 127 | goto regmap_err; | ||
| 128 | } | ||
| 129 | |||
| 164 | ret = mfd_add_devices(tps65910->dev, -1, | 130 | ret = mfd_add_devices(tps65910->dev, -1, |
| 165 | tps65910s, ARRAY_SIZE(tps65910s), | 131 | tps65910s, ARRAY_SIZE(tps65910s), |
| 166 | NULL, 0); | 132 | NULL, 0); |
| @@ -178,6 +144,8 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, | |||
| 178 | return ret; | 144 | return ret; |
| 179 | 145 | ||
| 180 | err: | 146 | err: |
| 147 | regmap_exit(tps65910->regmap); | ||
| 148 | regmap_err: | ||
| 181 | kfree(tps65910); | 149 | kfree(tps65910); |
| 182 | kfree(init_data); | 150 | kfree(init_data); |
| 183 | return ret; | 151 | return ret; |
| @@ -189,6 +157,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c) | |||
| 189 | 157 | ||
| 190 | tps65910_irq_exit(tps65910); | 158 | tps65910_irq_exit(tps65910); |
| 191 | mfd_remove_devices(tps65910->dev); | 159 | mfd_remove_devices(tps65910->dev); |
| 160 | regmap_exit(tps65910->regmap); | ||
| 192 | kfree(tps65910); | 161 | kfree(tps65910); |
| 193 | 162 | ||
| 194 | return 0; | 163 | return 0; |
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 806680d1bbb4..7c2267e71f8b 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
| @@ -46,9 +46,7 @@ | |||
| 46 | #include <linux/i2c.h> | 46 | #include <linux/i2c.h> |
| 47 | #include <linux/i2c/twl.h> | 47 | #include <linux/i2c/twl.h> |
| 48 | 48 | ||
| 49 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | 49 | #include "twl-core.h" |
| 50 | #include <plat/cpu.h> | ||
| 51 | #endif | ||
| 52 | 50 | ||
| 53 | /* | 51 | /* |
| 54 | * The TWL4030 "Triton 2" is one of a family of a multi-function "Power | 52 | * The TWL4030 "Triton 2" is one of a family of a multi-function "Power |
| @@ -116,8 +114,8 @@ | |||
| 116 | #define twl_has_watchdog() false | 114 | #define twl_has_watchdog() false |
| 117 | #endif | 115 | #endif |
| 118 | 116 | ||
| 119 | #if defined(CONFIG_MFD_TWL4030_AUDIO) || defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) ||\ | 117 | #if defined(CONFIG_MFD_TWL4030_AUDIO) || \ |
| 120 | defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE) | 118 | defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) |
| 121 | #define twl_has_codec() true | 119 | #define twl_has_codec() true |
| 122 | #else | 120 | #else |
| 123 | #define twl_has_codec() false | 121 | #define twl_has_codec() false |
| @@ -147,12 +145,10 @@ | |||
| 147 | #define SUB_CHIP_ID1 1 | 145 | #define SUB_CHIP_ID1 1 |
| 148 | #define SUB_CHIP_ID2 2 | 146 | #define SUB_CHIP_ID2 2 |
| 149 | #define SUB_CHIP_ID3 3 | 147 | #define SUB_CHIP_ID3 3 |
| 148 | #define SUB_CHIP_ID_INVAL 0xff | ||
| 150 | 149 | ||
| 151 | #define TWL_MODULE_LAST TWL4030_MODULE_LAST | 150 | #define TWL_MODULE_LAST TWL4030_MODULE_LAST |
| 152 | 151 | ||
| 153 | #define TWL4030_NR_IRQS 34 /* core:8, power:8, gpio: 18 */ | ||
| 154 | #define TWL6030_NR_IRQS 20 | ||
| 155 | |||
| 156 | /* Base Address defns for twl4030_map[] */ | 152 | /* Base Address defns for twl4030_map[] */ |
| 157 | 153 | ||
| 158 | /* subchip/slave 0 - USB ID */ | 154 | /* subchip/slave 0 - USB ID */ |
| @@ -314,7 +310,7 @@ static struct twl_mapping twl6030_map[] = { | |||
| 314 | * so they continue to match the order in this table. | 310 | * so they continue to match the order in this table. |
| 315 | */ | 311 | */ |
| 316 | { SUB_CHIP_ID1, TWL6030_BASEADD_USB }, | 312 | { SUB_CHIP_ID1, TWL6030_BASEADD_USB }, |
| 317 | { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO }, | 313 | { SUB_CHIP_ID_INVAL, TWL6030_BASEADD_AUDIO }, |
| 318 | { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID }, | 314 | { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID }, |
| 319 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | 315 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, |
| 320 | { SUB_CHIP_ID1, TWL6030_BASEADD_PIH }, | 316 | { SUB_CHIP_ID1, TWL6030_BASEADD_PIH }, |
| @@ -376,6 +372,11 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
| 376 | return -EPERM; | 372 | return -EPERM; |
| 377 | } | 373 | } |
| 378 | sid = twl_map[mod_no].sid; | 374 | sid = twl_map[mod_no].sid; |
| 375 | if (unlikely(sid == SUB_CHIP_ID_INVAL)) { | ||
| 376 | pr_err("%s: module %d is not part of the pmic\n", | ||
| 377 | DRIVER_NAME, mod_no); | ||
| 378 | return -EINVAL; | ||
| 379 | } | ||
| 379 | twl = &twl_modules[sid]; | 380 | twl = &twl_modules[sid]; |
| 380 | 381 | ||
| 381 | mutex_lock(&twl->xfer_lock); | 382 | mutex_lock(&twl->xfer_lock); |
| @@ -433,6 +434,11 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
| 433 | return -EPERM; | 434 | return -EPERM; |
| 434 | } | 435 | } |
| 435 | sid = twl_map[mod_no].sid; | 436 | sid = twl_map[mod_no].sid; |
| 437 | if (unlikely(sid == SUB_CHIP_ID_INVAL)) { | ||
| 438 | pr_err("%s: module %d is not part of the pmic\n", | ||
| 439 | DRIVER_NAME, mod_no); | ||
| 440 | return -EINVAL; | ||
| 441 | } | ||
| 436 | twl = &twl_modules[sid]; | 442 | twl = &twl_modules[sid]; |
| 437 | 443 | ||
| 438 | mutex_lock(&twl->xfer_lock); | 444 | mutex_lock(&twl->xfer_lock); |
| @@ -663,7 +669,8 @@ add_regulator(int num, struct regulator_init_data *pdata, | |||
| 663 | */ | 669 | */ |
| 664 | 670 | ||
| 665 | static int | 671 | static int |
| 666 | add_children(struct twl4030_platform_data *pdata, unsigned long features) | 672 | add_children(struct twl4030_platform_data *pdata, unsigned irq_base, |
| 673 | unsigned long features) | ||
| 667 | { | 674 | { |
| 668 | struct device *child; | 675 | struct device *child; |
| 669 | unsigned sub_chip_id; | 676 | unsigned sub_chip_id; |
| @@ -671,7 +678,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 671 | if (twl_has_gpio() && pdata->gpio) { | 678 | if (twl_has_gpio() && pdata->gpio) { |
| 672 | child = add_child(SUB_CHIP_ID1, "twl4030_gpio", | 679 | child = add_child(SUB_CHIP_ID1, "twl4030_gpio", |
| 673 | pdata->gpio, sizeof(*pdata->gpio), | 680 | pdata->gpio, sizeof(*pdata->gpio), |
| 674 | false, pdata->irq_base + GPIO_INTR_OFFSET, 0); | 681 | false, irq_base + GPIO_INTR_OFFSET, 0); |
| 675 | if (IS_ERR(child)) | 682 | if (IS_ERR(child)) |
| 676 | return PTR_ERR(child); | 683 | return PTR_ERR(child); |
| 677 | } | 684 | } |
| @@ -679,7 +686,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 679 | if (twl_has_keypad() && pdata->keypad) { | 686 | if (twl_has_keypad() && pdata->keypad) { |
| 680 | child = add_child(SUB_CHIP_ID2, "twl4030_keypad", | 687 | child = add_child(SUB_CHIP_ID2, "twl4030_keypad", |
| 681 | pdata->keypad, sizeof(*pdata->keypad), | 688 | pdata->keypad, sizeof(*pdata->keypad), |
| 682 | true, pdata->irq_base + KEYPAD_INTR_OFFSET, 0); | 689 | true, irq_base + KEYPAD_INTR_OFFSET, 0); |
| 683 | if (IS_ERR(child)) | 690 | if (IS_ERR(child)) |
| 684 | return PTR_ERR(child); | 691 | return PTR_ERR(child); |
| 685 | } | 692 | } |
| @@ -687,7 +694,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 687 | if (twl_has_madc() && pdata->madc) { | 694 | if (twl_has_madc() && pdata->madc) { |
| 688 | child = add_child(2, "twl4030_madc", | 695 | child = add_child(2, "twl4030_madc", |
| 689 | pdata->madc, sizeof(*pdata->madc), | 696 | pdata->madc, sizeof(*pdata->madc), |
| 690 | true, pdata->irq_base + MADC_INTR_OFFSET, 0); | 697 | true, irq_base + MADC_INTR_OFFSET, 0); |
| 691 | if (IS_ERR(child)) | 698 | if (IS_ERR(child)) |
| 692 | return PTR_ERR(child); | 699 | return PTR_ERR(child); |
| 693 | } | 700 | } |
| @@ -703,7 +710,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 703 | sub_chip_id = twl_map[TWL_MODULE_RTC].sid; | 710 | sub_chip_id = twl_map[TWL_MODULE_RTC].sid; |
| 704 | child = add_child(sub_chip_id, "twl_rtc", | 711 | child = add_child(sub_chip_id, "twl_rtc", |
| 705 | NULL, 0, | 712 | NULL, 0, |
| 706 | true, pdata->irq_base + RTC_INTR_OFFSET, 0); | 713 | true, irq_base + RTC_INTR_OFFSET, 0); |
| 707 | if (IS_ERR(child)) | 714 | if (IS_ERR(child)) |
| 708 | return PTR_ERR(child); | 715 | return PTR_ERR(child); |
| 709 | } | 716 | } |
| @@ -756,8 +763,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 756 | pdata->usb, sizeof(*pdata->usb), | 763 | pdata->usb, sizeof(*pdata->usb), |
| 757 | true, | 764 | true, |
| 758 | /* irq0 = USB_PRES, irq1 = USB */ | 765 | /* irq0 = USB_PRES, irq1 = USB */ |
| 759 | pdata->irq_base + USB_PRES_INTR_OFFSET, | 766 | irq_base + USB_PRES_INTR_OFFSET, |
| 760 | pdata->irq_base + USB_INTR_OFFSET); | 767 | irq_base + USB_INTR_OFFSET); |
| 761 | 768 | ||
| 762 | if (IS_ERR(child)) | 769 | if (IS_ERR(child)) |
| 763 | return PTR_ERR(child); | 770 | return PTR_ERR(child); |
| @@ -805,8 +812,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 805 | pdata->usb, sizeof(*pdata->usb), | 812 | pdata->usb, sizeof(*pdata->usb), |
| 806 | true, | 813 | true, |
| 807 | /* irq1 = VBUS_PRES, irq0 = USB ID */ | 814 | /* irq1 = VBUS_PRES, irq0 = USB ID */ |
| 808 | pdata->irq_base + USBOTG_INTR_OFFSET, | 815 | irq_base + USBOTG_INTR_OFFSET, |
| 809 | pdata->irq_base + USB_PRES_INTR_OFFSET); | 816 | irq_base + USB_PRES_INTR_OFFSET); |
| 810 | 817 | ||
| 811 | if (IS_ERR(child)) | 818 | if (IS_ERR(child)) |
| 812 | return PTR_ERR(child); | 819 | return PTR_ERR(child); |
| @@ -833,7 +840,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 833 | 840 | ||
| 834 | if (twl_has_pwrbutton() && twl_class_is_4030()) { | 841 | if (twl_has_pwrbutton() && twl_class_is_4030()) { |
| 835 | child = add_child(1, "twl4030_pwrbutton", | 842 | child = add_child(1, "twl4030_pwrbutton", |
| 836 | NULL, 0, true, pdata->irq_base + 8 + 0, 0); | 843 | NULL, 0, true, irq_base + 8 + 0, 0); |
| 837 | if (IS_ERR(child)) | 844 | if (IS_ERR(child)) |
| 838 | return PTR_ERR(child); | 845 | return PTR_ERR(child); |
| 839 | } | 846 | } |
| @@ -847,15 +854,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 847 | return PTR_ERR(child); | 854 | return PTR_ERR(child); |
| 848 | } | 855 | } |
| 849 | 856 | ||
| 850 | if (twl_has_codec() && pdata->audio && twl_class_is_6030()) { | ||
| 851 | sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; | ||
| 852 | child = add_child(sub_chip_id, "twl6040", | ||
| 853 | pdata->audio, sizeof(*pdata->audio), | ||
| 854 | false, 0, 0); | ||
| 855 | if (IS_ERR(child)) | ||
| 856 | return PTR_ERR(child); | ||
| 857 | } | ||
| 858 | |||
| 859 | /* twl4030 regulators */ | 857 | /* twl4030 regulators */ |
| 860 | if (twl_has_regulator() && twl_class_is_4030()) { | 858 | if (twl_has_regulator() && twl_class_is_4030()) { |
| 861 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1, | 859 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1, |
| @@ -1092,8 +1090,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
| 1092 | child = add_child(3, "twl4030_bci", | 1090 | child = add_child(3, "twl4030_bci", |
| 1093 | pdata->bci, sizeof(*pdata->bci), false, | 1091 | pdata->bci, sizeof(*pdata->bci), false, |
| 1094 | /* irq0 = CHG_PRES, irq1 = BCI */ | 1092 | /* irq0 = CHG_PRES, irq1 = BCI */ |
| 1095 | pdata->irq_base + BCI_PRES_INTR_OFFSET, | 1093 | irq_base + BCI_PRES_INTR_OFFSET, |
| 1096 | pdata->irq_base + BCI_INTR_OFFSET); | 1094 | irq_base + BCI_INTR_OFFSET); |
| 1097 | if (IS_ERR(child)) | 1095 | if (IS_ERR(child)) |
| 1098 | return PTR_ERR(child); | 1096 | return PTR_ERR(child); |
| 1099 | } | 1097 | } |
| @@ -1193,26 +1191,24 @@ static void clocks_init(struct device *dev, | |||
| 1193 | 1191 | ||
| 1194 | /*----------------------------------------------------------------------*/ | 1192 | /*----------------------------------------------------------------------*/ |
| 1195 | 1193 | ||
| 1196 | int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | ||
| 1197 | int twl4030_exit_irq(void); | ||
| 1198 | int twl4030_init_chip_irq(const char *chip); | ||
| 1199 | int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | ||
| 1200 | int twl6030_exit_irq(void); | ||
| 1201 | 1194 | ||
| 1202 | static int twl_remove(struct i2c_client *client) | 1195 | static int twl_remove(struct i2c_client *client) |
| 1203 | { | 1196 | { |
| 1204 | unsigned i; | 1197 | unsigned i, num_slaves; |
| 1205 | int status; | 1198 | int status; |
| 1206 | 1199 | ||
| 1207 | if (twl_class_is_4030()) | 1200 | if (twl_class_is_4030()) { |
| 1208 | status = twl4030_exit_irq(); | 1201 | status = twl4030_exit_irq(); |
| 1209 | else | 1202 | num_slaves = TWL_NUM_SLAVES; |
| 1203 | } else { | ||
| 1210 | status = twl6030_exit_irq(); | 1204 | status = twl6030_exit_irq(); |
| 1205 | num_slaves = TWL_NUM_SLAVES - 1; | ||
| 1206 | } | ||
| 1211 | 1207 | ||
| 1212 | if (status < 0) | 1208 | if (status < 0) |
| 1213 | return status; | 1209 | return status; |
| 1214 | 1210 | ||
| 1215 | for (i = 0; i < TWL_NUM_SLAVES; i++) { | 1211 | for (i = 0; i < num_slaves; i++) { |
| 1216 | struct twl_client *twl = &twl_modules[i]; | 1212 | struct twl_client *twl = &twl_modules[i]; |
| 1217 | 1213 | ||
| 1218 | if (twl->client && twl->client != client) | 1214 | if (twl->client && twl->client != client) |
| @@ -1223,20 +1219,15 @@ static int twl_remove(struct i2c_client *client) | |||
| 1223 | return 0; | 1219 | return 0; |
| 1224 | } | 1220 | } |
| 1225 | 1221 | ||
| 1226 | /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ | 1222 | /* NOTE: This driver only handles a single twl4030/tps659x0 chip */ |
| 1227 | static int __devinit | 1223 | static int __devinit |
| 1228 | twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | 1224 | twl_probe(struct i2c_client *client, const struct i2c_device_id *id) |
| 1229 | { | 1225 | { |
| 1230 | int status; | ||
| 1231 | unsigned i; | ||
| 1232 | struct twl4030_platform_data *pdata = client->dev.platform_data; | 1226 | struct twl4030_platform_data *pdata = client->dev.platform_data; |
| 1233 | struct device_node *node = client->dev.of_node; | 1227 | struct device_node *node = client->dev.of_node; |
| 1234 | u8 temp; | 1228 | int irq_base = 0; |
| 1235 | int ret = 0; | 1229 | int status; |
| 1236 | int nr_irqs = TWL4030_NR_IRQS; | 1230 | unsigned i, num_slaves; |
| 1237 | |||
| 1238 | if ((id->driver_data) & TWL6030_CLASS) | ||
| 1239 | nr_irqs = TWL6030_NR_IRQS; | ||
| 1240 | 1231 | ||
| 1241 | if (node && !pdata) { | 1232 | if (node && !pdata) { |
| 1242 | /* | 1233 | /* |
| @@ -1255,17 +1246,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1255 | return -EINVAL; | 1246 | return -EINVAL; |
| 1256 | } | 1247 | } |
| 1257 | 1248 | ||
| 1258 | status = irq_alloc_descs(-1, pdata->irq_base, nr_irqs, 0); | ||
| 1259 | if (IS_ERR_VALUE(status)) { | ||
| 1260 | dev_err(&client->dev, "Fail to allocate IRQ descs\n"); | ||
| 1261 | return status; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | pdata->irq_base = status; | ||
| 1265 | pdata->irq_end = pdata->irq_base + nr_irqs; | ||
| 1266 | irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0, | ||
| 1267 | &irq_domain_simple_ops, NULL); | ||
| 1268 | |||
| 1269 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { | 1249 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { |
| 1270 | dev_dbg(&client->dev, "can't talk I2C?\n"); | 1250 | dev_dbg(&client->dev, "can't talk I2C?\n"); |
| 1271 | return -EIO; | 1251 | return -EIO; |
| @@ -1276,13 +1256,23 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1276 | return -EBUSY; | 1256 | return -EBUSY; |
| 1277 | } | 1257 | } |
| 1278 | 1258 | ||
| 1279 | for (i = 0; i < TWL_NUM_SLAVES; i++) { | 1259 | if ((id->driver_data) & TWL6030_CLASS) { |
| 1280 | struct twl_client *twl = &twl_modules[i]; | 1260 | twl_id = TWL6030_CLASS_ID; |
| 1261 | twl_map = &twl6030_map[0]; | ||
| 1262 | num_slaves = TWL_NUM_SLAVES - 1; | ||
| 1263 | } else { | ||
| 1264 | twl_id = TWL4030_CLASS_ID; | ||
| 1265 | twl_map = &twl4030_map[0]; | ||
| 1266 | num_slaves = TWL_NUM_SLAVES; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | for (i = 0; i < num_slaves; i++) { | ||
| 1270 | struct twl_client *twl = &twl_modules[i]; | ||
| 1281 | 1271 | ||
| 1282 | twl->address = client->addr + i; | 1272 | twl->address = client->addr + i; |
| 1283 | if (i == 0) | 1273 | if (i == 0) { |
| 1284 | twl->client = client; | 1274 | twl->client = client; |
| 1285 | else { | 1275 | } else { |
| 1286 | twl->client = i2c_new_dummy(client->adapter, | 1276 | twl->client = i2c_new_dummy(client->adapter, |
| 1287 | twl->address); | 1277 | twl->address); |
| 1288 | if (!twl->client) { | 1278 | if (!twl->client) { |
| @@ -1294,22 +1284,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1294 | } | 1284 | } |
| 1295 | mutex_init(&twl->xfer_lock); | 1285 | mutex_init(&twl->xfer_lock); |
| 1296 | } | 1286 | } |
| 1287 | |||
| 1297 | inuse = true; | 1288 | inuse = true; |
| 1298 | if ((id->driver_data) & TWL6030_CLASS) { | ||
| 1299 | twl_id = TWL6030_CLASS_ID; | ||
| 1300 | twl_map = &twl6030_map[0]; | ||
| 1301 | } else { | ||
| 1302 | twl_id = TWL4030_CLASS_ID; | ||
| 1303 | twl_map = &twl4030_map[0]; | ||
| 1304 | } | ||
| 1305 | 1289 | ||
| 1306 | /* setup clock framework */ | 1290 | /* setup clock framework */ |
| 1307 | clocks_init(&client->dev, pdata->clock); | 1291 | clocks_init(&client->dev, pdata->clock); |
| 1308 | 1292 | ||
| 1309 | /* read TWL IDCODE Register */ | 1293 | /* read TWL IDCODE Register */ |
| 1310 | if (twl_id == TWL4030_CLASS_ID) { | 1294 | if (twl_id == TWL4030_CLASS_ID) { |
| 1311 | ret = twl_read_idcode_register(); | 1295 | status = twl_read_idcode_register(); |
| 1312 | WARN(ret < 0, "Error: reading twl_idcode register value\n"); | 1296 | WARN(status < 0, "Error: reading twl_idcode register value\n"); |
| 1313 | } | 1297 | } |
| 1314 | 1298 | ||
| 1315 | /* load power event scripts */ | 1299 | /* load power event scripts */ |
| @@ -1317,31 +1301,31 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1317 | twl4030_power_init(pdata->power); | 1301 | twl4030_power_init(pdata->power); |
| 1318 | 1302 | ||
| 1319 | /* Maybe init the T2 Interrupt subsystem */ | 1303 | /* Maybe init the T2 Interrupt subsystem */ |
| 1320 | if (client->irq | 1304 | if (client->irq) { |
| 1321 | && pdata->irq_base | ||
| 1322 | && pdata->irq_end > pdata->irq_base) { | ||
| 1323 | if (twl_class_is_4030()) { | 1305 | if (twl_class_is_4030()) { |
| 1324 | twl4030_init_chip_irq(id->name); | 1306 | twl4030_init_chip_irq(id->name); |
| 1325 | status = twl4030_init_irq(client->irq, pdata->irq_base, | 1307 | irq_base = twl4030_init_irq(&client->dev, client->irq); |
| 1326 | pdata->irq_end); | ||
| 1327 | } else { | 1308 | } else { |
| 1328 | status = twl6030_init_irq(client->irq, pdata->irq_base, | 1309 | irq_base = twl6030_init_irq(&client->dev, client->irq); |
| 1329 | pdata->irq_end); | ||
| 1330 | } | 1310 | } |
| 1331 | 1311 | ||
| 1332 | if (status < 0) | 1312 | if (irq_base < 0) { |
| 1313 | status = irq_base; | ||
| 1333 | goto fail; | 1314 | goto fail; |
| 1315 | } | ||
| 1334 | } | 1316 | } |
| 1335 | 1317 | ||
| 1336 | /* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface. | 1318 | /* |
| 1319 | * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface. | ||
| 1337 | * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0, | 1320 | * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0, |
| 1338 | * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0. | 1321 | * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0. |
| 1339 | */ | 1322 | */ |
| 1340 | |||
| 1341 | if (twl_class_is_4030()) { | 1323 | if (twl_class_is_4030()) { |
| 1324 | u8 temp; | ||
| 1325 | |||
| 1342 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1); | 1326 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1); |
| 1343 | temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \ | 1327 | temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \ |
| 1344 | I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU); | 1328 | I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU); |
| 1345 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); | 1329 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); |
| 1346 | } | 1330 | } |
| 1347 | 1331 | ||
| @@ -1349,11 +1333,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1349 | if (node) | 1333 | if (node) |
| 1350 | status = of_platform_populate(node, NULL, NULL, &client->dev); | 1334 | status = of_platform_populate(node, NULL, NULL, &client->dev); |
| 1351 | if (status) | 1335 | if (status) |
| 1352 | status = add_children(pdata, id->driver_data); | 1336 | status = add_children(pdata, irq_base, id->driver_data); |
| 1353 | 1337 | ||
| 1354 | fail: | 1338 | fail: |
| 1355 | if (status < 0) | 1339 | if (status < 0) |
| 1356 | twl_remove(client); | 1340 | twl_remove(client); |
| 1341 | |||
| 1357 | return status; | 1342 | return status; |
| 1358 | } | 1343 | } |
| 1359 | 1344 | ||
diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h index 8c50a556e986..6ff99dce714f 100644 --- a/drivers/mfd/twl-core.h +++ b/drivers/mfd/twl-core.h | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | #ifndef __TWL_CORE_H__ | 1 | #ifndef __TWL_CORE_H__ |
| 2 | #define __TWL_CORE_H__ | 2 | #define __TWL_CORE_H__ |
| 3 | 3 | ||
| 4 | extern int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | 4 | extern int twl6030_init_irq(struct device *dev, int irq_num); |
| 5 | extern int twl6030_exit_irq(void); | 5 | extern int twl6030_exit_irq(void); |
| 6 | extern int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | 6 | extern int twl4030_init_irq(struct device *dev, int irq_num); |
| 7 | extern int twl4030_exit_irq(void); | 7 | extern int twl4030_exit_irq(void); |
| 8 | extern int twl4030_init_chip_irq(const char *chip); | 8 | extern int twl4030_init_chip_irq(const char *chip); |
| 9 | 9 | ||
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index b69bb517b102..5d656e814358 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
| @@ -28,10 +28,12 @@ | |||
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
| 31 | #include <linux/export.h> | ||
| 31 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
| 32 | #include <linux/irq.h> | 33 | #include <linux/irq.h> |
| 33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 34 | 35 | #include <linux/of.h> | |
| 36 | #include <linux/irqdomain.h> | ||
| 35 | #include <linux/i2c/twl.h> | 37 | #include <linux/i2c/twl.h> |
| 36 | 38 | ||
| 37 | #include "twl-core.h" | 39 | #include "twl-core.h" |
| @@ -53,13 +55,14 @@ | |||
| 53 | * base + 8 .. base + 15 SIH for PWR_INT | 55 | * base + 8 .. base + 15 SIH for PWR_INT |
| 54 | * base + 16 .. base + 33 SIH for GPIO | 56 | * base + 16 .. base + 33 SIH for GPIO |
| 55 | */ | 57 | */ |
| 58 | #define TWL4030_CORE_NR_IRQS 8 | ||
| 59 | #define TWL4030_PWR_NR_IRQS 8 | ||
| 56 | 60 | ||
| 57 | /* PIH register offsets */ | 61 | /* PIH register offsets */ |
| 58 | #define REG_PIH_ISR_P1 0x01 | 62 | #define REG_PIH_ISR_P1 0x01 |
| 59 | #define REG_PIH_ISR_P2 0x02 | 63 | #define REG_PIH_ISR_P2 0x02 |
| 60 | #define REG_PIH_SIR 0x03 /* for testing */ | 64 | #define REG_PIH_SIR 0x03 /* for testing */ |
| 61 | 65 | ||
| 62 | |||
| 63 | /* Linux could (eventually) use either IRQ line */ | 66 | /* Linux could (eventually) use either IRQ line */ |
| 64 | static int irq_line; | 67 | static int irq_line; |
| 65 | 68 | ||
| @@ -111,7 +114,8 @@ static int nr_sih_modules; | |||
| 111 | #define TWL4030_MODULE_INT_PWR TWL4030_MODULE_INT | 114 | #define TWL4030_MODULE_INT_PWR TWL4030_MODULE_INT |
| 112 | 115 | ||
| 113 | 116 | ||
| 114 | /* Order in this table matches order in PIH_ISR. That is, | 117 | /* |
| 118 | * Order in this table matches order in PIH_ISR. That is, | ||
| 115 | * BIT(n) in PIH_ISR is sih_modules[n]. | 119 | * BIT(n) in PIH_ISR is sih_modules[n]. |
| 116 | */ | 120 | */ |
| 117 | /* sih_modules_twl4030 is used both in twl4030 and twl5030 */ | 121 | /* sih_modules_twl4030 is used both in twl4030 and twl5030 */ |
| @@ -288,7 +292,6 @@ static unsigned twl4030_irq_base; | |||
| 288 | */ | 292 | */ |
| 289 | static irqreturn_t handle_twl4030_pih(int irq, void *devid) | 293 | static irqreturn_t handle_twl4030_pih(int irq, void *devid) |
| 290 | { | 294 | { |
| 291 | int module_irq; | ||
| 292 | irqreturn_t ret; | 295 | irqreturn_t ret; |
| 293 | u8 pih_isr; | 296 | u8 pih_isr; |
| 294 | 297 | ||
| @@ -299,16 +302,18 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid) | |||
| 299 | return IRQ_NONE; | 302 | return IRQ_NONE; |
| 300 | } | 303 | } |
| 301 | 304 | ||
| 302 | /* these handlers deal with the relevant SIH irq status */ | 305 | while (pih_isr) { |
| 303 | for (module_irq = twl4030_irq_base; | 306 | unsigned long pending = __ffs(pih_isr); |
| 304 | pih_isr; | 307 | unsigned int irq; |
| 305 | pih_isr >>= 1, module_irq++) { | 308 | |
| 306 | if (pih_isr & 0x1) | 309 | pih_isr &= ~BIT(pending); |
| 307 | handle_nested_irq(module_irq); | 310 | irq = pending + twl4030_irq_base; |
| 311 | handle_nested_irq(irq); | ||
| 308 | } | 312 | } |
| 309 | 313 | ||
| 310 | return IRQ_HANDLED; | 314 | return IRQ_HANDLED; |
| 311 | } | 315 | } |
| 316 | |||
| 312 | /*----------------------------------------------------------------------*/ | 317 | /*----------------------------------------------------------------------*/ |
| 313 | 318 | ||
| 314 | /* | 319 | /* |
| @@ -337,7 +342,6 @@ static int twl4030_init_sih_modules(unsigned line) | |||
| 337 | memset(buf, 0xff, sizeof buf); | 342 | memset(buf, 0xff, sizeof buf); |
| 338 | sih = sih_modules; | 343 | sih = sih_modules; |
| 339 | for (i = 0; i < nr_sih_modules; i++, sih++) { | 344 | for (i = 0; i < nr_sih_modules; i++, sih++) { |
| 340 | |||
| 341 | /* skip USB -- it's funky */ | 345 | /* skip USB -- it's funky */ |
| 342 | if (!sih->bytes_ixr) | 346 | if (!sih->bytes_ixr) |
| 343 | continue; | 347 | continue; |
| @@ -352,7 +356,8 @@ static int twl4030_init_sih_modules(unsigned line) | |||
| 352 | pr_err("twl4030: err %d initializing %s %s\n", | 356 | pr_err("twl4030: err %d initializing %s %s\n", |
| 353 | status, sih->name, "IMR"); | 357 | status, sih->name, "IMR"); |
| 354 | 358 | ||
| 355 | /* Maybe disable "exclusive" mode; buffer second pending irq; | 359 | /* |
| 360 | * Maybe disable "exclusive" mode; buffer second pending irq; | ||
| 356 | * set Clear-On-Read (COR) bit. | 361 | * set Clear-On-Read (COR) bit. |
| 357 | * | 362 | * |
| 358 | * NOTE that sometimes COR polarity is documented as being | 363 | * NOTE that sometimes COR polarity is documented as being |
| @@ -382,7 +387,8 @@ static int twl4030_init_sih_modules(unsigned line) | |||
| 382 | if (sih->irq_lines <= line) | 387 | if (sih->irq_lines <= line) |
| 383 | continue; | 388 | continue; |
| 384 | 389 | ||
| 385 | /* Clear pending interrupt status. Either the read was | 390 | /* |
| 391 | * Clear pending interrupt status. Either the read was | ||
| 386 | * enough, or we need to write those bits. Repeat, in | 392 | * enough, or we need to write those bits. Repeat, in |
| 387 | * case an IRQ is pending (PENDDIS=0) ... that's not | 393 | * case an IRQ is pending (PENDDIS=0) ... that's not |
| 388 | * uncommon with PWR_INT.PWRON. | 394 | * uncommon with PWR_INT.PWRON. |
| @@ -398,7 +404,8 @@ static int twl4030_init_sih_modules(unsigned line) | |||
| 398 | status = twl_i2c_write(sih->module, buf, | 404 | status = twl_i2c_write(sih->module, buf, |
| 399 | sih->mask[line].isr_offset, | 405 | sih->mask[line].isr_offset, |
| 400 | sih->bytes_ixr); | 406 | sih->bytes_ixr); |
| 401 | /* else COR=1 means read sufficed. | 407 | /* |
| 408 | * else COR=1 means read sufficed. | ||
| 402 | * (for most SIH modules...) | 409 | * (for most SIH modules...) |
| 403 | */ | 410 | */ |
| 404 | } | 411 | } |
| @@ -410,7 +417,8 @@ static int twl4030_init_sih_modules(unsigned line) | |||
| 410 | static inline void activate_irq(int irq) | 417 | static inline void activate_irq(int irq) |
| 411 | { | 418 | { |
| 412 | #ifdef CONFIG_ARM | 419 | #ifdef CONFIG_ARM |
| 413 | /* ARM requires an extra step to clear IRQ_NOREQUEST, which it | 420 | /* |
| 421 | * ARM requires an extra step to clear IRQ_NOREQUEST, which it | ||
| 414 | * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE. | 422 | * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE. |
| 415 | */ | 423 | */ |
| 416 | set_irq_flags(irq, IRQF_VALID); | 424 | set_irq_flags(irq, IRQF_VALID); |
| @@ -620,33 +628,24 @@ static irqreturn_t handle_twl4030_sih(int irq, void *data) | |||
| 620 | return IRQ_HANDLED; | 628 | return IRQ_HANDLED; |
| 621 | } | 629 | } |
| 622 | 630 | ||
| 623 | static unsigned twl4030_irq_next; | 631 | /* returns the first IRQ used by this SIH bank, or negative errno */ |
| 624 | 632 | int twl4030_sih_setup(struct device *dev, int module, int irq_base) | |
| 625 | /* returns the first IRQ used by this SIH bank, | ||
| 626 | * or negative errno | ||
| 627 | */ | ||
| 628 | int twl4030_sih_setup(int module) | ||
| 629 | { | 633 | { |
| 630 | int sih_mod; | 634 | int sih_mod; |
| 631 | const struct sih *sih = NULL; | 635 | const struct sih *sih = NULL; |
| 632 | struct sih_agent *agent; | 636 | struct sih_agent *agent; |
| 633 | int i, irq; | 637 | int i, irq; |
| 634 | int status = -EINVAL; | 638 | int status = -EINVAL; |
| 635 | unsigned irq_base = twl4030_irq_next; | ||
| 636 | 639 | ||
| 637 | /* only support modules with standard clear-on-read for now */ | 640 | /* only support modules with standard clear-on-read for now */ |
| 638 | for (sih_mod = 0, sih = sih_modules; | 641 | for (sih_mod = 0, sih = sih_modules; sih_mod < nr_sih_modules; |
| 639 | sih_mod < nr_sih_modules; | ||
| 640 | sih_mod++, sih++) { | 642 | sih_mod++, sih++) { |
| 641 | if (sih->module == module && sih->set_cor) { | 643 | if (sih->module == module && sih->set_cor) { |
| 642 | if (!WARN((irq_base + sih->bits) > NR_IRQS, | 644 | status = 0; |
| 643 | "irq %d for %s too big\n", | ||
| 644 | irq_base + sih->bits, | ||
| 645 | sih->name)) | ||
| 646 | status = 0; | ||
| 647 | break; | 645 | break; |
| 648 | } | 646 | } |
| 649 | } | 647 | } |
| 648 | |||
| 650 | if (status < 0) | 649 | if (status < 0) |
| 651 | return status; | 650 | return status; |
| 652 | 651 | ||
| @@ -654,8 +653,6 @@ int twl4030_sih_setup(int module) | |||
| 654 | if (!agent) | 653 | if (!agent) |
| 655 | return -ENOMEM; | 654 | return -ENOMEM; |
| 656 | 655 | ||
| 657 | status = 0; | ||
| 658 | |||
| 659 | agent->irq_base = irq_base; | 656 | agent->irq_base = irq_base; |
| 660 | agent->sih = sih; | 657 | agent->sih = sih; |
| 661 | agent->imr = ~0; | 658 | agent->imr = ~0; |
| @@ -671,8 +668,6 @@ int twl4030_sih_setup(int module) | |||
| 671 | activate_irq(irq); | 668 | activate_irq(irq); |
| 672 | } | 669 | } |
| 673 | 670 | ||
| 674 | twl4030_irq_next += i; | ||
| 675 | |||
| 676 | /* replace generic PIH handler (handle_simple_irq) */ | 671 | /* replace generic PIH handler (handle_simple_irq) */ |
| 677 | irq = sih_mod + twl4030_irq_base; | 672 | irq = sih_mod + twl4030_irq_base; |
| 678 | irq_set_handler_data(irq, agent); | 673 | irq_set_handler_data(irq, agent); |
| @@ -680,26 +675,43 @@ int twl4030_sih_setup(int module) | |||
| 680 | status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0, | 675 | status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0, |
| 681 | agent->irq_name ?: sih->name, NULL); | 676 | agent->irq_name ?: sih->name, NULL); |
| 682 | 677 | ||
| 683 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name, | 678 | dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name, |
| 684 | irq, irq_base, twl4030_irq_next - 1); | 679 | irq, irq_base, irq_base + i - 1); |
| 685 | 680 | ||
| 686 | return status < 0 ? status : irq_base; | 681 | return status < 0 ? status : irq_base; |
| 687 | } | 682 | } |
| 688 | 683 | ||
| 689 | /* FIXME need a call to reverse twl4030_sih_setup() ... */ | 684 | /* FIXME need a call to reverse twl4030_sih_setup() ... */ |
| 690 | 685 | ||
| 691 | |||
| 692 | /*----------------------------------------------------------------------*/ | 686 | /*----------------------------------------------------------------------*/ |
| 693 | 687 | ||
| 694 | /* FIXME pass in which interrupt line we'll use ... */ | 688 | /* FIXME pass in which interrupt line we'll use ... */ |
| 695 | #define twl_irq_line 0 | 689 | #define twl_irq_line 0 |
| 696 | 690 | ||
| 697 | int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | 691 | int twl4030_init_irq(struct device *dev, int irq_num) |
| 698 | { | 692 | { |
| 699 | static struct irq_chip twl4030_irq_chip; | 693 | static struct irq_chip twl4030_irq_chip; |
| 694 | int status, i; | ||
| 695 | int irq_base, irq_end, nr_irqs; | ||
| 696 | struct device_node *node = dev->of_node; | ||
| 700 | 697 | ||
| 701 | int status; | 698 | /* |
| 702 | int i; | 699 | * TWL core and pwr interrupts must be contiguous because |
| 700 | * the hwirqs numbers are defined contiguously from 1 to 15. | ||
| 701 | * Create only one domain for both. | ||
| 702 | */ | ||
| 703 | nr_irqs = TWL4030_PWR_NR_IRQS + TWL4030_CORE_NR_IRQS; | ||
| 704 | |||
| 705 | irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); | ||
| 706 | if (IS_ERR_VALUE(irq_base)) { | ||
| 707 | dev_err(dev, "Fail to allocate IRQ descs\n"); | ||
| 708 | return irq_base; | ||
| 709 | } | ||
| 710 | |||
| 711 | irq_domain_add_legacy(node, nr_irqs, irq_base, 0, | ||
| 712 | &irq_domain_simple_ops, NULL); | ||
| 713 | |||
| 714 | irq_end = irq_base + TWL4030_CORE_NR_IRQS; | ||
| 703 | 715 | ||
| 704 | /* | 716 | /* |
| 705 | * Mask and clear all TWL4030 interrupts since initially we do | 717 | * Mask and clear all TWL4030 interrupts since initially we do |
| @@ -711,7 +723,8 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
| 711 | 723 | ||
| 712 | twl4030_irq_base = irq_base; | 724 | twl4030_irq_base = irq_base; |
| 713 | 725 | ||
| 714 | /* install an irq handler for each of the SIH modules; | 726 | /* |
| 727 | * Install an irq handler for each of the SIH modules; | ||
| 715 | * clone dummy irq_chip since PIH can't *do* anything | 728 | * clone dummy irq_chip since PIH can't *do* anything |
| 716 | */ | 729 | */ |
| 717 | twl4030_irq_chip = dummy_irq_chip; | 730 | twl4030_irq_chip = dummy_irq_chip; |
| @@ -725,14 +738,14 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
| 725 | irq_set_nested_thread(i, 1); | 738 | irq_set_nested_thread(i, 1); |
| 726 | activate_irq(i); | 739 | activate_irq(i); |
| 727 | } | 740 | } |
| 728 | twl4030_irq_next = i; | 741 | |
| 729 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", | 742 | dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", "PIH", |
| 730 | irq_num, irq_base, twl4030_irq_next - 1); | 743 | irq_num, irq_base, irq_end); |
| 731 | 744 | ||
| 732 | /* ... and the PWR_INT module ... */ | 745 | /* ... and the PWR_INT module ... */ |
| 733 | status = twl4030_sih_setup(TWL4030_MODULE_INT); | 746 | status = twl4030_sih_setup(dev, TWL4030_MODULE_INT, irq_end); |
| 734 | if (status < 0) { | 747 | if (status < 0) { |
| 735 | pr_err("twl4030: sih_setup PWR INT --> %d\n", status); | 748 | dev_err(dev, "sih_setup PWR INT --> %d\n", status); |
| 736 | goto fail; | 749 | goto fail; |
| 737 | } | 750 | } |
| 738 | 751 | ||
| @@ -741,11 +754,11 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
| 741 | IRQF_ONESHOT, | 754 | IRQF_ONESHOT, |
| 742 | "TWL4030-PIH", NULL); | 755 | "TWL4030-PIH", NULL); |
| 743 | if (status < 0) { | 756 | if (status < 0) { |
| 744 | pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); | 757 | dev_err(dev, "could not claim irq%d: %d\n", irq_num, status); |
| 745 | goto fail_rqirq; | 758 | goto fail_rqirq; |
| 746 | } | 759 | } |
| 747 | 760 | ||
| 748 | return status; | 761 | return irq_base; |
| 749 | fail_rqirq: | 762 | fail_rqirq: |
| 750 | /* clean up twl4030_sih_setup */ | 763 | /* clean up twl4030_sih_setup */ |
| 751 | fail: | 764 | fail: |
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index c6b456ad7342..b76902f1e44a 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c | |||
| @@ -39,6 +39,8 @@ | |||
| 39 | #include <linux/i2c/twl.h> | 39 | #include <linux/i2c/twl.h> |
| 40 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
| 41 | #include <linux/suspend.h> | 41 | #include <linux/suspend.h> |
| 42 | #include <linux/of.h> | ||
| 43 | #include <linux/irqdomain.h> | ||
| 42 | 44 | ||
| 43 | #include "twl-core.h" | 45 | #include "twl-core.h" |
| 44 | 46 | ||
| @@ -51,8 +53,8 @@ | |||
| 51 | * | 53 | * |
| 52 | * We set up IRQs starting at a platform-specified base. An interrupt map table, | 54 | * We set up IRQs starting at a platform-specified base. An interrupt map table, |
| 53 | * specifies mapping between interrupt number and the associated module. | 55 | * specifies mapping between interrupt number and the associated module. |
| 54 | * | ||
| 55 | */ | 56 | */ |
| 57 | #define TWL6030_NR_IRQS 20 | ||
| 56 | 58 | ||
| 57 | static int twl6030_interrupt_mapping[24] = { | 59 | static int twl6030_interrupt_mapping[24] = { |
| 58 | PWR_INTR_OFFSET, /* Bit 0 PWRON */ | 60 | PWR_INTR_OFFSET, /* Bit 0 PWRON */ |
| @@ -185,8 +187,17 @@ static int twl6030_irq_thread(void *data) | |||
| 185 | } | 187 | } |
| 186 | local_irq_enable(); | 188 | local_irq_enable(); |
| 187 | } | 189 | } |
| 188 | ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes, | 190 | |
| 189 | REG_INT_STS_A, 3); /* clear INT_STS_A */ | 191 | /* |
| 192 | * NOTE: | ||
| 193 | * Simulation confirms that documentation is wrong w.r.t the | ||
| 194 | * interrupt status clear operation. A single *byte* write to | ||
| 195 | * any one of STS_A to STS_C register results in all three | ||
| 196 | * STS registers being reset. Since it does not matter which | ||
| 197 | * value is written, all three registers are cleared on a | ||
| 198 | * single byte write, so we just use 0x0 to clear. | ||
| 199 | */ | ||
| 200 | ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A); | ||
| 190 | if (ret) | 201 | if (ret) |
| 191 | pr_warning("twl6030: I2C error in clearing PIH ISR\n"); | 202 | pr_warning("twl6030: I2C error in clearing PIH ISR\n"); |
| 192 | 203 | ||
| @@ -227,7 +238,7 @@ static inline void activate_irq(int irq) | |||
| 227 | #endif | 238 | #endif |
| 228 | } | 239 | } |
| 229 | 240 | ||
| 230 | int twl6030_irq_set_wake(struct irq_data *d, unsigned int on) | 241 | static int twl6030_irq_set_wake(struct irq_data *d, unsigned int on) |
| 231 | { | 242 | { |
| 232 | if (on) | 243 | if (on) |
| 233 | atomic_inc(&twl6030_wakeirqs); | 244 | atomic_inc(&twl6030_wakeirqs); |
| @@ -237,11 +248,6 @@ int twl6030_irq_set_wake(struct irq_data *d, unsigned int on) | |||
| 237 | return 0; | 248 | return 0; |
| 238 | } | 249 | } |
| 239 | 250 | ||
| 240 | /*----------------------------------------------------------------------*/ | ||
| 241 | |||
| 242 | static unsigned twl6030_irq_next; | ||
| 243 | |||
| 244 | /*----------------------------------------------------------------------*/ | ||
| 245 | int twl6030_interrupt_unmask(u8 bit_mask, u8 offset) | 251 | int twl6030_interrupt_unmask(u8 bit_mask, u8 offset) |
| 246 | { | 252 | { |
| 247 | int ret; | 253 | int ret; |
| @@ -311,7 +317,8 @@ int twl6030_mmc_card_detect_config(void) | |||
| 311 | ret); | 317 | ret); |
| 312 | return ret; | 318 | return ret; |
| 313 | } | 319 | } |
| 314 | return 0; | 320 | |
| 321 | return twl6030_irq_base + MMCDETECT_INTR_OFFSET; | ||
| 315 | } | 322 | } |
| 316 | EXPORT_SYMBOL(twl6030_mmc_card_detect_config); | 323 | EXPORT_SYMBOL(twl6030_mmc_card_detect_config); |
| 317 | 324 | ||
| @@ -340,29 +347,44 @@ int twl6030_mmc_card_detect(struct device *dev, int slot) | |||
| 340 | } | 347 | } |
| 341 | EXPORT_SYMBOL(twl6030_mmc_card_detect); | 348 | EXPORT_SYMBOL(twl6030_mmc_card_detect); |
| 342 | 349 | ||
| 343 | int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | 350 | int twl6030_init_irq(struct device *dev, int irq_num) |
| 344 | { | 351 | { |
| 345 | 352 | struct device_node *node = dev->of_node; | |
| 346 | int status = 0; | 353 | int nr_irqs, irq_base, irq_end; |
| 347 | int i; | ||
| 348 | struct task_struct *task; | 354 | struct task_struct *task; |
| 349 | int ret; | 355 | static struct irq_chip twl6030_irq_chip; |
| 350 | u8 mask[4]; | 356 | int status = 0; |
| 357 | int i; | ||
| 358 | u8 mask[4]; | ||
| 359 | |||
| 360 | nr_irqs = TWL6030_NR_IRQS; | ||
| 361 | |||
| 362 | irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); | ||
| 363 | if (IS_ERR_VALUE(irq_base)) { | ||
| 364 | dev_err(dev, "Fail to allocate IRQ descs\n"); | ||
| 365 | return irq_base; | ||
| 366 | } | ||
| 367 | |||
| 368 | irq_domain_add_legacy(node, nr_irqs, irq_base, 0, | ||
| 369 | &irq_domain_simple_ops, NULL); | ||
| 370 | |||
| 371 | irq_end = irq_base + nr_irqs; | ||
| 351 | 372 | ||
| 352 | static struct irq_chip twl6030_irq_chip; | ||
| 353 | mask[1] = 0xFF; | 373 | mask[1] = 0xFF; |
| 354 | mask[2] = 0xFF; | 374 | mask[2] = 0xFF; |
| 355 | mask[3] = 0xFF; | 375 | mask[3] = 0xFF; |
| 356 | ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], | 376 | |
| 357 | REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */ | 377 | /* mask all int lines */ |
| 358 | ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], | 378 | twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3); |
| 359 | REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */ | 379 | /* mask all int sts */ |
| 360 | ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], | 380 | twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3); |
| 361 | REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */ | 381 | /* clear INT_STS_A,B,C */ |
| 382 | twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3); | ||
| 362 | 383 | ||
| 363 | twl6030_irq_base = irq_base; | 384 | twl6030_irq_base = irq_base; |
| 364 | 385 | ||
| 365 | /* install an irq handler for each of the modules; | 386 | /* |
| 387 | * install an irq handler for each of the modules; | ||
| 366 | * clone dummy irq_chip since PIH can't *do* anything | 388 | * clone dummy irq_chip since PIH can't *do* anything |
| 367 | */ | 389 | */ |
| 368 | twl6030_irq_chip = dummy_irq_chip; | 390 | twl6030_irq_chip = dummy_irq_chip; |
| @@ -377,30 +399,29 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
| 377 | activate_irq(i); | 399 | activate_irq(i); |
| 378 | } | 400 | } |
| 379 | 401 | ||
| 380 | twl6030_irq_next = i; | 402 | dev_info(dev, "PIH (irq %d) chaining IRQs %d..%d\n", |
| 381 | pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", | 403 | irq_num, irq_base, irq_end); |
| 382 | irq_num, irq_base, twl6030_irq_next - 1); | ||
| 383 | 404 | ||
| 384 | /* install an irq handler to demultiplex the TWL6030 interrupt */ | 405 | /* install an irq handler to demultiplex the TWL6030 interrupt */ |
| 385 | init_completion(&irq_event); | 406 | init_completion(&irq_event); |
| 386 | 407 | ||
| 387 | status = request_irq(irq_num, handle_twl6030_pih, 0, | 408 | status = request_irq(irq_num, handle_twl6030_pih, 0, "TWL6030-PIH", |
| 388 | "TWL6030-PIH", &irq_event); | 409 | &irq_event); |
| 389 | if (status < 0) { | 410 | if (status < 0) { |
| 390 | pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); | 411 | dev_err(dev, "could not claim irq %d: %d\n", irq_num, status); |
| 391 | goto fail_irq; | 412 | goto fail_irq; |
| 392 | } | 413 | } |
| 393 | 414 | ||
| 394 | task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); | 415 | task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); |
| 395 | if (IS_ERR(task)) { | 416 | if (IS_ERR(task)) { |
| 396 | pr_err("twl6030: could not create irq %d thread!\n", irq_num); | 417 | dev_err(dev, "could not create irq %d thread!\n", irq_num); |
| 397 | status = PTR_ERR(task); | 418 | status = PTR_ERR(task); |
| 398 | goto fail_kthread; | 419 | goto fail_kthread; |
| 399 | } | 420 | } |
| 400 | 421 | ||
| 401 | twl_irq = irq_num; | 422 | twl_irq = irq_num; |
| 402 | register_pm_notifier(&twl6030_irq_pm_notifier_block); | 423 | register_pm_notifier(&twl6030_irq_pm_notifier_block); |
| 403 | return status; | 424 | return irq_base; |
| 404 | 425 | ||
| 405 | fail_kthread: | 426 | fail_kthread: |
| 406 | free_irq(irq_num, &irq_event); | 427 | free_irq(irq_num, &irq_event); |
| @@ -408,6 +429,7 @@ fail_kthread: | |||
| 408 | fail_irq: | 429 | fail_irq: |
| 409 | for (i = irq_base; i < irq_end; i++) | 430 | for (i = irq_base; i < irq_end; i++) |
| 410 | irq_set_chip_and_handler(i, NULL, NULL); | 431 | irq_set_chip_and_handler(i, NULL, NULL); |
| 432 | |||
| 411 | return status; | 433 | return status; |
| 412 | } | 434 | } |
| 413 | 435 | ||
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index 745c87945664..4bceee98f0a4 100644 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c | |||
| @@ -89,7 +89,7 @@ static const struct spi_device_id wm831x_spi_ids[] = { | |||
| 89 | { "wm8326", WM8326 }, | 89 | { "wm8326", WM8326 }, |
| 90 | { }, | 90 | { }, |
| 91 | }; | 91 | }; |
| 92 | MODULE_DEVICE_TABLE(spi, wm831x_spi_id); | 92 | MODULE_DEVICE_TABLE(spi, wm831x_spi_ids); |
| 93 | 93 | ||
| 94 | static struct spi_driver wm831x_spi_driver = { | 94 | static struct spi_driver wm831x_spi_driver = { |
| 95 | .driver = { | 95 | .driver = { |
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 237764ae5f9b..1189a17f0f25 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c | |||
| @@ -271,8 +271,7 @@ static int wm8400_init(struct wm8400 *wm8400, | |||
| 271 | return -EIO; | 271 | return -EIO; |
| 272 | } | 272 | } |
| 273 | if (i != reg_data[WM8400_RESET_ID].default_val) { | 273 | if (i != reg_data[WM8400_RESET_ID].default_val) { |
| 274 | dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n", | 274 | dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n", i); |
| 275 | reg); | ||
| 276 | return -ENODEV; | 275 | return -ENODEV; |
| 277 | } | 276 | } |
| 278 | 277 | ||
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 98733d408fee..9d7ca1e978fa 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
| @@ -639,7 +639,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
| 639 | } | 639 | } |
| 640 | 640 | ||
| 641 | pm_runtime_enable(wm8994->dev); | 641 | pm_runtime_enable(wm8994->dev); |
| 642 | pm_runtime_resume(wm8994->dev); | 642 | pm_runtime_idle(wm8994->dev); |
| 643 | 643 | ||
| 644 | return 0; | 644 | return 0; |
| 645 | 645 | ||
diff --git a/drivers/mfd/wm8994-regmap.c b/drivers/mfd/wm8994-regmap.c index 7605b6095453..bfd25af6ecb1 100644 --- a/drivers/mfd/wm8994-regmap.c +++ b/drivers/mfd/wm8994-regmap.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | #include "wm8994.h" | 20 | #include "wm8994.h" |
| 21 | 21 | ||
| 22 | static struct reg_default wm1811_defaults[] = { | 22 | static struct reg_default wm1811_defaults[] = { |
| 23 | { 0x0000, 0x1811 }, /* R0 - Software Reset */ | ||
| 24 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ | 23 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ |
| 25 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ | 24 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ |
| 26 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ | 25 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ |
| @@ -61,7 +60,7 @@ static struct reg_default wm1811_defaults[] = { | |||
| 61 | { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */ | 60 | { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */ |
| 62 | { 0x0037, 0x0000 }, /* R55 - Additional Control */ | 61 | { 0x0037, 0x0000 }, /* R55 - Additional Control */ |
| 63 | { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */ | 62 | { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */ |
| 64 | { 0x0039, 0x0180 }, /* R57 - AntiPOP (2) */ | 63 | { 0x0039, 0x0000 }, /* R57 - AntiPOP (2) */ |
| 65 | { 0x003B, 0x000D }, /* R59 - LDO 1 */ | 64 | { 0x003B, 0x000D }, /* R59 - LDO 1 */ |
| 66 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ | 65 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ |
| 67 | { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */ | 66 | { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */ |
| @@ -69,16 +68,12 @@ static struct reg_default wm1811_defaults[] = { | |||
| 69 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ | 68 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ |
| 70 | { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */ | 69 | { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */ |
| 71 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ | 70 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ |
| 72 | { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */ | ||
| 73 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ | 71 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ |
| 74 | { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */ | ||
| 75 | { 0x0059, 0x0000 }, /* R89 - DC Servo (4) */ | 72 | { 0x0059, 0x0000 }, /* R89 - DC Servo (4) */ |
| 76 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ | 73 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ |
| 77 | { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */ | 74 | { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */ |
| 78 | { 0x00D0, 0x7600 }, /* R208 - Mic Detect 1 */ | 75 | { 0x00D0, 0x7600 }, /* R208 - Mic Detect 1 */ |
| 79 | { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */ | 76 | { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */ |
| 80 | { 0x00D2, 0x0000 }, /* R210 - Mic Detect 3 */ | ||
| 81 | { 0x0100, 0x0100 }, /* R256 - Chip Revision */ | ||
| 82 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ | 77 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ |
| 83 | { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */ | 78 | { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */ |
| 84 | { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */ | 79 | { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */ |
| @@ -88,7 +83,6 @@ static struct reg_default wm1811_defaults[] = { | |||
| 88 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ | 83 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ |
| 89 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ | 84 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ |
| 90 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ | 85 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ |
| 91 | { 0x0212, 0x0000 }, /* R530 - Rate Status */ | ||
| 92 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ | 86 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ |
| 93 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ | 87 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ |
| 94 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ | 88 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ |
| @@ -218,8 +212,6 @@ static struct reg_default wm1811_defaults[] = { | |||
| 218 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ | 212 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ |
| 219 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ | 213 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ |
| 220 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ | 214 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ |
| 221 | { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */ | ||
| 222 | { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */ | ||
| 223 | { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */ | 215 | { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */ |
| 224 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ | 216 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ |
| 225 | { 0x0739, 0xDFEF }, /* R1849 - Interrupt Status 2 Mask */ | 217 | { 0x0739, 0xDFEF }, /* R1849 - Interrupt Status 2 Mask */ |
| @@ -228,7 +220,6 @@ static struct reg_default wm1811_defaults[] = { | |||
| 228 | }; | 220 | }; |
| 229 | 221 | ||
| 230 | static struct reg_default wm8994_defaults[] = { | 222 | static struct reg_default wm8994_defaults[] = { |
| 231 | { 0x0000, 0x8994 }, /* R0 - Software Reset */ | ||
| 232 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ | 223 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ |
| 233 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ | 224 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ |
| 234 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ | 225 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ |
| @@ -275,12 +266,9 @@ static struct reg_default wm8994_defaults[] = { | |||
| 275 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ | 266 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ |
| 276 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ | 267 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ |
| 277 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ | 268 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ |
| 278 | { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */ | ||
| 279 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ | 269 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ |
| 280 | { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */ | 270 | { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */ |
| 281 | { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */ | ||
| 282 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ | 271 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ |
| 283 | { 0x0100, 0x0003 }, /* R256 - Chip Revision */ | ||
| 284 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ | 272 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ |
| 285 | { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */ | 273 | { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */ |
| 286 | { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */ | 274 | { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */ |
| @@ -292,7 +280,6 @@ static struct reg_default wm8994_defaults[] = { | |||
| 292 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ | 280 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ |
| 293 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ | 281 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ |
| 294 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ | 282 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ |
| 295 | { 0x0212, 0x0000 }, /* R530 - Rate Status */ | ||
| 296 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ | 283 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ |
| 297 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ | 284 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ |
| 298 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ | 285 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ |
| @@ -445,9 +432,6 @@ static struct reg_default wm8994_defaults[] = { | |||
| 445 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ | 432 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ |
| 446 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ | 433 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ |
| 447 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ | 434 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ |
| 448 | { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */ | ||
| 449 | { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */ | ||
| 450 | { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */ | ||
| 451 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ | 435 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ |
| 452 | { 0x0739, 0xFFFF }, /* R1849 - Interrupt Status 2 Mask */ | 436 | { 0x0739, 0xFFFF }, /* R1849 - Interrupt Status 2 Mask */ |
| 453 | { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */ | 437 | { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */ |
| @@ -455,7 +439,6 @@ static struct reg_default wm8994_defaults[] = { | |||
| 455 | }; | 439 | }; |
| 456 | 440 | ||
| 457 | static struct reg_default wm8958_defaults[] = { | 441 | static struct reg_default wm8958_defaults[] = { |
| 458 | { 0x0000, 0x8958 }, /* R0 - Software Reset */ | ||
| 459 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ | 442 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ |
| 460 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ | 443 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ |
| 461 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ | 444 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ |
| @@ -970,6 +953,7 @@ static bool wm8994_readable_register(struct device *dev, unsigned int reg) | |||
| 970 | { | 953 | { |
| 971 | switch (reg) { | 954 | switch (reg) { |
| 972 | case WM8994_DC_SERVO_READBACK: | 955 | case WM8994_DC_SERVO_READBACK: |
| 956 | case WM8994_MICBIAS: | ||
| 973 | case WM8994_WRITE_SEQUENCER_CTRL_1: | 957 | case WM8994_WRITE_SEQUENCER_CTRL_1: |
| 974 | case WM8994_WRITE_SEQUENCER_CTRL_2: | 958 | case WM8994_WRITE_SEQUENCER_CTRL_2: |
| 975 | case WM8994_AIF1_ADC2_LEFT_VOLUME: | 959 | case WM8994_AIF1_ADC2_LEFT_VOLUME: |
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index f04761e6622d..afee0e8ae714 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c | |||
| @@ -376,6 +376,9 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev) | |||
| 376 | INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work); | 376 | INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work); |
| 377 | schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); | 377 | schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); |
| 378 | #endif /* VRTC_CALIBRATION */ | 378 | #endif /* VRTC_CALIBRATION */ |
| 379 | |||
| 380 | device_init_wakeup(&pdev->dev, 1); | ||
| 381 | |||
| 379 | return 0; | 382 | return 0; |
| 380 | out_rtc: | 383 | out_rtc: |
| 381 | free_irq(info->irq, info); | 384 | free_irq(info->irq, info); |
| @@ -401,10 +404,34 @@ static int __devexit pm860x_rtc_remove(struct platform_device *pdev) | |||
| 401 | return 0; | 404 | return 0; |
| 402 | } | 405 | } |
| 403 | 406 | ||
| 407 | #ifdef CONFIG_PM_SLEEP | ||
| 408 | static int pm860x_rtc_suspend(struct device *dev) | ||
| 409 | { | ||
| 410 | struct platform_device *pdev = to_platform_device(dev); | ||
| 411 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 412 | |||
| 413 | if (device_may_wakeup(dev)) | ||
| 414 | chip->wakeup_flag |= 1 << PM8607_IRQ_RTC; | ||
| 415 | return 0; | ||
| 416 | } | ||
| 417 | static int pm860x_rtc_resume(struct device *dev) | ||
| 418 | { | ||
| 419 | struct platform_device *pdev = to_platform_device(dev); | ||
| 420 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 421 | |||
| 422 | if (device_may_wakeup(dev)) | ||
| 423 | chip->wakeup_flag &= ~(1 << PM8607_IRQ_RTC); | ||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | #endif | ||
| 427 | |||
| 428 | static SIMPLE_DEV_PM_OPS(pm860x_rtc_pm_ops, pm860x_rtc_suspend, pm860x_rtc_resume); | ||
| 429 | |||
| 404 | static struct platform_driver pm860x_rtc_driver = { | 430 | static struct platform_driver pm860x_rtc_driver = { |
| 405 | .driver = { | 431 | .driver = { |
| 406 | .name = "88pm860x-rtc", | 432 | .name = "88pm860x-rtc", |
| 407 | .owner = THIS_MODULE, | 433 | .owner = THIS_MODULE, |
| 434 | .pm = &pm860x_rtc_pm_ops, | ||
| 408 | }, | 435 | }, |
| 409 | .probe = pm860x_rtc_probe, | 436 | .probe = pm860x_rtc_probe, |
| 410 | .remove = __devexit_p(pm860x_rtc_remove), | 437 | .remove = __devexit_p(pm860x_rtc_remove), |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 915943af3f21..f49181c73113 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
| @@ -67,6 +67,28 @@ static inline int wled_idc(int port) | |||
| 67 | return ret; | 67 | return ret; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static int backlight_power_set(struct pm860x_chip *chip, int port, | ||
| 71 | int on) | ||
| 72 | { | ||
| 73 | int ret = -EINVAL; | ||
| 74 | |||
| 75 | switch (port) { | ||
| 76 | case PM8606_BACKLIGHT1: | ||
| 77 | ret = on ? pm8606_osc_enable(chip, WLED1_DUTY) : | ||
| 78 | pm8606_osc_disable(chip, WLED1_DUTY); | ||
| 79 | break; | ||
| 80 | case PM8606_BACKLIGHT2: | ||
| 81 | ret = on ? pm8606_osc_enable(chip, WLED2_DUTY) : | ||
| 82 | pm8606_osc_disable(chip, WLED2_DUTY); | ||
| 83 | break; | ||
| 84 | case PM8606_BACKLIGHT3: | ||
| 85 | ret = on ? pm8606_osc_enable(chip, WLED3_DUTY) : | ||
| 86 | pm8606_osc_disable(chip, WLED3_DUTY); | ||
| 87 | break; | ||
| 88 | } | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 70 | static int pm860x_backlight_set(struct backlight_device *bl, int brightness) | 92 | static int pm860x_backlight_set(struct backlight_device *bl, int brightness) |
| 71 | { | 93 | { |
| 72 | struct pm860x_backlight_data *data = bl_get_data(bl); | 94 | struct pm860x_backlight_data *data = bl_get_data(bl); |
| @@ -79,6 +101,9 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness) | |||
| 79 | else | 101 | else |
| 80 | value = brightness; | 102 | value = brightness; |
| 81 | 103 | ||
| 104 | if (brightness) | ||
| 105 | backlight_power_set(chip, data->port, 1); | ||
| 106 | |||
| 82 | ret = pm860x_reg_write(data->i2c, wled_a(data->port), value); | 107 | ret = pm860x_reg_write(data->i2c, wled_a(data->port), value); |
| 83 | if (ret < 0) | 108 | if (ret < 0) |
| 84 | goto out; | 109 | goto out; |
| @@ -115,6 +140,9 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness) | |||
| 115 | if (ret < 0) | 140 | if (ret < 0) |
| 116 | goto out; | 141 | goto out; |
| 117 | 142 | ||
| 143 | if (brightness == 0) | ||
| 144 | backlight_power_set(chip, data->port, 0); | ||
| 145 | |||
| 118 | dev_dbg(chip->dev, "set brightness %d\n", value); | 146 | dev_dbg(chip->dev, "set brightness %d\n", value); |
| 119 | data->current_brightness = value; | 147 | data->current_brightness = value; |
| 120 | return 0; | 148 | return 0; |
| @@ -170,7 +198,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
| 170 | struct backlight_device *bl; | 198 | struct backlight_device *bl; |
| 171 | struct resource *res; | 199 | struct resource *res; |
| 172 | struct backlight_properties props; | 200 | struct backlight_properties props; |
| 173 | unsigned char value; | ||
| 174 | char name[MFD_NAME_SIZE]; | 201 | char name[MFD_NAME_SIZE]; |
| 175 | int ret; | 202 | int ret; |
| 176 | 203 | ||
| @@ -217,26 +244,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
| 217 | 244 | ||
| 218 | platform_set_drvdata(pdev, bl); | 245 | platform_set_drvdata(pdev, bl); |
| 219 | 246 | ||
| 220 | /* Enable reference VSYS */ | ||
| 221 | ret = pm860x_reg_read(data->i2c, PM8606_VSYS); | ||
| 222 | if (ret < 0) | ||
| 223 | goto out; | ||
| 224 | if ((ret & PM8606_VSYS_EN) == 0) { | ||
| 225 | value = ret | PM8606_VSYS_EN; | ||
| 226 | ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value); | ||
| 227 | if (ret < 0) | ||
| 228 | goto out; | ||
| 229 | } | ||
| 230 | /* Enable reference OSC */ | ||
| 231 | ret = pm860x_reg_read(data->i2c, PM8606_MISC); | ||
| 232 | if (ret < 0) | ||
| 233 | goto out; | ||
| 234 | if ((ret & PM8606_MISC_OSC_EN) == 0) { | ||
| 235 | value = ret | PM8606_MISC_OSC_EN; | ||
| 236 | ret = pm860x_reg_write(data->i2c, PM8606_MISC, value); | ||
| 237 | if (ret < 0) | ||
| 238 | goto out; | ||
| 239 | } | ||
| 240 | /* read current backlight */ | 247 | /* read current backlight */ |
| 241 | ret = pm860x_backlight_get_brightness(bl); | 248 | ret = pm860x_backlight_get_brightness(bl); |
| 242 | if (ret < 0) | 249 | if (ret < 0) |
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 7fcab23c59ce..2463b6100333 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
| @@ -761,7 +761,7 @@ struct twl_regulator_driver_data { | |||
| 761 | 761 | ||
| 762 | /*----------------------------------------------------------------------*/ | 762 | /*----------------------------------------------------------------------*/ |
| 763 | 763 | ||
| 764 | int twl4030_sih_setup(int module); | 764 | int twl4030_sih_setup(struct device *dev, int module, int irq_base); |
| 765 | 765 | ||
| 766 | /* Offsets to Power Registers */ | 766 | /* Offsets to Power Registers */ |
| 767 | #define TWL4030_VDAC_DEV_GRP 0x3B | 767 | #define TWL4030_VDAC_DEV_GRP 0x3B |
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h index 92be3476c9f5..84d071ade1d8 100644 --- a/include/linux/mfd/88pm860x.h +++ b/include/linux/mfd/88pm860x.h | |||
| @@ -263,6 +263,22 @@ enum { | |||
| 263 | #define PM8607_PD_PREBIAS_MASK (0x1F << 0) | 263 | #define PM8607_PD_PREBIAS_MASK (0x1F << 0) |
| 264 | #define PM8607_PD_PRECHG_MASK (7 << 5) | 264 | #define PM8607_PD_PRECHG_MASK (7 << 5) |
| 265 | 265 | ||
| 266 | #define PM8606_REF_GP_OSC_OFF 0 | ||
| 267 | #define PM8606_REF_GP_OSC_ON 1 | ||
| 268 | #define PM8606_REF_GP_OSC_UNKNOWN 2 | ||
| 269 | |||
| 270 | /* Clients of reference group and 8MHz oscillator in 88PM8606 */ | ||
| 271 | enum pm8606_ref_gp_and_osc_clients { | ||
| 272 | REF_GP_NO_CLIENTS = 0, | ||
| 273 | WLED1_DUTY = (1<<0), /*PF 0x02.7:0*/ | ||
| 274 | WLED2_DUTY = (1<<1), /*PF 0x04.7:0*/ | ||
| 275 | WLED3_DUTY = (1<<2), /*PF 0x06.7:0*/ | ||
| 276 | RGB1_ENABLE = (1<<3), /*PF 0x07.1*/ | ||
| 277 | RGB2_ENABLE = (1<<4), /*PF 0x07.2*/ | ||
| 278 | LDO_VBR_EN = (1<<5), /*PF 0x12.0*/ | ||
| 279 | REF_GP_MAX_CLIENT = 0xFFFF | ||
| 280 | }; | ||
| 281 | |||
| 266 | /* Interrupt Number in 88PM8607 */ | 282 | /* Interrupt Number in 88PM8607 */ |
| 267 | enum { | 283 | enum { |
| 268 | PM8607_IRQ_ONKEY, | 284 | PM8607_IRQ_ONKEY, |
| @@ -298,6 +314,7 @@ enum { | |||
| 298 | struct pm860x_chip { | 314 | struct pm860x_chip { |
| 299 | struct device *dev; | 315 | struct device *dev; |
| 300 | struct mutex irq_lock; | 316 | struct mutex irq_lock; |
| 317 | struct mutex osc_lock; | ||
| 301 | struct i2c_client *client; | 318 | struct i2c_client *client; |
| 302 | struct i2c_client *companion; /* companion chip client */ | 319 | struct i2c_client *companion; /* companion chip client */ |
| 303 | struct regmap *regmap; | 320 | struct regmap *regmap; |
| @@ -305,12 +322,15 @@ struct pm860x_chip { | |||
| 305 | 322 | ||
| 306 | int buck3_double; /* DVC ramp slope double */ | 323 | int buck3_double; /* DVC ramp slope double */ |
| 307 | unsigned short companion_addr; | 324 | unsigned short companion_addr; |
| 325 | unsigned short osc_vote; | ||
| 308 | int id; | 326 | int id; |
| 309 | int irq_mode; | 327 | int irq_mode; |
| 310 | int irq_base; | 328 | int irq_base; |
| 311 | int core_irq; | 329 | int core_irq; |
| 312 | unsigned char chip_version; | 330 | unsigned char chip_version; |
| 331 | unsigned char osc_status; | ||
| 313 | 332 | ||
| 333 | unsigned int wakeup_flag; | ||
| 314 | }; | 334 | }; |
| 315 | 335 | ||
| 316 | enum { | 336 | enum { |
| @@ -369,6 +389,9 @@ struct pm860x_platform_data { | |||
| 369 | int num_regulators; | 389 | int num_regulators; |
| 370 | }; | 390 | }; |
| 371 | 391 | ||
| 392 | extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short); | ||
| 393 | extern int pm8606_osc_disable(struct pm860x_chip *, unsigned short); | ||
| 394 | |||
| 372 | extern int pm860x_reg_read(struct i2c_client *, int); | 395 | extern int pm860x_reg_read(struct i2c_client *, int); |
| 373 | extern int pm860x_reg_write(struct i2c_client *, int, unsigned char); | 396 | extern int pm860x_reg_write(struct i2c_client *, int, unsigned char); |
| 374 | extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *); | 397 | extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *); |
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index e20dd6ead1d0..5fa697477b71 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h | |||
| @@ -34,13 +34,6 @@ struct device; | |||
| 34 | #define AB5500_1_1 0x21 | 34 | #define AB5500_1_1 0x21 |
| 35 | #define AB5500_2_0 0x24 | 35 | #define AB5500_2_0 0x24 |
| 36 | 36 | ||
| 37 | /* AB8500 CIDs*/ | ||
| 38 | #define AB8500_CUT1P0 0x10 | ||
| 39 | #define AB8500_CUT1P1 0x11 | ||
| 40 | #define AB8500_CUT2P0 0x20 | ||
| 41 | #define AB8500_CUT3P0 0x30 | ||
| 42 | #define AB8500_CUT3P3 0x33 | ||
| 43 | |||
| 44 | /* | 37 | /* |
| 45 | * AB3100, EVENTA1, A2 and A3 event register flags | 38 | * AB3100, EVENTA1, A2 and A3 event register flags |
| 46 | * these are catenated into a single 32-bit flag in the code | 39 | * these are catenated into a single 32-bit flag in the code |
diff --git a/include/linux/mfd/abx500/ab8500-gpio.h b/include/linux/mfd/abx500/ab8500-gpio.h index 488a8c920a29..2387c207ea86 100644 --- a/include/linux/mfd/abx500/ab8500-gpio.h +++ b/include/linux/mfd/abx500/ab8500-gpio.h | |||
| @@ -10,12 +10,14 @@ | |||
| 10 | 10 | ||
| 11 | /* | 11 | /* |
| 12 | * Platform data to register a block: only the initial gpio/irq number. | 12 | * Platform data to register a block: only the initial gpio/irq number. |
| 13 | * Array sizes are large enough to contain all AB8500 and AB9540 GPIO | ||
| 14 | * registers. | ||
| 13 | */ | 15 | */ |
| 14 | 16 | ||
| 15 | struct ab8500_gpio_platform_data { | 17 | struct ab8500_gpio_platform_data { |
| 16 | int gpio_base; | 18 | int gpio_base; |
| 17 | u32 irq_base; | 19 | u32 irq_base; |
| 18 | u8 config_reg[7]; | 20 | u8 config_reg[8]; |
| 19 | }; | 21 | }; |
| 20 | 22 | ||
| 21 | #endif /* _AB8500_GPIO_H */ | 23 | #endif /* _AB8500_GPIO_H */ |
diff --git a/include/linux/mfd/abx500/ab8500-sysctrl.h b/include/linux/mfd/abx500/ab8500-sysctrl.h index 10da0291f8f8..10eb50973c39 100644 --- a/include/linux/mfd/abx500/ab8500-sysctrl.h +++ b/include/linux/mfd/abx500/ab8500-sysctrl.h | |||
| @@ -71,6 +71,13 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits) | |||
| 71 | #define AB8500_SWATCTRL 0x230 | 71 | #define AB8500_SWATCTRL 0x230 |
| 72 | #define AB8500_HIQCLKCTRL 0x232 | 72 | #define AB8500_HIQCLKCTRL 0x232 |
| 73 | #define AB8500_VSIMSYSCLKCTRL 0x233 | 73 | #define AB8500_VSIMSYSCLKCTRL 0x233 |
| 74 | #define AB9540_SYSCLK12BUFCTRL 0x234 | ||
| 75 | #define AB9540_SYSCLK12CONFCTRL 0x235 | ||
| 76 | #define AB9540_SYSCLK12BUFCTRL2 0x236 | ||
| 77 | #define AB9540_SYSCLK12BUF1VALID 0x237 | ||
| 78 | #define AB9540_SYSCLK12BUF2VALID 0x238 | ||
| 79 | #define AB9540_SYSCLK12BUF3VALID 0x239 | ||
| 80 | #define AB9540_SYSCLK12BUF4VALID 0x23A | ||
| 74 | 81 | ||
| 75 | /* Bits */ | 82 | /* Bits */ |
| 76 | #define AB8500_TURNONSTATUS_PORNVBAT BIT(0) | 83 | #define AB8500_TURNONSTATUS_PORNVBAT BIT(0) |
| @@ -251,4 +258,40 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits) | |||
| 251 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ7VALID BIT(6) | 258 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ7VALID BIT(6) |
| 252 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ8VALID BIT(7) | 259 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ8VALID BIT(7) |
| 253 | 260 | ||
| 261 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF1ENA BIT(0) | ||
| 262 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF2ENA BIT(1) | ||
| 263 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF3ENA BIT(2) | ||
| 264 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF4ENA BIT(3) | ||
| 265 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUFENA_MASK 0x0F | ||
| 266 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF1STRE BIT(4) | ||
| 267 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF2STRE BIT(5) | ||
| 268 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF3STRE BIT(6) | ||
| 269 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF4STRE BIT(7) | ||
| 270 | #define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUFSTRE_MASK 0xF0 | ||
| 271 | |||
| 272 | #define AB9540_SYSCLK12CONFCTRL_PLL26TO38ENA BIT(0) | ||
| 273 | #define AB9540_SYSCLK12CONFCTRL_SYSCLK12USBMUXSEL BIT(1) | ||
| 274 | #define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_MASK 0x0C | ||
| 275 | #define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_SHIFT 2 | ||
| 276 | #define AB9540_SYSCLK12CONFCTRL_SYSCLK12BUFMUX BIT(4) | ||
| 277 | #define AB9540_SYSCLK12CONFCTRL_SYSCLK12PLLMUX BIT(5) | ||
| 278 | #define AB9540_SYSCLK12CONFCTRL_SYSCLK2MUXVALID BIT(6) | ||
| 279 | |||
| 280 | #define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF1PDENA BIT(0) | ||
| 281 | #define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF2PDENA BIT(1) | ||
| 282 | #define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF3PDENA BIT(2) | ||
| 283 | #define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF4PDENA BIT(3) | ||
| 284 | |||
| 285 | #define AB9540_SYSCLK12BUF1VALID_SYSCLK12BUF1VALID_MASK 0xFF | ||
| 286 | #define AB9540_SYSCLK12BUF1VALID_SYSCLK12BUF1VALID_SHIFT 0 | ||
| 287 | |||
| 288 | #define AB9540_SYSCLK12BUF2VALID_SYSCLK12BUF2VALID_MASK 0xFF | ||
| 289 | #define AB9540_SYSCLK12BUF2VALID_SYSCLK12BUF2VALID_SHIFT 0 | ||
| 290 | |||
| 291 | #define AB9540_SYSCLK12BUF3VALID_SYSCLK12BUF3VALID_MASK 0xFF | ||
| 292 | #define AB9540_SYSCLK12BUF3VALID_SYSCLK12BUF3VALID_SHIFT 0 | ||
| 293 | |||
| 294 | #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF | ||
| 295 | #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0 | ||
| 296 | |||
| 254 | #endif /* __AB8500_SYSCTRL_H */ | 297 | #endif /* __AB8500_SYSCTRL_H */ |
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index dca94396190d..fccc3002f271 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h | |||
| @@ -12,6 +12,29 @@ | |||
| 12 | struct device; | 12 | struct device; |
| 13 | 13 | ||
| 14 | /* | 14 | /* |
| 15 | * AB IC versions | ||
| 16 | * | ||
| 17 | * AB8500_VERSION_AB8500 should be 0xFF but will never be read as need a | ||
| 18 | * non-supported multi-byte I2C access via PRCMU. Set to 0x00 to ease the | ||
| 19 | * print of version string. | ||
| 20 | */ | ||
| 21 | enum ab8500_version { | ||
| 22 | AB8500_VERSION_AB8500 = 0x0, | ||
| 23 | AB8500_VERSION_AB8505 = 0x1, | ||
| 24 | AB8500_VERSION_AB9540 = 0x2, | ||
| 25 | AB8500_VERSION_AB8540 = 0x3, | ||
| 26 | AB8500_VERSION_UNDEFINED, | ||
| 27 | }; | ||
| 28 | |||
| 29 | /* AB8500 CIDs*/ | ||
| 30 | #define AB8500_CUTEARLY 0x00 | ||
| 31 | #define AB8500_CUT1P0 0x10 | ||
| 32 | #define AB8500_CUT1P1 0x11 | ||
| 33 | #define AB8500_CUT2P0 0x20 | ||
| 34 | #define AB8500_CUT3P0 0x30 | ||
| 35 | #define AB8500_CUT3P3 0x33 | ||
| 36 | |||
| 37 | /* | ||
| 15 | * AB8500 bank addresses | 38 | * AB8500 bank addresses |
| 16 | */ | 39 | */ |
| 17 | #define AB8500_SYS_CTRL1_BLOCK 0x1 | 40 | #define AB8500_SYS_CTRL1_BLOCK 0x1 |
| @@ -37,30 +60,34 @@ struct device; | |||
| 37 | 60 | ||
| 38 | /* | 61 | /* |
| 39 | * Interrupts | 62 | * Interrupts |
| 63 | * Values used to index into array ab8500_irq_regoffset[] defined in | ||
| 64 | * drivers/mdf/ab8500-core.c | ||
| 40 | */ | 65 | */ |
| 41 | 66 | /* Definitions for AB8500 and AB9540 */ | |
| 42 | #define AB8500_INT_MAIN_EXT_CH_NOT_OK 0 | 67 | /* ab8500_irq_regoffset[0] -> IT[Source|Latch|Mask]1 */ |
| 43 | #define AB8500_INT_UN_PLUG_TV_DET 1 | 68 | #define AB8500_INT_MAIN_EXT_CH_NOT_OK 0 /* not 8505/9540 */ |
| 44 | #define AB8500_INT_PLUG_TV_DET 2 | 69 | #define AB8500_INT_UN_PLUG_TV_DET 1 /* not 8505/9540 */ |
| 70 | #define AB8500_INT_PLUG_TV_DET 2 /* not 8505/9540 */ | ||
| 45 | #define AB8500_INT_TEMP_WARM 3 | 71 | #define AB8500_INT_TEMP_WARM 3 |
| 46 | #define AB8500_INT_PON_KEY2DB_F 4 | 72 | #define AB8500_INT_PON_KEY2DB_F 4 |
| 47 | #define AB8500_INT_PON_KEY2DB_R 5 | 73 | #define AB8500_INT_PON_KEY2DB_R 5 |
| 48 | #define AB8500_INT_PON_KEY1DB_F 6 | 74 | #define AB8500_INT_PON_KEY1DB_F 6 |
| 49 | #define AB8500_INT_PON_KEY1DB_R 7 | 75 | #define AB8500_INT_PON_KEY1DB_R 7 |
| 76 | /* ab8500_irq_regoffset[1] -> IT[Source|Latch|Mask]2 */ | ||
| 50 | #define AB8500_INT_BATT_OVV 8 | 77 | #define AB8500_INT_BATT_OVV 8 |
| 51 | #define AB8500_INT_MAIN_CH_UNPLUG_DET 10 | 78 | #define AB8500_INT_MAIN_CH_UNPLUG_DET 10 /* not 8505 */ |
| 52 | #define AB8500_INT_MAIN_CH_PLUG_DET 11 | 79 | #define AB8500_INT_MAIN_CH_PLUG_DET 11 /* not 8505 */ |
| 53 | #define AB8500_INT_USB_ID_DET_F 12 | ||
| 54 | #define AB8500_INT_USB_ID_DET_R 13 | ||
| 55 | #define AB8500_INT_VBUS_DET_F 14 | 80 | #define AB8500_INT_VBUS_DET_F 14 |
| 56 | #define AB8500_INT_VBUS_DET_R 15 | 81 | #define AB8500_INT_VBUS_DET_R 15 |
| 82 | /* ab8500_irq_regoffset[2] -> IT[Source|Latch|Mask]3 */ | ||
| 57 | #define AB8500_INT_VBUS_CH_DROP_END 16 | 83 | #define AB8500_INT_VBUS_CH_DROP_END 16 |
| 58 | #define AB8500_INT_RTC_60S 17 | 84 | #define AB8500_INT_RTC_60S 17 |
| 59 | #define AB8500_INT_RTC_ALARM 18 | 85 | #define AB8500_INT_RTC_ALARM 18 |
| 60 | #define AB8500_INT_BAT_CTRL_INDB 20 | 86 | #define AB8500_INT_BAT_CTRL_INDB 20 |
| 61 | #define AB8500_INT_CH_WD_EXP 21 | 87 | #define AB8500_INT_CH_WD_EXP 21 |
| 62 | #define AB8500_INT_VBUS_OVV 22 | 88 | #define AB8500_INT_VBUS_OVV 22 |
| 63 | #define AB8500_INT_MAIN_CH_DROP_END 23 | 89 | #define AB8500_INT_MAIN_CH_DROP_END 23 /* not 8505/9540 */ |
| 90 | /* ab8500_irq_regoffset[3] -> IT[Source|Latch|Mask]4 */ | ||
| 64 | #define AB8500_INT_CCN_CONV_ACC 24 | 91 | #define AB8500_INT_CCN_CONV_ACC 24 |
| 65 | #define AB8500_INT_INT_AUD 25 | 92 | #define AB8500_INT_INT_AUD 25 |
| 66 | #define AB8500_INT_CCEOC 26 | 93 | #define AB8500_INT_CCEOC 26 |
| @@ -69,7 +96,8 @@ struct device; | |||
| 69 | #define AB8500_INT_LOW_BAT_R 29 | 96 | #define AB8500_INT_LOW_BAT_R 29 |
| 70 | #define AB8500_INT_BUP_CHG_NOT_OK 30 | 97 | #define AB8500_INT_BUP_CHG_NOT_OK 30 |
| 71 | #define AB8500_INT_BUP_CHG_OK 31 | 98 | #define AB8500_INT_BUP_CHG_OK 31 |
| 72 | #define AB8500_INT_GP_HW_ADC_CONV_END 32 | 99 | /* ab8500_irq_regoffset[4] -> IT[Source|Latch|Mask]5 */ |
| 100 | #define AB8500_INT_GP_HW_ADC_CONV_END 32 /* not 8505 */ | ||
| 73 | #define AB8500_INT_ACC_DETECT_1DB_F 33 | 101 | #define AB8500_INT_ACC_DETECT_1DB_F 33 |
| 74 | #define AB8500_INT_ACC_DETECT_1DB_R 34 | 102 | #define AB8500_INT_ACC_DETECT_1DB_R 34 |
| 75 | #define AB8500_INT_ACC_DETECT_22DB_F 35 | 103 | #define AB8500_INT_ACC_DETECT_22DB_F 35 |
| @@ -77,38 +105,43 @@ struct device; | |||
| 77 | #define AB8500_INT_ACC_DETECT_21DB_F 37 | 105 | #define AB8500_INT_ACC_DETECT_21DB_F 37 |
| 78 | #define AB8500_INT_ACC_DETECT_21DB_R 38 | 106 | #define AB8500_INT_ACC_DETECT_21DB_R 38 |
| 79 | #define AB8500_INT_GP_SW_ADC_CONV_END 39 | 107 | #define AB8500_INT_GP_SW_ADC_CONV_END 39 |
| 80 | #define AB8500_INT_GPIO6R 40 | 108 | /* ab8500_irq_regoffset[5] -> IT[Source|Latch|Mask]7 */ |
| 81 | #define AB8500_INT_GPIO7R 41 | 109 | #define AB8500_INT_GPIO6R 40 /* not 8505/9540 */ |
| 82 | #define AB8500_INT_GPIO8R 42 | 110 | #define AB8500_INT_GPIO7R 41 /* not 8505/9540 */ |
| 83 | #define AB8500_INT_GPIO9R 43 | 111 | #define AB8500_INT_GPIO8R 42 /* not 8505/9540 */ |
| 112 | #define AB8500_INT_GPIO9R 43 /* not 8505/9540 */ | ||
| 84 | #define AB8500_INT_GPIO10R 44 | 113 | #define AB8500_INT_GPIO10R 44 |
| 85 | #define AB8500_INT_GPIO11R 45 | 114 | #define AB8500_INT_GPIO11R 45 |
| 86 | #define AB8500_INT_GPIO12R 46 | 115 | #define AB8500_INT_GPIO12R 46 /* not 8505 */ |
| 87 | #define AB8500_INT_GPIO13R 47 | 116 | #define AB8500_INT_GPIO13R 47 |
| 88 | #define AB8500_INT_GPIO24R 48 | 117 | /* ab8500_irq_regoffset[6] -> IT[Source|Latch|Mask]8 */ |
| 89 | #define AB8500_INT_GPIO25R 49 | 118 | #define AB8500_INT_GPIO24R 48 /* not 8505 */ |
| 90 | #define AB8500_INT_GPIO36R 50 | 119 | #define AB8500_INT_GPIO25R 49 /* not 8505 */ |
| 91 | #define AB8500_INT_GPIO37R 51 | 120 | #define AB8500_INT_GPIO36R 50 /* not 8505/9540 */ |
| 92 | #define AB8500_INT_GPIO38R 52 | 121 | #define AB8500_INT_GPIO37R 51 /* not 8505/9540 */ |
| 93 | #define AB8500_INT_GPIO39R 53 | 122 | #define AB8500_INT_GPIO38R 52 /* not 8505/9540 */ |
| 123 | #define AB8500_INT_GPIO39R 53 /* not 8505/9540 */ | ||
| 94 | #define AB8500_INT_GPIO40R 54 | 124 | #define AB8500_INT_GPIO40R 54 |
| 95 | #define AB8500_INT_GPIO41R 55 | 125 | #define AB8500_INT_GPIO41R 55 |
| 96 | #define AB8500_INT_GPIO6F 56 | 126 | /* ab8500_irq_regoffset[7] -> IT[Source|Latch|Mask]9 */ |
| 97 | #define AB8500_INT_GPIO7F 57 | 127 | #define AB8500_INT_GPIO6F 56 /* not 8505/9540 */ |
| 98 | #define AB8500_INT_GPIO8F 58 | 128 | #define AB8500_INT_GPIO7F 57 /* not 8505/9540 */ |
| 99 | #define AB8500_INT_GPIO9F 59 | 129 | #define AB8500_INT_GPIO8F 58 /* not 8505/9540 */ |
| 130 | #define AB8500_INT_GPIO9F 59 /* not 8505/9540 */ | ||
| 100 | #define AB8500_INT_GPIO10F 60 | 131 | #define AB8500_INT_GPIO10F 60 |
| 101 | #define AB8500_INT_GPIO11F 61 | 132 | #define AB8500_INT_GPIO11F 61 |
| 102 | #define AB8500_INT_GPIO12F 62 | 133 | #define AB8500_INT_GPIO12F 62 /* not 8505 */ |
| 103 | #define AB8500_INT_GPIO13F 63 | 134 | #define AB8500_INT_GPIO13F 63 |
| 104 | #define AB8500_INT_GPIO24F 64 | 135 | /* ab8500_irq_regoffset[8] -> IT[Source|Latch|Mask]10 */ |
| 105 | #define AB8500_INT_GPIO25F 65 | 136 | #define AB8500_INT_GPIO24F 64 /* not 8505 */ |
| 106 | #define AB8500_INT_GPIO36F 66 | 137 | #define AB8500_INT_GPIO25F 65 /* not 8505 */ |
| 107 | #define AB8500_INT_GPIO37F 67 | 138 | #define AB8500_INT_GPIO36F 66 /* not 8505/9540 */ |
| 108 | #define AB8500_INT_GPIO38F 68 | 139 | #define AB8500_INT_GPIO37F 67 /* not 8505/9540 */ |
| 109 | #define AB8500_INT_GPIO39F 69 | 140 | #define AB8500_INT_GPIO38F 68 /* not 8505/9540 */ |
| 141 | #define AB8500_INT_GPIO39F 69 /* not 8505/9540 */ | ||
| 110 | #define AB8500_INT_GPIO40F 70 | 142 | #define AB8500_INT_GPIO40F 70 |
| 111 | #define AB8500_INT_GPIO41F 71 | 143 | #define AB8500_INT_GPIO41F 71 |
| 144 | /* ab8500_irq_regoffset[9] -> IT[Source|Latch|Mask]12 */ | ||
| 112 | #define AB8500_INT_ADP_SOURCE_ERROR 72 | 145 | #define AB8500_INT_ADP_SOURCE_ERROR 72 |
| 113 | #define AB8500_INT_ADP_SINK_ERROR 73 | 146 | #define AB8500_INT_ADP_SINK_ERROR 73 |
| 114 | #define AB8500_INT_ADP_PROBE_PLUG 74 | 147 | #define AB8500_INT_ADP_PROBE_PLUG 74 |
| @@ -116,30 +149,67 @@ struct device; | |||
| 116 | #define AB8500_INT_ADP_SENSE_OFF 76 | 149 | #define AB8500_INT_ADP_SENSE_OFF 76 |
| 117 | #define AB8500_INT_USB_PHY_POWER_ERR 78 | 150 | #define AB8500_INT_USB_PHY_POWER_ERR 78 |
| 118 | #define AB8500_INT_USB_LINK_STATUS 79 | 151 | #define AB8500_INT_USB_LINK_STATUS 79 |
| 152 | /* ab8500_irq_regoffset[10] -> IT[Source|Latch|Mask]19 */ | ||
| 119 | #define AB8500_INT_BTEMP_LOW 80 | 153 | #define AB8500_INT_BTEMP_LOW 80 |
| 120 | #define AB8500_INT_BTEMP_LOW_MEDIUM 81 | 154 | #define AB8500_INT_BTEMP_LOW_MEDIUM 81 |
| 121 | #define AB8500_INT_BTEMP_MEDIUM_HIGH 82 | 155 | #define AB8500_INT_BTEMP_MEDIUM_HIGH 82 |
| 122 | #define AB8500_INT_BTEMP_HIGH 83 | 156 | #define AB8500_INT_BTEMP_HIGH 83 |
| 123 | #define AB8500_INT_USB_CHARGER_NOT_OK 89 | 157 | /* ab8500_irq_regoffset[11] -> IT[Source|Latch|Mask]20 */ |
| 158 | #define AB8500_INT_SRP_DETECT 88 | ||
| 159 | #define AB8500_INT_USB_CHARGER_NOT_OKR 89 | ||
| 124 | #define AB8500_INT_ID_WAKEUP_R 90 | 160 | #define AB8500_INT_ID_WAKEUP_R 90 |
| 125 | #define AB8500_INT_ID_DET_R1R 92 | 161 | #define AB8500_INT_ID_DET_R1R 92 |
| 126 | #define AB8500_INT_ID_DET_R2R 93 | 162 | #define AB8500_INT_ID_DET_R2R 93 |
| 127 | #define AB8500_INT_ID_DET_R3R 94 | 163 | #define AB8500_INT_ID_DET_R3R 94 |
| 128 | #define AB8500_INT_ID_DET_R4R 95 | 164 | #define AB8500_INT_ID_DET_R4R 95 |
| 165 | /* ab8500_irq_regoffset[12] -> IT[Source|Latch|Mask]21 */ | ||
| 129 | #define AB8500_INT_ID_WAKEUP_F 96 | 166 | #define AB8500_INT_ID_WAKEUP_F 96 |
| 130 | #define AB8500_INT_ID_DET_R1F 98 | 167 | #define AB8500_INT_ID_DET_R1F 98 |
| 131 | #define AB8500_INT_ID_DET_R2F 99 | 168 | #define AB8500_INT_ID_DET_R2F 99 |
| 132 | #define AB8500_INT_ID_DET_R3F 100 | 169 | #define AB8500_INT_ID_DET_R3F 100 |
| 133 | #define AB8500_INT_ID_DET_R4F 101 | 170 | #define AB8500_INT_ID_DET_R4F 101 |
| 134 | #define AB8500_INT_USB_CHG_DET_DONE 102 | 171 | #define AB8500_INT_CHAUTORESTARTAFTSEC 102 |
| 172 | #define AB8500_INT_CHSTOPBYSEC 103 | ||
| 173 | /* ab8500_irq_regoffset[13] -> IT[Source|Latch|Mask]22 */ | ||
| 135 | #define AB8500_INT_USB_CH_TH_PROT_F 104 | 174 | #define AB8500_INT_USB_CH_TH_PROT_F 104 |
| 136 | #define AB8500_INT_USB_CH_TH_PROT_R 105 | 175 | #define AB8500_INT_USB_CH_TH_PROT_R 105 |
| 137 | #define AB8500_INT_MAIN_CH_TH_PROT_F 106 | 176 | #define AB8500_INT_MAIN_CH_TH_PROT_F 106 /* not 8505/9540 */ |
| 138 | #define AB8500_INT_MAIN_CH_TH_PROT_R 107 | 177 | #define AB8500_INT_MAIN_CH_TH_PROT_R 107 /* not 8505/9540 */ |
| 139 | #define AB8500_INT_USB_CHARGER_NOT_OKF 111 | 178 | #define AB8500_INT_CHCURLIMNOHSCHIRP 109 |
| 179 | #define AB8500_INT_CHCURLIMHSCHIRP 110 | ||
| 180 | #define AB8500_INT_XTAL32K_KO 111 | ||
| 181 | |||
| 182 | /* Definitions for AB9540 */ | ||
| 183 | /* ab8500_irq_regoffset[14] -> IT[Source|Latch|Mask]13 */ | ||
| 184 | #define AB9540_INT_GPIO50R 113 | ||
| 185 | #define AB9540_INT_GPIO51R 114 /* not 8505 */ | ||
| 186 | #define AB9540_INT_GPIO52R 115 | ||
| 187 | #define AB9540_INT_GPIO53R 116 | ||
| 188 | #define AB9540_INT_GPIO54R 117 /* not 8505 */ | ||
| 189 | #define AB9540_INT_IEXT_CH_RF_BFN_R 118 | ||
| 190 | #define AB9540_INT_IEXT_CH_RF_BFN_F 119 | ||
| 191 | /* ab8500_irq_regoffset[15] -> IT[Source|Latch|Mask]14 */ | ||
| 192 | #define AB9540_INT_GPIO50F 121 | ||
| 193 | #define AB9540_INT_GPIO51F 122 /* not 8505 */ | ||
| 194 | #define AB9540_INT_GPIO52F 123 | ||
| 195 | #define AB9540_INT_GPIO53F 124 | ||
| 196 | #define AB9540_INT_GPIO54F 125 /* not 8505 */ | ||
| 140 | 197 | ||
| 198 | /* | ||
| 199 | * AB8500_AB9540_NR_IRQS is used when configuring the IRQ numbers for the | ||
| 200 | * entire platform. This is a "compile time" constant so this must be set to | ||
| 201 | * the largest possible value that may be encountered with different AB SOCs. | ||
| 202 | * Of the currently supported AB devices, AB8500 and AB9540, it is the AB9540 | ||
| 203 | * which is larger. | ||
| 204 | */ | ||
| 141 | #define AB8500_NR_IRQS 112 | 205 | #define AB8500_NR_IRQS 112 |
| 206 | #define AB8505_NR_IRQS 128 | ||
| 207 | #define AB9540_NR_IRQS 128 | ||
| 208 | /* This is set to the roof of any AB8500 chip variant IRQ counts */ | ||
| 209 | #define AB8500_MAX_NR_IRQS AB9540_NR_IRQS | ||
| 210 | |||
| 142 | #define AB8500_NUM_IRQ_REGS 14 | 211 | #define AB8500_NUM_IRQ_REGS 14 |
| 212 | #define AB9540_NUM_IRQ_REGS 17 | ||
| 143 | 213 | ||
| 144 | /** | 214 | /** |
| 145 | * struct ab8500 - ab8500 internal structure | 215 | * struct ab8500 - ab8500 internal structure |
| @@ -147,13 +217,18 @@ struct device; | |||
| 147 | * @lock: read/write operations lock | 217 | * @lock: read/write operations lock |
| 148 | * @irq_lock: genirq bus lock | 218 | * @irq_lock: genirq bus lock |
| 149 | * @irq: irq line | 219 | * @irq: irq line |
| 220 | * @version: chip version id (e.g. ab8500 or ab9540) | ||
| 150 | * @chip_id: chip revision id | 221 | * @chip_id: chip revision id |
| 151 | * @write: register write | 222 | * @write: register write |
| 223 | * @write_masked: masked register write | ||
| 152 | * @read: register read | 224 | * @read: register read |
| 153 | * @rx_buf: rx buf for SPI | 225 | * @rx_buf: rx buf for SPI |
| 154 | * @tx_buf: tx buf for SPI | 226 | * @tx_buf: tx buf for SPI |
| 155 | * @mask: cache of IRQ regs for bus lock | 227 | * @mask: cache of IRQ regs for bus lock |
| 156 | * @oldmask: cache of previous IRQ regs for bus lock | 228 | * @oldmask: cache of previous IRQ regs for bus lock |
| 229 | * @mask_size: Actual number of valid entries in mask[], oldmask[] and | ||
| 230 | * irq_reg_offset | ||
| 231 | * @irq_reg_offset: Array of offsets into IRQ registers | ||
| 157 | */ | 232 | */ |
| 158 | struct ab8500 { | 233 | struct ab8500 { |
| 159 | struct device *dev; | 234 | struct device *dev; |
| @@ -162,16 +237,20 @@ struct ab8500 { | |||
| 162 | 237 | ||
| 163 | int irq_base; | 238 | int irq_base; |
| 164 | int irq; | 239 | int irq; |
| 240 | enum ab8500_version version; | ||
| 165 | u8 chip_id; | 241 | u8 chip_id; |
| 166 | 242 | ||
| 167 | int (*write) (struct ab8500 *a8500, u16 addr, u8 data); | 243 | int (*write)(struct ab8500 *ab8500, u16 addr, u8 data); |
| 168 | int (*read) (struct ab8500 *a8500, u16 addr); | 244 | int (*write_masked)(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data); |
| 245 | int (*read)(struct ab8500 *ab8500, u16 addr); | ||
| 169 | 246 | ||
| 170 | unsigned long tx_buf[4]; | 247 | unsigned long tx_buf[4]; |
| 171 | unsigned long rx_buf[4]; | 248 | unsigned long rx_buf[4]; |
| 172 | 249 | ||
| 173 | u8 mask[AB8500_NUM_IRQ_REGS]; | 250 | u8 *mask; |
| 174 | u8 oldmask[AB8500_NUM_IRQ_REGS]; | 251 | u8 *oldmask; |
| 252 | int mask_size; | ||
| 253 | const int *irq_reg_offset; | ||
| 175 | }; | 254 | }; |
| 176 | 255 | ||
| 177 | struct regulator_reg_init; | 256 | struct regulator_reg_init; |
| @@ -197,7 +276,52 @@ struct ab8500_platform_data { | |||
| 197 | struct ab8500_gpio_platform_data *gpio; | 276 | struct ab8500_gpio_platform_data *gpio; |
| 198 | }; | 277 | }; |
| 199 | 278 | ||
| 200 | extern int __devinit ab8500_init(struct ab8500 *ab8500); | 279 | extern int __devinit ab8500_init(struct ab8500 *ab8500, |
| 280 | enum ab8500_version version); | ||
| 201 | extern int __devexit ab8500_exit(struct ab8500 *ab8500); | 281 | extern int __devexit ab8500_exit(struct ab8500 *ab8500); |
| 202 | 282 | ||
| 283 | static inline int is_ab8500(struct ab8500 *ab) | ||
| 284 | { | ||
| 285 | return ab->version == AB8500_VERSION_AB8500; | ||
| 286 | } | ||
| 287 | |||
| 288 | static inline int is_ab8505(struct ab8500 *ab) | ||
| 289 | { | ||
| 290 | return ab->version == AB8500_VERSION_AB8505; | ||
| 291 | } | ||
| 292 | |||
| 293 | static inline int is_ab9540(struct ab8500 *ab) | ||
| 294 | { | ||
| 295 | return ab->version == AB8500_VERSION_AB9540; | ||
| 296 | } | ||
| 297 | |||
| 298 | static inline int is_ab8540(struct ab8500 *ab) | ||
| 299 | { | ||
| 300 | return ab->version == AB8500_VERSION_AB8540; | ||
| 301 | } | ||
| 302 | |||
| 303 | /* exclude also ab8505, ab9540... */ | ||
| 304 | static inline int is_ab8500_1p0_or_earlier(struct ab8500 *ab) | ||
| 305 | { | ||
| 306 | return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P0)); | ||
| 307 | } | ||
| 308 | |||
| 309 | /* exclude also ab8505, ab9540... */ | ||
| 310 | static inline int is_ab8500_1p1_or_earlier(struct ab8500 *ab) | ||
| 311 | { | ||
| 312 | return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P1)); | ||
| 313 | } | ||
| 314 | |||
| 315 | /* exclude also ab8505, ab9540... */ | ||
| 316 | static inline int is_ab8500_2p0_or_earlier(struct ab8500 *ab) | ||
| 317 | { | ||
| 318 | return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT2P0)); | ||
| 319 | } | ||
| 320 | |||
| 321 | /* exclude also ab8505, ab9540... */ | ||
| 322 | static inline int is_ab8500_2p0(struct ab8500 *ab) | ||
| 323 | { | ||
| 324 | return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0)); | ||
| 325 | } | ||
| 326 | |||
| 203 | #endif /* MFD_AB8500_H */ | 327 | #endif /* MFD_AB8500_H */ |
diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h new file mode 100644 index 000000000000..22c1007d3ec5 --- /dev/null +++ b/include/linux/mfd/anatop.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* | ||
| 2 | * anatop.h - Anatop MFD driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org> | ||
| 5 | * Copyright (C) 2012 Linaro | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef __LINUX_MFD_ANATOP_H | ||
| 23 | #define __LINUX_MFD_ANATOP_H | ||
| 24 | |||
| 25 | #include <linux/spinlock.h> | ||
| 26 | |||
| 27 | /** | ||
| 28 | * anatop - MFD data | ||
| 29 | * @ioreg: ioremap register | ||
| 30 | * @reglock: spinlock for register read/write | ||
| 31 | */ | ||
| 32 | struct anatop { | ||
| 33 | void *ioreg; | ||
| 34 | spinlock_t reglock; | ||
| 35 | }; | ||
| 36 | |||
| 37 | extern u32 anatop_get_bits(struct anatop *, u32, int, int); | ||
| 38 | extern void anatop_set_bits(struct anatop *, u32, int, int, u32); | ||
| 39 | |||
| 40 | #endif /* __LINUX_MFD_ANATOP_H */ | ||
diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h index 5702d1be13b4..7ffbd6e9e7fc 100644 --- a/include/linux/mfd/da9052/da9052.h +++ b/include/linux/mfd/da9052/da9052.h | |||
| @@ -76,8 +76,6 @@ enum da9052_chip_id { | |||
| 76 | struct da9052_pdata; | 76 | struct da9052_pdata; |
| 77 | 77 | ||
| 78 | struct da9052 { | 78 | struct da9052 { |
| 79 | struct mutex io_lock; | ||
| 80 | |||
| 81 | struct device *dev; | 79 | struct device *dev; |
| 82 | struct regmap *regmap; | 80 | struct regmap *regmap; |
| 83 | 81 | ||
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index 60d27f7bfc1f..b3a43b1263fe 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h | |||
| @@ -11,6 +11,24 @@ | |||
| 11 | #define __MFD_DB8500_PRCMU_H | 11 | #define __MFD_DB8500_PRCMU_H |
| 12 | 12 | ||
| 13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 14 | #include <linux/bitops.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * Registers | ||
| 18 | */ | ||
| 19 | #define DB8500_PRCM_GPIOCR 0x138 | ||
| 20 | #define DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0 BIT(0) | ||
| 21 | #define DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD BIT(9) | ||
| 22 | #define DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 BIT(11) | ||
| 23 | #define DB8500_PRCM_GPIOCR_SPI2_SELECT BIT(23) | ||
| 24 | |||
| 25 | #define DB8500_PRCM_LINE_VALUE 0x170 | ||
| 26 | #define DB8500_PRCM_LINE_VALUE_HSI_CAWAKE0 BIT(3) | ||
| 27 | |||
| 28 | #define DB8500_PRCM_DSI_SW_RESET 0x324 | ||
| 29 | #define DB8500_PRCM_DSI_SW_RESET_DSI0_SW_RESETN BIT(0) | ||
| 30 | #define DB8500_PRCM_DSI_SW_RESET_DSI1_SW_RESETN BIT(1) | ||
| 31 | #define DB8500_PRCM_DSI_SW_RESET_DSI2_SW_RESETN BIT(2) | ||
| 14 | 32 | ||
| 15 | /* This portion previously known as <mach/prcmu-fw-defs_v1.h> */ | 33 | /* This portion previously known as <mach/prcmu-fw-defs_v1.h> */ |
| 16 | 34 | ||
| @@ -421,40 +439,22 @@ enum auto_enable { | |||
| 421 | /* End of file previously known as prcmu-fw-defs_v1.h */ | 439 | /* End of file previously known as prcmu-fw-defs_v1.h */ |
| 422 | 440 | ||
| 423 | /** | 441 | /** |
| 424 | * enum hw_acc_dev - enum for hw accelerators | 442 | * enum prcmu_power_status - results from set_power_state |
| 425 | * @HW_ACC_SVAMMDSP: for SVAMMDSP | 443 | * @PRCMU_SLEEP_OK: Sleep went ok |
| 426 | * @HW_ACC_SVAPIPE: for SVAPIPE | 444 | * @PRCMU_DEEP_SLEEP_OK: DeepSleep went ok |
| 427 | * @HW_ACC_SIAMMDSP: for SIAMMDSP | 445 | * @PRCMU_IDLE_OK: Idle went ok |
| 428 | * @HW_ACC_SIAPIPE: for SIAPIPE | 446 | * @PRCMU_DEEPIDLE_OK: DeepIdle went ok |
| 429 | * @HW_ACC_SGA: for SGA | 447 | * @PRCMU_PRCMU2ARMPENDINGIT_ER: Pending interrupt detected |
| 430 | * @HW_ACC_B2R2: for B2R2 | 448 | * @PRCMU_ARMPENDINGIT_ER: Pending interrupt detected |
| 431 | * @HW_ACC_MCDE: for MCDE | ||
| 432 | * @HW_ACC_ESRAM1: for ESRAM1 | ||
| 433 | * @HW_ACC_ESRAM2: for ESRAM2 | ||
| 434 | * @HW_ACC_ESRAM3: for ESRAM3 | ||
| 435 | * @HW_ACC_ESRAM4: for ESRAM4 | ||
| 436 | * @NUM_HW_ACC: number of hardware accelerators | ||
| 437 | * | ||
| 438 | * Different hw accelerators which can be turned ON/ | ||
| 439 | * OFF or put into retention (MMDSPs and ESRAMs). | ||
| 440 | * Used with EPOD API. | ||
| 441 | * | 449 | * |
| 442 | * NOTE! Deprecated, to be removed when all users switched over to use the | ||
| 443 | * regulator API. | ||
| 444 | */ | 450 | */ |
| 445 | enum hw_acc_dev { | 451 | enum prcmu_power_status { |
| 446 | HW_ACC_SVAMMDSP, | 452 | PRCMU_SLEEP_OK = 0xf3, |
| 447 | HW_ACC_SVAPIPE, | 453 | PRCMU_DEEP_SLEEP_OK = 0xf6, |
| 448 | HW_ACC_SIAMMDSP, | 454 | PRCMU_IDLE_OK = 0xf0, |
| 449 | HW_ACC_SIAPIPE, | 455 | PRCMU_DEEPIDLE_OK = 0xe3, |
| 450 | HW_ACC_SGA, | 456 | PRCMU_PRCMU2ARMPENDINGIT_ER = 0x91, |
| 451 | HW_ACC_B2R2, | 457 | PRCMU_ARMPENDINGIT_ER = 0x93, |
| 452 | HW_ACC_MCDE, | ||
| 453 | HW_ACC_ESRAM1, | ||
| 454 | HW_ACC_ESRAM2, | ||
| 455 | HW_ACC_ESRAM3, | ||
| 456 | HW_ACC_ESRAM4, | ||
| 457 | NUM_HW_ACC | ||
| 458 | }; | 458 | }; |
| 459 | 459 | ||
| 460 | /* | 460 | /* |
| @@ -493,6 +493,20 @@ struct prcmu_auto_pm_config { | |||
| 493 | u8 sva_policy; | 493 | u8 sva_policy; |
| 494 | }; | 494 | }; |
| 495 | 495 | ||
| 496 | #define PRCMU_FW_PROJECT_U8500 2 | ||
| 497 | #define PRCMU_FW_PROJECT_U9500 4 | ||
| 498 | #define PRCMU_FW_PROJECT_U8500_C2 7 | ||
| 499 | #define PRCMU_FW_PROJECT_U9500_C2 11 | ||
| 500 | #define PRCMU_FW_PROJECT_U8520 13 | ||
| 501 | #define PRCMU_FW_PROJECT_U8420 14 | ||
| 502 | |||
| 503 | struct prcmu_fw_version { | ||
| 504 | u8 project; | ||
| 505 | u8 api_version; | ||
| 506 | u8 func_version; | ||
| 507 | u8 errata; | ||
| 508 | }; | ||
| 509 | |||
| 496 | #ifdef CONFIG_MFD_DB8500_PRCMU | 510 | #ifdef CONFIG_MFD_DB8500_PRCMU |
| 497 | 511 | ||
| 498 | void db8500_prcmu_early_init(void); | 512 | void db8500_prcmu_early_init(void); |
| @@ -500,42 +514,41 @@ int prcmu_set_rc_a2p(enum romcode_write); | |||
| 500 | enum romcode_read prcmu_get_rc_p2a(void); | 514 | enum romcode_read prcmu_get_rc_p2a(void); |
| 501 | enum ap_pwrst prcmu_get_xp70_current_state(void); | 515 | enum ap_pwrst prcmu_get_xp70_current_state(void); |
| 502 | bool prcmu_has_arm_maxopp(void); | 516 | bool prcmu_has_arm_maxopp(void); |
| 503 | bool prcmu_is_u8400(void); | 517 | struct prcmu_fw_version *prcmu_get_fw_version(void); |
| 504 | int prcmu_set_ape_opp(u8 opp); | ||
| 505 | int prcmu_get_ape_opp(void); | ||
| 506 | int prcmu_request_ape_opp_100_voltage(bool enable); | 518 | int prcmu_request_ape_opp_100_voltage(bool enable); |
| 507 | int prcmu_release_usb_wakeup_state(void); | 519 | int prcmu_release_usb_wakeup_state(void); |
| 508 | int prcmu_set_ddr_opp(u8 opp); | ||
| 509 | int prcmu_get_ddr_opp(void); | ||
| 510 | /* NOTE! Use regulator framework instead */ | ||
| 511 | int prcmu_set_hwacc(u16 hw_acc_dev, u8 state); | ||
| 512 | void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, | 520 | void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, |
| 513 | struct prcmu_auto_pm_config *idle); | 521 | struct prcmu_auto_pm_config *idle); |
| 514 | bool prcmu_is_auto_pm_enabled(void); | 522 | bool prcmu_is_auto_pm_enabled(void); |
| 515 | 523 | ||
| 516 | int prcmu_config_clkout(u8 clkout, u8 source, u8 div); | 524 | int prcmu_config_clkout(u8 clkout, u8 source, u8 div); |
| 517 | int prcmu_set_clock_divider(u8 clock, u8 divider); | 525 | int prcmu_set_clock_divider(u8 clock, u8 divider); |
| 518 | int prcmu_config_hotdog(u8 threshold); | 526 | int db8500_prcmu_config_hotdog(u8 threshold); |
| 519 | int prcmu_config_hotmon(u8 low, u8 high); | 527 | int db8500_prcmu_config_hotmon(u8 low, u8 high); |
| 520 | int prcmu_start_temp_sense(u16 cycles32k); | 528 | int db8500_prcmu_start_temp_sense(u16 cycles32k); |
| 521 | int prcmu_stop_temp_sense(void); | 529 | int db8500_prcmu_stop_temp_sense(void); |
| 522 | int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); | 530 | int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); |
| 523 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); | 531 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); |
| 524 | 532 | ||
| 525 | void prcmu_ac_wake_req(void); | 533 | void prcmu_ac_wake_req(void); |
| 526 | void prcmu_ac_sleep_req(void); | 534 | void prcmu_ac_sleep_req(void); |
| 527 | void prcmu_modem_reset(void); | 535 | void db8500_prcmu_modem_reset(void); |
| 528 | void prcmu_enable_spi2(void); | ||
| 529 | void prcmu_disable_spi2(void); | ||
| 530 | 536 | ||
| 531 | int prcmu_config_a9wdog(u8 num, bool sleep_auto_off); | 537 | int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off); |
| 532 | int prcmu_enable_a9wdog(u8 id); | 538 | int db8500_prcmu_enable_a9wdog(u8 id); |
| 533 | int prcmu_disable_a9wdog(u8 id); | 539 | int db8500_prcmu_disable_a9wdog(u8 id); |
| 534 | int prcmu_kick_a9wdog(u8 id); | 540 | int db8500_prcmu_kick_a9wdog(u8 id); |
| 535 | int prcmu_load_a9wdog(u8 id, u32 val); | 541 | int db8500_prcmu_load_a9wdog(u8 id, u32 val); |
| 536 | 542 | ||
| 537 | void db8500_prcmu_system_reset(u16 reset_code); | 543 | void db8500_prcmu_system_reset(u16 reset_code); |
| 538 | int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); | 544 | int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); |
| 545 | u8 db8500_prcmu_get_power_state_result(void); | ||
| 546 | int db8500_prcmu_gic_decouple(void); | ||
| 547 | int db8500_prcmu_gic_recouple(void); | ||
| 548 | int db8500_prcmu_copy_gic_settings(void); | ||
| 549 | bool db8500_prcmu_gic_pending_irq(void); | ||
| 550 | bool db8500_prcmu_pending_irq(void); | ||
| 551 | bool db8500_prcmu_is_cpu_in_wfi(int cpu); | ||
| 539 | void db8500_prcmu_enable_wakeups(u32 wakeups); | 552 | void db8500_prcmu_enable_wakeups(u32 wakeups); |
| 540 | int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state); | 553 | int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state); |
| 541 | int db8500_prcmu_request_clock(u8 clock, bool enable); | 554 | int db8500_prcmu_request_clock(u8 clock, bool enable); |
| @@ -549,6 +562,14 @@ u16 db8500_prcmu_get_reset_code(void); | |||
| 549 | bool db8500_prcmu_is_ac_wake_requested(void); | 562 | bool db8500_prcmu_is_ac_wake_requested(void); |
| 550 | int db8500_prcmu_set_arm_opp(u8 opp); | 563 | int db8500_prcmu_set_arm_opp(u8 opp); |
| 551 | int db8500_prcmu_get_arm_opp(void); | 564 | int db8500_prcmu_get_arm_opp(void); |
| 565 | int db8500_prcmu_set_ape_opp(u8 opp); | ||
| 566 | int db8500_prcmu_get_ape_opp(void); | ||
| 567 | int db8500_prcmu_set_ddr_opp(u8 opp); | ||
| 568 | int db8500_prcmu_get_ddr_opp(void); | ||
| 569 | |||
| 570 | u32 db8500_prcmu_read(unsigned int reg); | ||
| 571 | void db8500_prcmu_write(unsigned int reg, u32 value); | ||
| 572 | void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value); | ||
| 552 | 573 | ||
| 553 | #else /* !CONFIG_MFD_DB8500_PRCMU */ | 574 | #else /* !CONFIG_MFD_DB8500_PRCMU */ |
| 554 | 575 | ||
| @@ -574,17 +595,17 @@ static inline bool prcmu_has_arm_maxopp(void) | |||
| 574 | return false; | 595 | return false; |
| 575 | } | 596 | } |
| 576 | 597 | ||
| 577 | static inline bool prcmu_is_u8400(void) | 598 | static inline struct prcmu_fw_version *prcmu_get_fw_version(void) |
| 578 | { | 599 | { |
| 579 | return false; | 600 | return NULL; |
| 580 | } | 601 | } |
| 581 | 602 | ||
| 582 | static inline int prcmu_set_ape_opp(u8 opp) | 603 | static inline int db8500_prcmu_set_ape_opp(u8 opp) |
| 583 | { | 604 | { |
| 584 | return 0; | 605 | return 0; |
| 585 | } | 606 | } |
| 586 | 607 | ||
| 587 | static inline int prcmu_get_ape_opp(void) | 608 | static inline int db8500_prcmu_get_ape_opp(void) |
| 588 | { | 609 | { |
| 589 | return APE_100_OPP; | 610 | return APE_100_OPP; |
| 590 | } | 611 | } |
| @@ -599,21 +620,16 @@ static inline int prcmu_release_usb_wakeup_state(void) | |||
| 599 | return 0; | 620 | return 0; |
| 600 | } | 621 | } |
| 601 | 622 | ||
| 602 | static inline int prcmu_set_ddr_opp(u8 opp) | 623 | static inline int db8500_prcmu_set_ddr_opp(u8 opp) |
| 603 | { | 624 | { |
| 604 | return 0; | 625 | return 0; |
| 605 | } | 626 | } |
| 606 | 627 | ||
| 607 | static inline int prcmu_get_ddr_opp(void) | 628 | static inline int db8500_prcmu_get_ddr_opp(void) |
| 608 | { | 629 | { |
| 609 | return DDR_100_OPP; | 630 | return DDR_100_OPP; |
| 610 | } | 631 | } |
| 611 | 632 | ||
| 612 | static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state) | ||
| 613 | { | ||
| 614 | return 0; | ||
| 615 | } | ||
| 616 | |||
| 617 | static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, | 633 | static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, |
| 618 | struct prcmu_auto_pm_config *idle) | 634 | struct prcmu_auto_pm_config *idle) |
| 619 | { | 635 | { |
| @@ -634,22 +650,22 @@ static inline int prcmu_set_clock_divider(u8 clock, u8 divider) | |||
| 634 | return 0; | 650 | return 0; |
| 635 | } | 651 | } |
| 636 | 652 | ||
| 637 | static inline int prcmu_config_hotdog(u8 threshold) | 653 | static inline int db8500_prcmu_config_hotdog(u8 threshold) |
| 638 | { | 654 | { |
| 639 | return 0; | 655 | return 0; |
| 640 | } | 656 | } |
| 641 | 657 | ||
| 642 | static inline int prcmu_config_hotmon(u8 low, u8 high) | 658 | static inline int db8500_prcmu_config_hotmon(u8 low, u8 high) |
| 643 | { | 659 | { |
| 644 | return 0; | 660 | return 0; |
| 645 | } | 661 | } |
| 646 | 662 | ||
| 647 | static inline int prcmu_start_temp_sense(u16 cycles32k) | 663 | static inline int db8500_prcmu_start_temp_sense(u16 cycles32k) |
| 648 | { | 664 | { |
| 649 | return 0; | 665 | return 0; |
| 650 | } | 666 | } |
| 651 | 667 | ||
| 652 | static inline int prcmu_stop_temp_sense(void) | 668 | static inline int db8500_prcmu_stop_temp_sense(void) |
| 653 | { | 669 | { |
| 654 | return 0; | 670 | return 0; |
| 655 | } | 671 | } |
| @@ -668,22 +684,17 @@ static inline void prcmu_ac_wake_req(void) {} | |||
| 668 | 684 | ||
| 669 | static inline void prcmu_ac_sleep_req(void) {} | 685 | static inline void prcmu_ac_sleep_req(void) {} |
| 670 | 686 | ||
| 671 | static inline void prcmu_modem_reset(void) {} | 687 | static inline void db8500_prcmu_modem_reset(void) {} |
| 672 | 688 | ||
| 673 | static inline int prcmu_enable_spi2(void) | 689 | static inline void db8500_prcmu_system_reset(u16 reset_code) {} |
| 674 | { | ||
| 675 | return 0; | ||
| 676 | } | ||
| 677 | 690 | ||
| 678 | static inline int prcmu_disable_spi2(void) | 691 | static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, |
| 692 | bool keep_ap_pll) | ||
| 679 | { | 693 | { |
| 680 | return 0; | 694 | return 0; |
| 681 | } | 695 | } |
| 682 | 696 | ||
| 683 | static inline void db8500_prcmu_system_reset(u16 reset_code) {} | 697 | static inline u8 db8500_prcmu_get_power_state_result(void) |
| 684 | |||
| 685 | static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, | ||
| 686 | bool keep_ap_pll) | ||
| 687 | { | 698 | { |
| 688 | return 0; | 699 | return 0; |
| 689 | } | 700 | } |
| @@ -729,27 +740,27 @@ static inline u16 db8500_prcmu_get_reset_code(void) | |||
| 729 | return 0; | 740 | return 0; |
| 730 | } | 741 | } |
| 731 | 742 | ||
| 732 | static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | 743 | static inline int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) |
| 733 | { | 744 | { |
| 734 | return 0; | 745 | return 0; |
| 735 | } | 746 | } |
| 736 | 747 | ||
| 737 | static inline int prcmu_enable_a9wdog(u8 id) | 748 | static inline int db8500_prcmu_enable_a9wdog(u8 id) |
| 738 | { | 749 | { |
| 739 | return 0; | 750 | return 0; |
| 740 | } | 751 | } |
| 741 | 752 | ||
| 742 | static inline int prcmu_disable_a9wdog(u8 id) | 753 | static inline int db8500_prcmu_disable_a9wdog(u8 id) |
| 743 | { | 754 | { |
| 744 | return 0; | 755 | return 0; |
| 745 | } | 756 | } |
| 746 | 757 | ||
| 747 | static inline int prcmu_kick_a9wdog(u8 id) | 758 | static inline int db8500_prcmu_kick_a9wdog(u8 id) |
| 748 | { | 759 | { |
| 749 | return 0; | 760 | return 0; |
| 750 | } | 761 | } |
| 751 | 762 | ||
| 752 | static inline int prcmu_load_a9wdog(u8 id, u32 val) | 763 | static inline int db8500_prcmu_load_a9wdog(u8 id, u32 val) |
| 753 | { | 764 | { |
| 754 | return 0; | 765 | return 0; |
| 755 | } | 766 | } |
| @@ -769,6 +780,16 @@ static inline int db8500_prcmu_get_arm_opp(void) | |||
| 769 | return 0; | 780 | return 0; |
| 770 | } | 781 | } |
| 771 | 782 | ||
| 783 | static inline u32 db8500_prcmu_read(unsigned int reg) | ||
| 784 | { | ||
| 785 | return 0; | ||
| 786 | } | ||
| 787 | |||
| 788 | static inline void db8500_prcmu_write(unsigned int reg, u32 value) {} | ||
| 789 | |||
| 790 | static inline void db8500_prcmu_write_masked(unsigned int reg, u32 mask, | ||
| 791 | u32 value) {} | ||
| 792 | |||
| 772 | #endif /* !CONFIG_MFD_DB8500_PRCMU */ | 793 | #endif /* !CONFIG_MFD_DB8500_PRCMU */ |
| 773 | 794 | ||
| 774 | #endif /* __MFD_DB8500_PRCMU_H */ | 795 | #endif /* __MFD_DB8500_PRCMU_H */ |
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index bac942f959c1..d7674eb7305f 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 12 | #include <linux/notifier.h> | 12 | #include <linux/notifier.h> |
| 13 | #include <asm/mach-types.h> | 13 | #include <linux/err.h> |
| 14 | 14 | ||
| 15 | /* PRCMU Wakeup defines */ | 15 | /* PRCMU Wakeup defines */ |
| 16 | enum prcmu_wakeup_index { | 16 | enum prcmu_wakeup_index { |
| @@ -80,6 +80,29 @@ enum prcmu_wakeup_index { | |||
| 80 | #define EPOD_STATE_ON_CLK_OFF 0x03 | 80 | #define EPOD_STATE_ON_CLK_OFF 0x03 |
| 81 | #define EPOD_STATE_ON 0x04 | 81 | #define EPOD_STATE_ON 0x04 |
| 82 | 82 | ||
| 83 | /* DB5500 CLKOUT IDs */ | ||
| 84 | enum { | ||
| 85 | DB5500_CLKOUT0 = 0, | ||
| 86 | DB5500_CLKOUT1, | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* DB5500 CLKOUTx sources */ | ||
| 90 | enum { | ||
| 91 | DB5500_CLKOUT_REF_CLK_SEL0, | ||
| 92 | DB5500_CLKOUT_RTC_CLK0_SEL0, | ||
| 93 | DB5500_CLKOUT_ULP_CLK_SEL0, | ||
| 94 | DB5500_CLKOUT_STATIC0, | ||
| 95 | DB5500_CLKOUT_REFCLK, | ||
| 96 | DB5500_CLKOUT_ULPCLK, | ||
| 97 | DB5500_CLKOUT_ARMCLK, | ||
| 98 | DB5500_CLKOUT_SYSACC0CLK, | ||
| 99 | DB5500_CLKOUT_SOC0PLLCLK, | ||
| 100 | DB5500_CLKOUT_SOC1PLLCLK, | ||
| 101 | DB5500_CLKOUT_DDRPLLCLK, | ||
| 102 | DB5500_CLKOUT_TVCLK, | ||
| 103 | DB5500_CLKOUT_IRDACLK, | ||
| 104 | }; | ||
| 105 | |||
| 83 | /* | 106 | /* |
| 84 | * CLKOUT sources | 107 | * CLKOUT sources |
| 85 | */ | 108 | */ |
| @@ -111,6 +134,7 @@ enum prcmu_clock { | |||
| 111 | PRCMU_MSP1CLK, | 134 | PRCMU_MSP1CLK, |
| 112 | PRCMU_I2CCLK, | 135 | PRCMU_I2CCLK, |
| 113 | PRCMU_SDMMCCLK, | 136 | PRCMU_SDMMCCLK, |
| 137 | PRCMU_SPARE1CLK, | ||
| 114 | PRCMU_SLIMCLK, | 138 | PRCMU_SLIMCLK, |
| 115 | PRCMU_PER1CLK, | 139 | PRCMU_PER1CLK, |
| 116 | PRCMU_PER2CLK, | 140 | PRCMU_PER2CLK, |
| @@ -139,12 +163,20 @@ enum prcmu_clock { | |||
| 139 | PRCMU_IRRCCLK, | 163 | PRCMU_IRRCCLK, |
| 140 | PRCMU_SIACLK, | 164 | PRCMU_SIACLK, |
| 141 | PRCMU_SVACLK, | 165 | PRCMU_SVACLK, |
| 166 | PRCMU_ACLK, | ||
| 142 | PRCMU_NUM_REG_CLOCKS, | 167 | PRCMU_NUM_REG_CLOCKS, |
| 143 | PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS, | 168 | PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS, |
| 169 | PRCMU_CDCLK, | ||
| 144 | PRCMU_TIMCLK, | 170 | PRCMU_TIMCLK, |
| 145 | PRCMU_PLLSOC0, | 171 | PRCMU_PLLSOC0, |
| 146 | PRCMU_PLLSOC1, | 172 | PRCMU_PLLSOC1, |
| 147 | PRCMU_PLLDDR, | 173 | PRCMU_PLLDDR, |
| 174 | PRCMU_PLLDSI, | ||
| 175 | PRCMU_DSI0CLK, | ||
| 176 | PRCMU_DSI1CLK, | ||
| 177 | PRCMU_DSI0ESCCLK, | ||
| 178 | PRCMU_DSI1ESCCLK, | ||
| 179 | PRCMU_DSI2ESCCLK, | ||
| 148 | }; | 180 | }; |
| 149 | 181 | ||
| 150 | /** | 182 | /** |
| @@ -153,12 +185,14 @@ enum prcmu_clock { | |||
| 153 | * @APE_NO_CHANGE: The APE operating point is unchanged | 185 | * @APE_NO_CHANGE: The APE operating point is unchanged |
| 154 | * @APE_100_OPP: The new APE operating point is ape100opp | 186 | * @APE_100_OPP: The new APE operating point is ape100opp |
| 155 | * @APE_50_OPP: 50% | 187 | * @APE_50_OPP: 50% |
| 188 | * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%. | ||
| 156 | */ | 189 | */ |
| 157 | enum ape_opp { | 190 | enum ape_opp { |
| 158 | APE_OPP_INIT = 0x00, | 191 | APE_OPP_INIT = 0x00, |
| 159 | APE_NO_CHANGE = 0x01, | 192 | APE_NO_CHANGE = 0x01, |
| 160 | APE_100_OPP = 0x02, | 193 | APE_100_OPP = 0x02, |
| 161 | APE_50_OPP = 0x03 | 194 | APE_50_OPP = 0x03, |
| 195 | APE_50_PARTLY_25_OPP = 0xFF, | ||
| 162 | }; | 196 | }; |
| 163 | 197 | ||
| 164 | /** | 198 | /** |
| @@ -218,9 +252,11 @@ enum ddr_pwrst { | |||
| 218 | 252 | ||
| 219 | #if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500) | 253 | #if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500) |
| 220 | 254 | ||
| 255 | #include <mach/id.h> | ||
| 256 | |||
| 221 | static inline void __init prcmu_early_init(void) | 257 | static inline void __init prcmu_early_init(void) |
| 222 | { | 258 | { |
| 223 | if (machine_is_u5500()) | 259 | if (cpu_is_u5500()) |
| 224 | return db5500_prcmu_early_init(); | 260 | return db5500_prcmu_early_init(); |
| 225 | else | 261 | else |
| 226 | return db8500_prcmu_early_init(); | 262 | return db8500_prcmu_early_init(); |
| @@ -229,7 +265,7 @@ static inline void __init prcmu_early_init(void) | |||
| 229 | static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, | 265 | static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, |
| 230 | bool keep_ap_pll) | 266 | bool keep_ap_pll) |
| 231 | { | 267 | { |
| 232 | if (machine_is_u5500()) | 268 | if (cpu_is_u5500()) |
| 233 | return db5500_prcmu_set_power_state(state, keep_ulp_clk, | 269 | return db5500_prcmu_set_power_state(state, keep_ulp_clk, |
| 234 | keep_ap_pll); | 270 | keep_ap_pll); |
| 235 | else | 271 | else |
| @@ -237,9 +273,65 @@ static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, | |||
| 237 | keep_ap_pll); | 273 | keep_ap_pll); |
| 238 | } | 274 | } |
| 239 | 275 | ||
| 276 | static inline u8 prcmu_get_power_state_result(void) | ||
| 277 | { | ||
| 278 | if (cpu_is_u5500()) | ||
| 279 | return -EINVAL; | ||
| 280 | else | ||
| 281 | return db8500_prcmu_get_power_state_result(); | ||
| 282 | } | ||
| 283 | |||
| 284 | static inline int prcmu_gic_decouple(void) | ||
| 285 | { | ||
| 286 | if (cpu_is_u5500()) | ||
| 287 | return -EINVAL; | ||
| 288 | else | ||
| 289 | return db8500_prcmu_gic_decouple(); | ||
| 290 | } | ||
| 291 | |||
| 292 | static inline int prcmu_gic_recouple(void) | ||
| 293 | { | ||
| 294 | if (cpu_is_u5500()) | ||
| 295 | return -EINVAL; | ||
| 296 | else | ||
| 297 | return db8500_prcmu_gic_recouple(); | ||
| 298 | } | ||
| 299 | |||
| 300 | static inline bool prcmu_gic_pending_irq(void) | ||
| 301 | { | ||
| 302 | if (cpu_is_u5500()) | ||
| 303 | return -EINVAL; | ||
| 304 | else | ||
| 305 | return db8500_prcmu_gic_pending_irq(); | ||
| 306 | } | ||
| 307 | |||
| 308 | static inline bool prcmu_is_cpu_in_wfi(int cpu) | ||
| 309 | { | ||
| 310 | if (cpu_is_u5500()) | ||
| 311 | return -EINVAL; | ||
| 312 | else | ||
| 313 | return db8500_prcmu_is_cpu_in_wfi(cpu); | ||
| 314 | } | ||
| 315 | |||
| 316 | static inline int prcmu_copy_gic_settings(void) | ||
| 317 | { | ||
| 318 | if (cpu_is_u5500()) | ||
| 319 | return -EINVAL; | ||
| 320 | else | ||
| 321 | return db8500_prcmu_copy_gic_settings(); | ||
| 322 | } | ||
| 323 | |||
| 324 | static inline bool prcmu_pending_irq(void) | ||
| 325 | { | ||
| 326 | if (cpu_is_u5500()) | ||
| 327 | return -EINVAL; | ||
| 328 | else | ||
| 329 | return db8500_prcmu_pending_irq(); | ||
| 330 | } | ||
| 331 | |||
| 240 | static inline int prcmu_set_epod(u16 epod_id, u8 epod_state) | 332 | static inline int prcmu_set_epod(u16 epod_id, u8 epod_state) |
| 241 | { | 333 | { |
| 242 | if (machine_is_u5500()) | 334 | if (cpu_is_u5500()) |
| 243 | return -EINVAL; | 335 | return -EINVAL; |
| 244 | else | 336 | else |
| 245 | return db8500_prcmu_set_epod(epod_id, epod_state); | 337 | return db8500_prcmu_set_epod(epod_id, epod_state); |
| @@ -247,7 +339,7 @@ static inline int prcmu_set_epod(u16 epod_id, u8 epod_state) | |||
| 247 | 339 | ||
| 248 | static inline void prcmu_enable_wakeups(u32 wakeups) | 340 | static inline void prcmu_enable_wakeups(u32 wakeups) |
| 249 | { | 341 | { |
| 250 | if (machine_is_u5500()) | 342 | if (cpu_is_u5500()) |
| 251 | db5500_prcmu_enable_wakeups(wakeups); | 343 | db5500_prcmu_enable_wakeups(wakeups); |
| 252 | else | 344 | else |
| 253 | db8500_prcmu_enable_wakeups(wakeups); | 345 | db8500_prcmu_enable_wakeups(wakeups); |
| @@ -260,7 +352,7 @@ static inline void prcmu_disable_wakeups(void) | |||
| 260 | 352 | ||
| 261 | static inline void prcmu_config_abb_event_readout(u32 abb_events) | 353 | static inline void prcmu_config_abb_event_readout(u32 abb_events) |
| 262 | { | 354 | { |
| 263 | if (machine_is_u5500()) | 355 | if (cpu_is_u5500()) |
| 264 | db5500_prcmu_config_abb_event_readout(abb_events); | 356 | db5500_prcmu_config_abb_event_readout(abb_events); |
| 265 | else | 357 | else |
| 266 | db8500_prcmu_config_abb_event_readout(abb_events); | 358 | db8500_prcmu_config_abb_event_readout(abb_events); |
| @@ -268,7 +360,7 @@ static inline void prcmu_config_abb_event_readout(u32 abb_events) | |||
| 268 | 360 | ||
| 269 | static inline void prcmu_get_abb_event_buffer(void __iomem **buf) | 361 | static inline void prcmu_get_abb_event_buffer(void __iomem **buf) |
| 270 | { | 362 | { |
| 271 | if (machine_is_u5500()) | 363 | if (cpu_is_u5500()) |
| 272 | db5500_prcmu_get_abb_event_buffer(buf); | 364 | db5500_prcmu_get_abb_event_buffer(buf); |
| 273 | else | 365 | else |
| 274 | db8500_prcmu_get_abb_event_buffer(buf); | 366 | db8500_prcmu_get_abb_event_buffer(buf); |
| @@ -276,25 +368,40 @@ static inline void prcmu_get_abb_event_buffer(void __iomem **buf) | |||
| 276 | 368 | ||
| 277 | int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); | 369 | int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); |
| 278 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); | 370 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); |
| 371 | int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size); | ||
| 279 | 372 | ||
| 280 | int prcmu_config_clkout(u8 clkout, u8 source, u8 div); | 373 | int prcmu_config_clkout(u8 clkout, u8 source, u8 div); |
| 281 | 374 | ||
| 282 | static inline int prcmu_request_clock(u8 clock, bool enable) | 375 | static inline int prcmu_request_clock(u8 clock, bool enable) |
| 283 | { | 376 | { |
| 284 | if (machine_is_u5500()) | 377 | if (cpu_is_u5500()) |
| 285 | return db5500_prcmu_request_clock(clock, enable); | 378 | return db5500_prcmu_request_clock(clock, enable); |
| 286 | else | 379 | else |
| 287 | return db8500_prcmu_request_clock(clock, enable); | 380 | return db8500_prcmu_request_clock(clock, enable); |
| 288 | } | 381 | } |
| 289 | 382 | ||
| 290 | int prcmu_set_ape_opp(u8 opp); | 383 | unsigned long prcmu_clock_rate(u8 clock); |
| 291 | int prcmu_get_ape_opp(void); | 384 | long prcmu_round_clock_rate(u8 clock, unsigned long rate); |
| 292 | int prcmu_set_ddr_opp(u8 opp); | 385 | int prcmu_set_clock_rate(u8 clock, unsigned long rate); |
| 293 | int prcmu_get_ddr_opp(void); | 386 | |
| 387 | static inline int prcmu_set_ddr_opp(u8 opp) | ||
| 388 | { | ||
| 389 | if (cpu_is_u5500()) | ||
| 390 | return -EINVAL; | ||
| 391 | else | ||
| 392 | return db8500_prcmu_set_ddr_opp(opp); | ||
| 393 | } | ||
| 394 | static inline int prcmu_get_ddr_opp(void) | ||
| 395 | { | ||
| 396 | if (cpu_is_u5500()) | ||
| 397 | return -EINVAL; | ||
| 398 | else | ||
| 399 | return db8500_prcmu_get_ddr_opp(); | ||
| 400 | } | ||
| 294 | 401 | ||
| 295 | static inline int prcmu_set_arm_opp(u8 opp) | 402 | static inline int prcmu_set_arm_opp(u8 opp) |
| 296 | { | 403 | { |
| 297 | if (machine_is_u5500()) | 404 | if (cpu_is_u5500()) |
| 298 | return -EINVAL; | 405 | return -EINVAL; |
| 299 | else | 406 | else |
| 300 | return db8500_prcmu_set_arm_opp(opp); | 407 | return db8500_prcmu_set_arm_opp(opp); |
| @@ -302,15 +409,31 @@ static inline int prcmu_set_arm_opp(u8 opp) | |||
| 302 | 409 | ||
| 303 | static inline int prcmu_get_arm_opp(void) | 410 | static inline int prcmu_get_arm_opp(void) |
| 304 | { | 411 | { |
| 305 | if (machine_is_u5500()) | 412 | if (cpu_is_u5500()) |
| 306 | return -EINVAL; | 413 | return -EINVAL; |
| 307 | else | 414 | else |
| 308 | return db8500_prcmu_get_arm_opp(); | 415 | return db8500_prcmu_get_arm_opp(); |
| 309 | } | 416 | } |
| 310 | 417 | ||
| 418 | static inline int prcmu_set_ape_opp(u8 opp) | ||
| 419 | { | ||
| 420 | if (cpu_is_u5500()) | ||
| 421 | return -EINVAL; | ||
| 422 | else | ||
| 423 | return db8500_prcmu_set_ape_opp(opp); | ||
| 424 | } | ||
| 425 | |||
| 426 | static inline int prcmu_get_ape_opp(void) | ||
| 427 | { | ||
| 428 | if (cpu_is_u5500()) | ||
| 429 | return -EINVAL; | ||
| 430 | else | ||
| 431 | return db8500_prcmu_get_ape_opp(); | ||
| 432 | } | ||
| 433 | |||
| 311 | static inline void prcmu_system_reset(u16 reset_code) | 434 | static inline void prcmu_system_reset(u16 reset_code) |
| 312 | { | 435 | { |
| 313 | if (machine_is_u5500()) | 436 | if (cpu_is_u5500()) |
| 314 | return db5500_prcmu_system_reset(reset_code); | 437 | return db5500_prcmu_system_reset(reset_code); |
| 315 | else | 438 | else |
| 316 | return db8500_prcmu_system_reset(reset_code); | 439 | return db8500_prcmu_system_reset(reset_code); |
| @@ -318,7 +441,7 @@ static inline void prcmu_system_reset(u16 reset_code) | |||
| 318 | 441 | ||
| 319 | static inline u16 prcmu_get_reset_code(void) | 442 | static inline u16 prcmu_get_reset_code(void) |
| 320 | { | 443 | { |
| 321 | if (machine_is_u5500()) | 444 | if (cpu_is_u5500()) |
| 322 | return db5500_prcmu_get_reset_code(); | 445 | return db5500_prcmu_get_reset_code(); |
| 323 | else | 446 | else |
| 324 | return db8500_prcmu_get_reset_code(); | 447 | return db8500_prcmu_get_reset_code(); |
| @@ -326,10 +449,17 @@ static inline u16 prcmu_get_reset_code(void) | |||
| 326 | 449 | ||
| 327 | void prcmu_ac_wake_req(void); | 450 | void prcmu_ac_wake_req(void); |
| 328 | void prcmu_ac_sleep_req(void); | 451 | void prcmu_ac_sleep_req(void); |
| 329 | void prcmu_modem_reset(void); | 452 | static inline void prcmu_modem_reset(void) |
| 453 | { | ||
| 454 | if (cpu_is_u5500()) | ||
| 455 | return; | ||
| 456 | else | ||
| 457 | return db8500_prcmu_modem_reset(); | ||
| 458 | } | ||
| 459 | |||
| 330 | static inline bool prcmu_is_ac_wake_requested(void) | 460 | static inline bool prcmu_is_ac_wake_requested(void) |
| 331 | { | 461 | { |
| 332 | if (machine_is_u5500()) | 462 | if (cpu_is_u5500()) |
| 333 | return db5500_prcmu_is_ac_wake_requested(); | 463 | return db5500_prcmu_is_ac_wake_requested(); |
| 334 | else | 464 | else |
| 335 | return db8500_prcmu_is_ac_wake_requested(); | 465 | return db8500_prcmu_is_ac_wake_requested(); |
| @@ -337,7 +467,7 @@ static inline bool prcmu_is_ac_wake_requested(void) | |||
| 337 | 467 | ||
| 338 | static inline int prcmu_set_display_clocks(void) | 468 | static inline int prcmu_set_display_clocks(void) |
| 339 | { | 469 | { |
| 340 | if (machine_is_u5500()) | 470 | if (cpu_is_u5500()) |
| 341 | return db5500_prcmu_set_display_clocks(); | 471 | return db5500_prcmu_set_display_clocks(); |
| 342 | else | 472 | else |
| 343 | return db8500_prcmu_set_display_clocks(); | 473 | return db8500_prcmu_set_display_clocks(); |
| @@ -345,7 +475,7 @@ static inline int prcmu_set_display_clocks(void) | |||
| 345 | 475 | ||
| 346 | static inline int prcmu_disable_dsipll(void) | 476 | static inline int prcmu_disable_dsipll(void) |
| 347 | { | 477 | { |
| 348 | if (machine_is_u5500()) | 478 | if (cpu_is_u5500()) |
| 349 | return db5500_prcmu_disable_dsipll(); | 479 | return db5500_prcmu_disable_dsipll(); |
| 350 | else | 480 | else |
| 351 | return db8500_prcmu_disable_dsipll(); | 481 | return db8500_prcmu_disable_dsipll(); |
| @@ -353,7 +483,7 @@ static inline int prcmu_disable_dsipll(void) | |||
| 353 | 483 | ||
| 354 | static inline int prcmu_enable_dsipll(void) | 484 | static inline int prcmu_enable_dsipll(void) |
| 355 | { | 485 | { |
| 356 | if (machine_is_u5500()) | 486 | if (cpu_is_u5500()) |
| 357 | return db5500_prcmu_enable_dsipll(); | 487 | return db5500_prcmu_enable_dsipll(); |
| 358 | else | 488 | else |
| 359 | return db8500_prcmu_enable_dsipll(); | 489 | return db8500_prcmu_enable_dsipll(); |
| @@ -361,11 +491,107 @@ static inline int prcmu_enable_dsipll(void) | |||
| 361 | 491 | ||
| 362 | static inline int prcmu_config_esram0_deep_sleep(u8 state) | 492 | static inline int prcmu_config_esram0_deep_sleep(u8 state) |
| 363 | { | 493 | { |
| 364 | if (machine_is_u5500()) | 494 | if (cpu_is_u5500()) |
| 365 | return -EINVAL; | 495 | return -EINVAL; |
| 366 | else | 496 | else |
| 367 | return db8500_prcmu_config_esram0_deep_sleep(state); | 497 | return db8500_prcmu_config_esram0_deep_sleep(state); |
| 368 | } | 498 | } |
| 499 | |||
| 500 | static inline int prcmu_config_hotdog(u8 threshold) | ||
| 501 | { | ||
| 502 | if (cpu_is_u5500()) | ||
| 503 | return -EINVAL; | ||
| 504 | else | ||
| 505 | return db8500_prcmu_config_hotdog(threshold); | ||
| 506 | } | ||
| 507 | |||
| 508 | static inline int prcmu_config_hotmon(u8 low, u8 high) | ||
| 509 | { | ||
| 510 | if (cpu_is_u5500()) | ||
| 511 | return -EINVAL; | ||
| 512 | else | ||
| 513 | return db8500_prcmu_config_hotmon(low, high); | ||
| 514 | } | ||
| 515 | |||
| 516 | static inline int prcmu_start_temp_sense(u16 cycles32k) | ||
| 517 | { | ||
| 518 | if (cpu_is_u5500()) | ||
| 519 | return -EINVAL; | ||
| 520 | else | ||
| 521 | return db8500_prcmu_start_temp_sense(cycles32k); | ||
| 522 | } | ||
| 523 | |||
| 524 | static inline int prcmu_stop_temp_sense(void) | ||
| 525 | { | ||
| 526 | if (cpu_is_u5500()) | ||
| 527 | return -EINVAL; | ||
| 528 | else | ||
| 529 | return db8500_prcmu_stop_temp_sense(); | ||
| 530 | } | ||
| 531 | |||
| 532 | static inline u32 prcmu_read(unsigned int reg) | ||
| 533 | { | ||
| 534 | if (cpu_is_u5500()) | ||
| 535 | return -EINVAL; | ||
| 536 | else | ||
| 537 | return db8500_prcmu_read(reg); | ||
| 538 | } | ||
| 539 | |||
| 540 | static inline void prcmu_write(unsigned int reg, u32 value) | ||
| 541 | { | ||
| 542 | if (cpu_is_u5500()) | ||
| 543 | return; | ||
| 544 | else | ||
| 545 | db8500_prcmu_write(reg, value); | ||
| 546 | } | ||
| 547 | |||
| 548 | static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) | ||
| 549 | { | ||
| 550 | if (cpu_is_u5500()) | ||
| 551 | return; | ||
| 552 | else | ||
| 553 | db8500_prcmu_write_masked(reg, mask, value); | ||
| 554 | } | ||
| 555 | |||
| 556 | static inline int prcmu_enable_a9wdog(u8 id) | ||
| 557 | { | ||
| 558 | if (cpu_is_u5500()) | ||
| 559 | return -EINVAL; | ||
| 560 | else | ||
| 561 | return db8500_prcmu_enable_a9wdog(id); | ||
| 562 | } | ||
| 563 | |||
| 564 | static inline int prcmu_disable_a9wdog(u8 id) | ||
| 565 | { | ||
| 566 | if (cpu_is_u5500()) | ||
| 567 | return -EINVAL; | ||
| 568 | else | ||
| 569 | return db8500_prcmu_disable_a9wdog(id); | ||
| 570 | } | ||
| 571 | |||
| 572 | static inline int prcmu_kick_a9wdog(u8 id) | ||
| 573 | { | ||
| 574 | if (cpu_is_u5500()) | ||
| 575 | return -EINVAL; | ||
| 576 | else | ||
| 577 | return db8500_prcmu_kick_a9wdog(id); | ||
| 578 | } | ||
| 579 | |||
| 580 | static inline int prcmu_load_a9wdog(u8 id, u32 timeout) | ||
| 581 | { | ||
| 582 | if (cpu_is_u5500()) | ||
| 583 | return -EINVAL; | ||
| 584 | else | ||
| 585 | return db8500_prcmu_load_a9wdog(id, timeout); | ||
| 586 | } | ||
| 587 | |||
| 588 | static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | ||
| 589 | { | ||
| 590 | if (cpu_is_u5500()) | ||
| 591 | return -EINVAL; | ||
| 592 | else | ||
| 593 | return db8500_prcmu_config_a9wdog(num, sleep_auto_off); | ||
| 594 | } | ||
| 369 | #else | 595 | #else |
| 370 | 596 | ||
| 371 | static inline void __init prcmu_early_init(void) {} | 597 | static inline void __init prcmu_early_init(void) {} |
| @@ -395,6 +621,12 @@ static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
| 395 | return -ENOSYS; | 621 | return -ENOSYS; |
| 396 | } | 622 | } |
| 397 | 623 | ||
| 624 | static inline int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, | ||
| 625 | u8 size) | ||
| 626 | { | ||
| 627 | return -ENOSYS; | ||
| 628 | } | ||
| 629 | |||
| 398 | static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div) | 630 | static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div) |
| 399 | { | 631 | { |
| 400 | return 0; | 632 | return 0; |
| @@ -405,6 +637,21 @@ static inline int prcmu_request_clock(u8 clock, bool enable) | |||
| 405 | return 0; | 637 | return 0; |
| 406 | } | 638 | } |
| 407 | 639 | ||
| 640 | static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate) | ||
| 641 | { | ||
| 642 | return 0; | ||
| 643 | } | ||
| 644 | |||
| 645 | static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate) | ||
| 646 | { | ||
| 647 | return 0; | ||
| 648 | } | ||
| 649 | |||
| 650 | static inline unsigned long prcmu_clock_rate(u8 clock) | ||
| 651 | { | ||
| 652 | return 0; | ||
| 653 | } | ||
| 654 | |||
| 408 | static inline int prcmu_set_ape_opp(u8 opp) | 655 | static inline int prcmu_set_ape_opp(u8 opp) |
| 409 | { | 656 | { |
| 410 | return 0; | 657 | return 0; |
| @@ -480,14 +727,133 @@ static inline void prcmu_get_abb_event_buffer(void __iomem **buf) | |||
| 480 | *buf = NULL; | 727 | *buf = NULL; |
| 481 | } | 728 | } |
| 482 | 729 | ||
| 730 | static inline int prcmu_config_hotdog(u8 threshold) | ||
| 731 | { | ||
| 732 | return 0; | ||
| 733 | } | ||
| 734 | |||
| 735 | static inline int prcmu_config_hotmon(u8 low, u8 high) | ||
| 736 | { | ||
| 737 | return 0; | ||
| 738 | } | ||
| 739 | |||
| 740 | static inline int prcmu_start_temp_sense(u16 cycles32k) | ||
| 741 | { | ||
| 742 | return 0; | ||
| 743 | } | ||
| 744 | |||
| 745 | static inline int prcmu_stop_temp_sense(void) | ||
| 746 | { | ||
| 747 | return 0; | ||
| 748 | } | ||
| 749 | |||
| 750 | static inline u32 prcmu_read(unsigned int reg) | ||
| 751 | { | ||
| 752 | return 0; | ||
| 753 | } | ||
| 754 | |||
| 755 | static inline void prcmu_write(unsigned int reg, u32 value) {} | ||
| 756 | |||
| 757 | static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} | ||
| 758 | |||
| 759 | #endif | ||
| 760 | |||
| 761 | static inline void prcmu_set(unsigned int reg, u32 bits) | ||
| 762 | { | ||
| 763 | prcmu_write_masked(reg, bits, bits); | ||
| 764 | } | ||
| 765 | |||
| 766 | static inline void prcmu_clear(unsigned int reg, u32 bits) | ||
| 767 | { | ||
| 768 | prcmu_write_masked(reg, bits, 0); | ||
| 769 | } | ||
| 770 | |||
| 771 | #if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500) | ||
| 772 | |||
| 773 | /** | ||
| 774 | * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. | ||
| 775 | */ | ||
| 776 | static inline void prcmu_enable_spi2(void) | ||
| 777 | { | ||
| 778 | if (cpu_is_u8500()) | ||
| 779 | prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); | ||
| 780 | } | ||
| 781 | |||
| 782 | /** | ||
| 783 | * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. | ||
| 784 | */ | ||
| 785 | static inline void prcmu_disable_spi2(void) | ||
| 786 | { | ||
| 787 | if (cpu_is_u8500()) | ||
| 788 | prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT); | ||
| 789 | } | ||
| 790 | |||
| 791 | /** | ||
| 792 | * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD | ||
| 793 | * and UARTMOD on OtherAlternateC3. | ||
| 794 | */ | ||
| 795 | static inline void prcmu_enable_stm_mod_uart(void) | ||
| 796 | { | ||
| 797 | if (cpu_is_u8500()) { | ||
| 798 | prcmu_set(DB8500_PRCM_GPIOCR, | ||
| 799 | (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | | ||
| 800 | DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); | ||
| 801 | } | ||
| 802 | } | ||
| 803 | |||
| 804 | /** | ||
| 805 | * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD | ||
| 806 | * and UARTMOD on OtherAlternateC3. | ||
| 807 | */ | ||
| 808 | static inline void prcmu_disable_stm_mod_uart(void) | ||
| 809 | { | ||
| 810 | if (cpu_is_u8500()) { | ||
| 811 | prcmu_clear(DB8500_PRCM_GPIOCR, | ||
| 812 | (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 | | ||
| 813 | DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0)); | ||
| 814 | } | ||
| 815 | } | ||
| 816 | |||
| 817 | /** | ||
| 818 | * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1. | ||
| 819 | */ | ||
| 820 | static inline void prcmu_enable_stm_ape(void) | ||
| 821 | { | ||
| 822 | if (cpu_is_u8500()) { | ||
| 823 | prcmu_set(DB8500_PRCM_GPIOCR, | ||
| 824 | DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); | ||
| 825 | } | ||
| 826 | } | ||
| 827 | |||
| 828 | /** | ||
| 829 | * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1. | ||
| 830 | */ | ||
| 831 | static inline void prcmu_disable_stm_ape(void) | ||
| 832 | { | ||
| 833 | if (cpu_is_u8500()) { | ||
| 834 | prcmu_clear(DB8500_PRCM_GPIOCR, | ||
| 835 | DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD); | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | #else | ||
| 840 | |||
| 841 | static inline void prcmu_enable_spi2(void) {} | ||
| 842 | static inline void prcmu_disable_spi2(void) {} | ||
| 843 | static inline void prcmu_enable_stm_mod_uart(void) {} | ||
| 844 | static inline void prcmu_disable_stm_mod_uart(void) {} | ||
| 845 | static inline void prcmu_enable_stm_ape(void) {} | ||
| 846 | static inline void prcmu_disable_stm_ape(void) {} | ||
| 847 | |||
| 483 | #endif | 848 | #endif |
| 484 | 849 | ||
| 485 | /* PRCMU QoS APE OPP class */ | 850 | /* PRCMU QoS APE OPP class */ |
| 486 | #define PRCMU_QOS_APE_OPP 1 | 851 | #define PRCMU_QOS_APE_OPP 1 |
| 487 | #define PRCMU_QOS_DDR_OPP 2 | 852 | #define PRCMU_QOS_DDR_OPP 2 |
| 853 | #define PRCMU_QOS_ARM_OPP 3 | ||
| 488 | #define PRCMU_QOS_DEFAULT_VALUE -1 | 854 | #define PRCMU_QOS_DEFAULT_VALUE -1 |
| 489 | 855 | ||
| 490 | #ifdef CONFIG_UX500_PRCMU_QOS_POWER | 856 | #ifdef CONFIG_DBX500_PRCMU_QOS_POWER |
| 491 | 857 | ||
| 492 | unsigned long prcmu_qos_get_cpufreq_opp_delay(void); | 858 | unsigned long prcmu_qos_get_cpufreq_opp_delay(void); |
| 493 | void prcmu_qos_set_cpufreq_opp_delay(unsigned long); | 859 | void prcmu_qos_set_cpufreq_opp_delay(unsigned long); |
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h index b86ee45c8b03..10e038bac8dd 100644 --- a/include/linux/mfd/mc13xxx.h +++ b/include/linux/mfd/mc13xxx.h | |||
| @@ -38,7 +38,8 @@ int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq); | |||
| 38 | int mc13xxx_get_flags(struct mc13xxx *mc13xxx); | 38 | int mc13xxx_get_flags(struct mc13xxx *mc13xxx); |
| 39 | 39 | ||
| 40 | int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, | 40 | int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, |
| 41 | unsigned int mode, unsigned int channel, unsigned int *sample); | 41 | unsigned int mode, unsigned int channel, |
| 42 | u8 ato, bool atox, unsigned int *sample); | ||
| 42 | 43 | ||
| 43 | #define MC13XXX_IRQ_ADCDONE 0 | 44 | #define MC13XXX_IRQ_ADCDONE 0 |
| 44 | #define MC13XXX_IRQ_ADCBISDONE 1 | 45 | #define MC13XXX_IRQ_ADCBISDONE 1 |
| @@ -157,6 +158,18 @@ struct mc13xxx_buttons_platform_data { | |||
| 157 | unsigned short b3on_key; | 158 | unsigned short b3on_key; |
| 158 | }; | 159 | }; |
| 159 | 160 | ||
| 161 | struct mc13xxx_ts_platform_data { | ||
| 162 | /* Delay between Touchscreen polarization and ADC Conversion. | ||
| 163 | * Given in clock ticks of a 32 kHz clock which gives a granularity of | ||
| 164 | * about 30.5ms */ | ||
| 165 | u8 ato; | ||
| 166 | |||
| 167 | #define MC13783_TS_ATO_FIRST false | ||
| 168 | #define MC13783_TS_ATO_EACH true | ||
| 169 | /* Use the ATO delay only for the first conversion or for each one */ | ||
| 170 | bool atox; | ||
| 171 | }; | ||
| 172 | |||
| 160 | struct mc13xxx_platform_data { | 173 | struct mc13xxx_platform_data { |
| 161 | #define MC13XXX_USE_TOUCHSCREEN (1 << 0) | 174 | #define MC13XXX_USE_TOUCHSCREEN (1 << 0) |
| 162 | #define MC13XXX_USE_CODEC (1 << 1) | 175 | #define MC13XXX_USE_CODEC (1 << 1) |
| @@ -167,6 +180,7 @@ struct mc13xxx_platform_data { | |||
| 167 | struct mc13xxx_regulator_platform_data regulators; | 180 | struct mc13xxx_regulator_platform_data regulators; |
| 168 | struct mc13xxx_leds_platform_data *leds; | 181 | struct mc13xxx_leds_platform_data *leds; |
| 169 | struct mc13xxx_buttons_platform_data *buttons; | 182 | struct mc13xxx_buttons_platform_data *buttons; |
| 183 | struct mc13xxx_ts_platform_data touch; | ||
| 170 | }; | 184 | }; |
| 171 | 185 | ||
| 172 | #define MC13XXX_ADC_MODE_TS 1 | 186 | #define MC13XXX_ADC_MODE_TS 1 |
diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h new file mode 100644 index 000000000000..a2c61609d21d --- /dev/null +++ b/include/linux/mfd/rc5t583.h | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | /* | ||
| 2 | * Core driver interface to access RICOH_RC5T583 power management chip. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * Author: Laxman dewangan <ldewangan@nvidia.com> | ||
| 6 | * | ||
| 7 | * Based on code | ||
| 8 | * Copyright (C) 2011 RICOH COMPANY,LTD | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms and conditions of the GNU General Public License, | ||
| 12 | * version 2, as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 17 | * more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef __LINUX_MFD_RC5T583_H | ||
| 25 | #define __LINUX_MFD_RC5T583_H | ||
| 26 | |||
| 27 | #include <linux/mutex.h> | ||
| 28 | #include <linux/types.h> | ||
| 29 | |||
| 30 | #define RC5T583_MAX_REGS 0xF8 | ||
| 31 | |||
| 32 | /* Maximum number of main interrupts */ | ||
| 33 | #define MAX_MAIN_INTERRUPT 5 | ||
| 34 | #define RC5T583_MAX_GPEDGE_REG 2 | ||
| 35 | #define RC5T583_MAX_INTERRUPT_MASK_REGS 9 | ||
| 36 | |||
| 37 | /* Interrupt enable register */ | ||
| 38 | #define RC5T583_INT_EN_SYS1 0x19 | ||
| 39 | #define RC5T583_INT_EN_SYS2 0x1D | ||
| 40 | #define RC5T583_INT_EN_DCDC 0x41 | ||
| 41 | #define RC5T583_INT_EN_RTC 0xED | ||
| 42 | #define RC5T583_INT_EN_ADC1 0x90 | ||
| 43 | #define RC5T583_INT_EN_ADC2 0x91 | ||
| 44 | #define RC5T583_INT_EN_ADC3 0x92 | ||
| 45 | |||
| 46 | /* Interrupt status registers (monitor regs in Ricoh)*/ | ||
| 47 | #define RC5T583_INTC_INTPOL 0xAD | ||
| 48 | #define RC5T583_INTC_INTEN 0xAE | ||
| 49 | #define RC5T583_INTC_INTMON 0xAF | ||
| 50 | |||
| 51 | #define RC5T583_INT_MON_GRP 0xAF | ||
| 52 | #define RC5T583_INT_MON_SYS1 0x1B | ||
| 53 | #define RC5T583_INT_MON_SYS2 0x1F | ||
| 54 | #define RC5T583_INT_MON_DCDC 0x43 | ||
| 55 | #define RC5T583_INT_MON_RTC 0xEE | ||
| 56 | |||
| 57 | /* Interrupt clearing registers */ | ||
| 58 | #define RC5T583_INT_IR_SYS1 0x1A | ||
| 59 | #define RC5T583_INT_IR_SYS2 0x1E | ||
| 60 | #define RC5T583_INT_IR_DCDC 0x42 | ||
| 61 | #define RC5T583_INT_IR_RTC 0xEE | ||
| 62 | #define RC5T583_INT_IR_ADCL 0x94 | ||
| 63 | #define RC5T583_INT_IR_ADCH 0x95 | ||
| 64 | #define RC5T583_INT_IR_ADCEND 0x96 | ||
| 65 | #define RC5T583_INT_IR_GPIOR 0xA9 | ||
| 66 | #define RC5T583_INT_IR_GPIOF 0xAA | ||
| 67 | |||
| 68 | /* Sleep sequence registers */ | ||
| 69 | #define RC5T583_SLPSEQ1 0x21 | ||
| 70 | #define RC5T583_SLPSEQ2 0x22 | ||
| 71 | #define RC5T583_SLPSEQ3 0x23 | ||
| 72 | #define RC5T583_SLPSEQ4 0x24 | ||
| 73 | #define RC5T583_SLPSEQ5 0x25 | ||
| 74 | #define RC5T583_SLPSEQ6 0x26 | ||
| 75 | #define RC5T583_SLPSEQ7 0x27 | ||
| 76 | #define RC5T583_SLPSEQ8 0x28 | ||
| 77 | #define RC5T583_SLPSEQ9 0x29 | ||
| 78 | #define RC5T583_SLPSEQ10 0x2A | ||
| 79 | #define RC5T583_SLPSEQ11 0x2B | ||
| 80 | |||
| 81 | /* Regulator registers */ | ||
| 82 | #define RC5T583_REG_DC0CTL 0x30 | ||
| 83 | #define RC5T583_REG_DC0DAC 0x31 | ||
| 84 | #define RC5T583_REG_DC0LATCTL 0x32 | ||
| 85 | #define RC5T583_REG_SR0CTL 0x33 | ||
| 86 | |||
| 87 | #define RC5T583_REG_DC1CTL 0x34 | ||
| 88 | #define RC5T583_REG_DC1DAC 0x35 | ||
| 89 | #define RC5T583_REG_DC1LATCTL 0x36 | ||
| 90 | #define RC5T583_REG_SR1CTL 0x37 | ||
| 91 | |||
| 92 | #define RC5T583_REG_DC2CTL 0x38 | ||
| 93 | #define RC5T583_REG_DC2DAC 0x39 | ||
| 94 | #define RC5T583_REG_DC2LATCTL 0x3A | ||
| 95 | #define RC5T583_REG_SR2CTL 0x3B | ||
| 96 | |||
| 97 | #define RC5T583_REG_DC3CTL 0x3C | ||
| 98 | #define RC5T583_REG_DC3DAC 0x3D | ||
| 99 | #define RC5T583_REG_DC3LATCTL 0x3E | ||
| 100 | #define RC5T583_REG_SR3CTL 0x3F | ||
| 101 | |||
| 102 | |||
| 103 | #define RC5T583_REG_LDOEN1 0x50 | ||
| 104 | #define RC5T583_REG_LDOEN2 0x51 | ||
| 105 | #define RC5T583_REG_LDODIS1 0x52 | ||
| 106 | #define RC5T583_REG_LDODIS2 0x53 | ||
| 107 | |||
| 108 | #define RC5T583_REG_LDO0DAC 0x54 | ||
| 109 | #define RC5T583_REG_LDO1DAC 0x55 | ||
| 110 | #define RC5T583_REG_LDO2DAC 0x56 | ||
| 111 | #define RC5T583_REG_LDO3DAC 0x57 | ||
| 112 | #define RC5T583_REG_LDO4DAC 0x58 | ||
| 113 | #define RC5T583_REG_LDO5DAC 0x59 | ||
| 114 | #define RC5T583_REG_LDO6DAC 0x5A | ||
| 115 | #define RC5T583_REG_LDO7DAC 0x5B | ||
| 116 | #define RC5T583_REG_LDO8DAC 0x5C | ||
| 117 | #define RC5T583_REG_LDO9DAC 0x5D | ||
| 118 | |||
| 119 | #define RC5T583_REG_DC0DAC_DS 0x60 | ||
| 120 | #define RC5T583_REG_DC1DAC_DS 0x61 | ||
| 121 | #define RC5T583_REG_DC2DAC_DS 0x62 | ||
| 122 | #define RC5T583_REG_DC3DAC_DS 0x63 | ||
| 123 | |||
| 124 | #define RC5T583_REG_LDO0DAC_DS 0x64 | ||
| 125 | #define RC5T583_REG_LDO1DAC_DS 0x65 | ||
| 126 | #define RC5T583_REG_LDO2DAC_DS 0x66 | ||
| 127 | #define RC5T583_REG_LDO3DAC_DS 0x67 | ||
| 128 | #define RC5T583_REG_LDO4DAC_DS 0x68 | ||
| 129 | #define RC5T583_REG_LDO5DAC_DS 0x69 | ||
| 130 | #define RC5T583_REG_LDO6DAC_DS 0x6A | ||
| 131 | #define RC5T583_REG_LDO7DAC_DS 0x6B | ||
| 132 | #define RC5T583_REG_LDO8DAC_DS 0x6C | ||
| 133 | #define RC5T583_REG_LDO9DAC_DS 0x6D | ||
| 134 | |||
| 135 | /* GPIO register base address */ | ||
| 136 | #define RC5T583_GPIO_IOSEL 0xA0 | ||
| 137 | #define RC5T583_GPIO_PDEN 0xA1 | ||
| 138 | #define RC5T583_GPIO_IOOUT 0xA2 | ||
| 139 | #define RC5T583_GPIO_PGSEL 0xA3 | ||
| 140 | #define RC5T583_GPIO_GPINV 0xA4 | ||
| 141 | #define RC5T583_GPIO_GPDEB 0xA5 | ||
| 142 | #define RC5T583_GPIO_GPEDGE1 0xA6 | ||
| 143 | #define RC5T583_GPIO_GPEDGE2 0xA7 | ||
| 144 | #define RC5T583_GPIO_EN_INT 0xA8 | ||
| 145 | #define RC5T583_GPIO_MON_IOIN 0xAB | ||
| 146 | #define RC5T583_GPIO_GPOFUNC 0xAC | ||
| 147 | |||
| 148 | /* RICOH_RC5T583 IRQ definitions */ | ||
| 149 | enum { | ||
| 150 | RC5T583_IRQ_ONKEY, | ||
| 151 | RC5T583_IRQ_ACOK, | ||
| 152 | RC5T583_IRQ_LIDOPEN, | ||
| 153 | RC5T583_IRQ_PREOT, | ||
| 154 | RC5T583_IRQ_CLKSTP, | ||
| 155 | RC5T583_IRQ_ONKEY_OFF, | ||
| 156 | RC5T583_IRQ_WD, | ||
| 157 | RC5T583_IRQ_EN_PWRREQ1, | ||
| 158 | RC5T583_IRQ_EN_PWRREQ2, | ||
| 159 | RC5T583_IRQ_PRE_VINDET, | ||
| 160 | |||
| 161 | RC5T583_IRQ_DC0LIM, | ||
| 162 | RC5T583_IRQ_DC1LIM, | ||
| 163 | RC5T583_IRQ_DC2LIM, | ||
| 164 | RC5T583_IRQ_DC3LIM, | ||
| 165 | |||
| 166 | RC5T583_IRQ_CTC, | ||
| 167 | RC5T583_IRQ_YALE, | ||
| 168 | RC5T583_IRQ_DALE, | ||
| 169 | RC5T583_IRQ_WALE, | ||
| 170 | |||
| 171 | RC5T583_IRQ_AIN1L, | ||
| 172 | RC5T583_IRQ_AIN2L, | ||
| 173 | RC5T583_IRQ_AIN3L, | ||
| 174 | RC5T583_IRQ_VBATL, | ||
| 175 | RC5T583_IRQ_VIN3L, | ||
| 176 | RC5T583_IRQ_VIN8L, | ||
| 177 | RC5T583_IRQ_AIN1H, | ||
| 178 | RC5T583_IRQ_AIN2H, | ||
| 179 | RC5T583_IRQ_AIN3H, | ||
| 180 | RC5T583_IRQ_VBATH, | ||
| 181 | RC5T583_IRQ_VIN3H, | ||
| 182 | RC5T583_IRQ_VIN8H, | ||
| 183 | RC5T583_IRQ_ADCEND, | ||
| 184 | |||
| 185 | RC5T583_IRQ_GPIO0, | ||
| 186 | RC5T583_IRQ_GPIO1, | ||
| 187 | RC5T583_IRQ_GPIO2, | ||
| 188 | RC5T583_IRQ_GPIO3, | ||
| 189 | RC5T583_IRQ_GPIO4, | ||
| 190 | RC5T583_IRQ_GPIO5, | ||
| 191 | RC5T583_IRQ_GPIO6, | ||
| 192 | RC5T583_IRQ_GPIO7, | ||
| 193 | |||
| 194 | /* Should be last entry */ | ||
| 195 | RC5T583_MAX_IRQS, | ||
| 196 | }; | ||
| 197 | |||
| 198 | /* Ricoh583 gpio definitions */ | ||
| 199 | enum { | ||
| 200 | RC5T583_GPIO0, | ||
| 201 | RC5T583_GPIO1, | ||
| 202 | RC5T583_GPIO2, | ||
| 203 | RC5T583_GPIO3, | ||
| 204 | RC5T583_GPIO4, | ||
| 205 | RC5T583_GPIO5, | ||
| 206 | RC5T583_GPIO6, | ||
| 207 | RC5T583_GPIO7, | ||
| 208 | |||
| 209 | /* Should be last entry */ | ||
| 210 | RC5T583_MAX_GPIO, | ||
| 211 | }; | ||
| 212 | |||
| 213 | enum { | ||
| 214 | RC5T583_DS_NONE, | ||
| 215 | RC5T583_DS_DC0, | ||
| 216 | RC5T583_DS_DC1, | ||
| 217 | RC5T583_DS_DC2, | ||
| 218 | RC5T583_DS_DC3, | ||
| 219 | RC5T583_DS_LDO0, | ||
| 220 | RC5T583_DS_LDO1, | ||
| 221 | RC5T583_DS_LDO2, | ||
| 222 | RC5T583_DS_LDO3, | ||
| 223 | RC5T583_DS_LDO4, | ||
| 224 | RC5T583_DS_LDO5, | ||
| 225 | RC5T583_DS_LDO6, | ||
| 226 | RC5T583_DS_LDO7, | ||
| 227 | RC5T583_DS_LDO8, | ||
| 228 | RC5T583_DS_LDO9, | ||
| 229 | RC5T583_DS_PSO0, | ||
| 230 | RC5T583_DS_PSO1, | ||
| 231 | RC5T583_DS_PSO2, | ||
| 232 | RC5T583_DS_PSO3, | ||
| 233 | RC5T583_DS_PSO4, | ||
| 234 | RC5T583_DS_PSO5, | ||
| 235 | RC5T583_DS_PSO6, | ||
| 236 | RC5T583_DS_PSO7, | ||
| 237 | |||
| 238 | /* Should be last entry */ | ||
| 239 | RC5T583_DS_MAX, | ||
| 240 | }; | ||
| 241 | |||
| 242 | /* | ||
| 243 | * Ricoh pmic RC5T583 supports sleep through two external controls. | ||
| 244 | * The output of gpios and regulator can be enable/disable through | ||
| 245 | * this external signals. | ||
| 246 | */ | ||
| 247 | enum { | ||
| 248 | RC5T583_EXT_PWRREQ1_CONTROL = 0x1, | ||
| 249 | RC5T583_EXT_PWRREQ2_CONTROL = 0x2, | ||
| 250 | }; | ||
| 251 | |||
| 252 | struct rc5t583 { | ||
| 253 | struct device *dev; | ||
| 254 | struct regmap *regmap; | ||
| 255 | int chip_irq; | ||
| 256 | int irq_base; | ||
| 257 | struct mutex irq_lock; | ||
| 258 | unsigned long group_irq_en[MAX_MAIN_INTERRUPT]; | ||
| 259 | |||
| 260 | /* For main interrupt bits in INTC */ | ||
| 261 | uint8_t intc_inten_reg; | ||
| 262 | |||
| 263 | /* For group interrupt bits and address */ | ||
| 264 | uint8_t irq_en_reg[RC5T583_MAX_INTERRUPT_MASK_REGS]; | ||
| 265 | |||
| 266 | /* For gpio edge */ | ||
| 267 | uint8_t gpedge_reg[RC5T583_MAX_GPEDGE_REG]; | ||
| 268 | }; | ||
| 269 | |||
| 270 | /* | ||
| 271 | * rc5t583_platform_data: Platform data for ricoh rc5t583 pmu. | ||
| 272 | * The board specific data is provided through this structure. | ||
| 273 | * @irq_base: Irq base number on which this device registers their interrupts. | ||
| 274 | * @enable_shutdown: Enable shutdown through the input pin "shutdown". | ||
| 275 | */ | ||
| 276 | |||
| 277 | struct rc5t583_platform_data { | ||
| 278 | int irq_base; | ||
| 279 | bool enable_shutdown; | ||
| 280 | }; | ||
| 281 | |||
| 282 | int rc5t583_write(struct device *dev, u8 reg, uint8_t val); | ||
| 283 | int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val); | ||
| 284 | int rc5t583_set_bits(struct device *dev, unsigned int reg, | ||
| 285 | unsigned int bit_mask); | ||
| 286 | int rc5t583_clear_bits(struct device *dev, unsigned int reg, | ||
| 287 | unsigned int bit_mask); | ||
| 288 | int rc5t583_update(struct device *dev, unsigned int reg, | ||
| 289 | unsigned int val, unsigned int mask); | ||
| 290 | int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id, | ||
| 291 | int ext_pwr_req, int deepsleep_slot_nr); | ||
| 292 | int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base); | ||
| 293 | int rc5t583_irq_exit(struct rc5t583 *rc5t583); | ||
| 294 | |||
| 295 | #endif | ||
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index 8c54de674b4b..8516fd1eaabc 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h | |||
| @@ -28,6 +28,7 @@ enum stmpe_partnum { | |||
| 28 | STMPE1601, | 28 | STMPE1601, |
| 29 | STMPE2401, | 29 | STMPE2401, |
| 30 | STMPE2403, | 30 | STMPE2403, |
| 31 | STMPE_NBR_PARTS | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | /* | 34 | /* |
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h new file mode 100644 index 000000000000..38e31c55adbb --- /dev/null +++ b/include/linux/mfd/tps65090.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * Core driver interface for TI TPS65090 PMIC family | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 NVIDIA Corporation | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef __LINUX_MFD_TPS65090_H | ||
| 23 | #define __LINUX_MFD_TPS65090_H | ||
| 24 | |||
| 25 | struct tps65090_subdev_info { | ||
| 26 | int id; | ||
| 27 | const char *name; | ||
| 28 | void *platform_data; | ||
| 29 | }; | ||
| 30 | |||
| 31 | struct tps65090_platform_data { | ||
| 32 | int irq_base; | ||
| 33 | int num_subdevs; | ||
| 34 | struct tps65090_subdev_info *subdevs; | ||
| 35 | }; | ||
| 36 | |||
| 37 | /* | ||
| 38 | * NOTE: the functions below are not intended for use outside | ||
| 39 | * of the TPS65090 sub-device drivers | ||
| 40 | */ | ||
| 41 | extern int tps65090_write(struct device *dev, int reg, uint8_t val); | ||
| 42 | extern int tps65090_read(struct device *dev, int reg, uint8_t *val); | ||
| 43 | extern int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num); | ||
| 44 | extern int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num); | ||
| 45 | |||
| 46 | #endif /*__LINUX_MFD_TPS65090_H */ | ||
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h new file mode 100644 index 000000000000..e030ef9a64ee --- /dev/null +++ b/include/linux/mfd/tps65217.h | |||
| @@ -0,0 +1,283 @@ | |||
| 1 | /* | ||
| 2 | * linux/mfd/tps65217.h | ||
| 3 | * | ||
| 4 | * Functions to access TPS65217 power management chip. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License as | ||
| 10 | * published by the Free Software Foundation version 2. | ||
| 11 | * | ||
| 12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 13 | * kind, whether express or implied; without even the implied warranty | ||
| 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef __LINUX_MFD_TPS65217_H | ||
| 19 | #define __LINUX_MFD_TPS65217_H | ||
| 20 | |||
| 21 | #include <linux/i2c.h> | ||
| 22 | #include <linux/regulator/driver.h> | ||
| 23 | #include <linux/regulator/machine.h> | ||
| 24 | |||
| 25 | /* I2C ID for TPS65217 part */ | ||
| 26 | #define TPS65217_I2C_ID 0x24 | ||
| 27 | |||
| 28 | /* All register addresses */ | ||
| 29 | #define TPS65217_REG_CHIPID 0X00 | ||
| 30 | #define TPS65217_REG_PPATH 0X01 | ||
| 31 | #define TPS65217_REG_INT 0X02 | ||
| 32 | #define TPS65217_REG_CHGCONFIG0 0X03 | ||
| 33 | #define TPS65217_REG_CHGCONFIG1 0X04 | ||
| 34 | #define TPS65217_REG_CHGCONFIG2 0X05 | ||
| 35 | #define TPS65217_REG_CHGCONFIG3 0X06 | ||
| 36 | #define TPS65217_REG_WLEDCTRL1 0X07 | ||
| 37 | #define TPS65217_REG_WLEDCTRL2 0X08 | ||
| 38 | #define TPS65217_REG_MUXCTRL 0X09 | ||
| 39 | #define TPS65217_REG_STATUS 0X0A | ||
| 40 | #define TPS65217_REG_PASSWORD 0X0B | ||
| 41 | #define TPS65217_REG_PGOOD 0X0C | ||
| 42 | #define TPS65217_REG_DEFPG 0X0D | ||
| 43 | #define TPS65217_REG_DEFDCDC1 0X0E | ||
| 44 | #define TPS65217_REG_DEFDCDC2 0X0F | ||
| 45 | #define TPS65217_REG_DEFDCDC3 0X10 | ||
| 46 | #define TPS65217_REG_DEFSLEW 0X11 | ||
| 47 | #define TPS65217_REG_DEFLDO1 0X12 | ||
| 48 | #define TPS65217_REG_DEFLDO2 0X13 | ||
| 49 | #define TPS65217_REG_DEFLS1 0X14 | ||
| 50 | #define TPS65217_REG_DEFLS2 0X15 | ||
| 51 | #define TPS65217_REG_ENABLE 0X16 | ||
| 52 | #define TPS65217_REG_DEFUVLO 0X18 | ||
| 53 | #define TPS65217_REG_SEQ1 0X19 | ||
| 54 | #define TPS65217_REG_SEQ2 0X1A | ||
| 55 | #define TPS65217_REG_SEQ3 0X1B | ||
| 56 | #define TPS65217_REG_SEQ4 0X1C | ||
| 57 | #define TPS65217_REG_SEQ5 0X1D | ||
| 58 | #define TPS65217_REG_SEQ6 0X1E | ||
| 59 | |||
| 60 | /* Register field definitions */ | ||
| 61 | #define TPS65217_CHIPID_CHIP_MASK 0xF0 | ||
| 62 | #define TPS65217_CHIPID_REV_MASK 0x0F | ||
| 63 | |||
| 64 | #define TPS65217_PPATH_ACSINK_ENABLE BIT(7) | ||
| 65 | #define TPS65217_PPATH_USBSINK_ENABLE BIT(6) | ||
| 66 | #define TPS65217_PPATH_AC_PW_ENABLE BIT(5) | ||
| 67 | #define TPS65217_PPATH_USB_PW_ENABLE BIT(4) | ||
| 68 | #define TPS65217_PPATH_AC_CURRENT_MASK 0x0C | ||
| 69 | #define TPS65217_PPATH_USB_CURRENT_MASK 0x03 | ||
| 70 | |||
| 71 | #define TPS65217_INT_PBM BIT(6) | ||
| 72 | #define TPS65217_INT_ACM BIT(5) | ||
| 73 | #define TPS65217_INT_USBM BIT(4) | ||
| 74 | #define TPS65217_INT_PBI BIT(2) | ||
| 75 | #define TPS65217_INT_ACI BIT(1) | ||
| 76 | #define TPS65217_INT_USBI BIT(0) | ||
| 77 | |||
| 78 | #define TPS65217_CHGCONFIG0_TREG BIT(7) | ||
| 79 | #define TPS65217_CHGCONFIG0_DPPM BIT(6) | ||
| 80 | #define TPS65217_CHGCONFIG0_TSUSP BIT(5) | ||
| 81 | #define TPS65217_CHGCONFIG0_TERMI BIT(4) | ||
| 82 | #define TPS65217_CHGCONFIG0_ACTIVE BIT(3) | ||
| 83 | #define TPS65217_CHGCONFIG0_CHGTOUT BIT(2) | ||
| 84 | #define TPS65217_CHGCONFIG0_PCHGTOUT BIT(1) | ||
| 85 | #define TPS65217_CHGCONFIG0_BATTEMP BIT(0) | ||
| 86 | |||
| 87 | #define TPS65217_CHGCONFIG1_TMR_MASK 0xC0 | ||
| 88 | #define TPS65217_CHGCONFIG1_TMR_ENABLE BIT(5) | ||
| 89 | #define TPS65217_CHGCONFIG1_NTC_TYPE BIT(4) | ||
| 90 | #define TPS65217_CHGCONFIG1_RESET BIT(3) | ||
| 91 | #define TPS65217_CHGCONFIG1_TERM BIT(2) | ||
| 92 | #define TPS65217_CHGCONFIG1_SUSP BIT(1) | ||
| 93 | #define TPS65217_CHGCONFIG1_CHG_EN BIT(0) | ||
| 94 | |||
| 95 | #define TPS65217_CHGCONFIG2_DYNTMR BIT(7) | ||
| 96 | #define TPS65217_CHGCONFIG2_VPREGHG BIT(6) | ||
| 97 | #define TPS65217_CHGCONFIG2_VOREG_MASK 0x30 | ||
| 98 | |||
| 99 | #define TPS65217_CHGCONFIG3_ICHRG_MASK 0xC0 | ||
| 100 | #define TPS65217_CHGCONFIG3_DPPMTH_MASK 0x30 | ||
| 101 | #define TPS65217_CHGCONFIG2_PCHRGT BIT(3) | ||
| 102 | #define TPS65217_CHGCONFIG2_TERMIF 0x06 | ||
| 103 | #define TPS65217_CHGCONFIG2_TRANGE BIT(0) | ||
| 104 | |||
| 105 | #define TPS65217_WLEDCTRL1_ISINK_ENABLE BIT(3) | ||
| 106 | #define TPS65217_WLEDCTRL1_ISEL BIT(2) | ||
| 107 | #define TPS65217_WLEDCTRL1_FDIM_MASK 0x03 | ||
| 108 | |||
| 109 | #define TPS65217_WLEDCTRL2_DUTY_MASK 0x7F | ||
| 110 | |||
| 111 | #define TPS65217_MUXCTRL_MUX_MASK 0x07 | ||
| 112 | |||
| 113 | #define TPS65217_STATUS_OFF BIT(7) | ||
| 114 | #define TPS65217_STATUS_ACPWR BIT(3) | ||
| 115 | #define TPS65217_STATUS_USBPWR BIT(2) | ||
| 116 | #define TPS65217_STATUS_PB BIT(0) | ||
| 117 | |||
| 118 | #define TPS65217_PASSWORD_REGS_UNLOCK 0x7D | ||
| 119 | |||
| 120 | #define TPS65217_PGOOD_LDO3_PG BIT(6) | ||
| 121 | #define TPS65217_PGOOD_LDO4_PG BIT(5) | ||
| 122 | #define TPS65217_PGOOD_DC1_PG BIT(4) | ||
| 123 | #define TPS65217_PGOOD_DC2_PG BIT(3) | ||
| 124 | #define TPS65217_PGOOD_DC3_PG BIT(2) | ||
| 125 | #define TPS65217_PGOOD_LDO1_PG BIT(1) | ||
| 126 | #define TPS65217_PGOOD_LDO2_PG BIT(0) | ||
| 127 | |||
| 128 | #define TPS65217_DEFPG_LDO1PGM BIT(3) | ||
| 129 | #define TPS65217_DEFPG_LDO2PGM BIT(2) | ||
| 130 | #define TPS65217_DEFPG_PGDLY_MASK 0x03 | ||
| 131 | |||
| 132 | #define TPS65217_DEFDCDCX_XADJX BIT(7) | ||
| 133 | #define TPS65217_DEFDCDCX_DCDC_MASK 0x3F | ||
| 134 | |||
| 135 | #define TPS65217_DEFSLEW_GO BIT(7) | ||
| 136 | #define TPS65217_DEFSLEW_GODSBL BIT(6) | ||
| 137 | #define TPS65217_DEFSLEW_PFM_EN1 BIT(5) | ||
| 138 | #define TPS65217_DEFSLEW_PFM_EN2 BIT(4) | ||
| 139 | #define TPS65217_DEFSLEW_PFM_EN3 BIT(3) | ||
| 140 | #define TPS65217_DEFSLEW_SLEW_MASK 0x07 | ||
| 141 | |||
| 142 | #define TPS65217_DEFLDO1_LDO1_MASK 0x0F | ||
| 143 | |||
| 144 | #define TPS65217_DEFLDO2_TRACK BIT(6) | ||
| 145 | #define TPS65217_DEFLDO2_LDO2_MASK 0x3F | ||
| 146 | |||
| 147 | #define TPS65217_DEFLDO3_LDO3_EN BIT(5) | ||
| 148 | #define TPS65217_DEFLDO3_LDO3_MASK 0x1F | ||
| 149 | |||
| 150 | #define TPS65217_DEFLDO4_LDO4_EN BIT(5) | ||
| 151 | #define TPS65217_DEFLDO4_LDO4_MASK 0x1F | ||
| 152 | |||
| 153 | #define TPS65217_ENABLE_LS1_EN BIT(6) | ||
| 154 | #define TPS65217_ENABLE_LS2_EN BIT(5) | ||
| 155 | #define TPS65217_ENABLE_DC1_EN BIT(4) | ||
| 156 | #define TPS65217_ENABLE_DC2_EN BIT(3) | ||
| 157 | #define TPS65217_ENABLE_DC3_EN BIT(2) | ||
| 158 | #define TPS65217_ENABLE_LDO1_EN BIT(1) | ||
| 159 | #define TPS65217_ENABLE_LDO2_EN BIT(0) | ||
| 160 | |||
| 161 | #define TPS65217_DEFUVLO_UVLOHYS BIT(2) | ||
| 162 | #define TPS65217_DEFUVLO_UVLO_MASK 0x03 | ||
| 163 | |||
| 164 | #define TPS65217_SEQ1_DC1_SEQ_MASK 0xF0 | ||
| 165 | #define TPS65217_SEQ1_DC2_SEQ_MASK 0x0F | ||
| 166 | |||
| 167 | #define TPS65217_SEQ2_DC3_SEQ_MASK 0xF0 | ||
| 168 | #define TPS65217_SEQ2_LDO1_SEQ_MASK 0x0F | ||
| 169 | |||
| 170 | #define TPS65217_SEQ3_LDO2_SEQ_MASK 0xF0 | ||
| 171 | #define TPS65217_SEQ3_LDO3_SEQ_MASK 0x0F | ||
| 172 | |||
| 173 | #define TPS65217_SEQ4_LDO4_SEQ_MASK 0xF0 | ||
| 174 | |||
| 175 | #define TPS65217_SEQ5_DLY1_MASK 0xC0 | ||
| 176 | #define TPS65217_SEQ5_DLY2_MASK 0x30 | ||
| 177 | #define TPS65217_SEQ5_DLY3_MASK 0x0C | ||
| 178 | #define TPS65217_SEQ5_DLY4_MASK 0x03 | ||
| 179 | |||
| 180 | #define TPS65217_SEQ6_DLY5_MASK 0xC0 | ||
| 181 | #define TPS65217_SEQ6_DLY6_MASK 0x30 | ||
| 182 | #define TPS65217_SEQ6_SEQUP BIT(2) | ||
| 183 | #define TPS65217_SEQ6_SEQDWN BIT(1) | ||
| 184 | #define TPS65217_SEQ6_INSTDWN BIT(0) | ||
| 185 | |||
| 186 | #define TPS65217_MAX_REGISTER 0x1E | ||
| 187 | #define TPS65217_PROTECT_NONE 0 | ||
| 188 | #define TPS65217_PROTECT_L1 1 | ||
| 189 | #define TPS65217_PROTECT_L2 2 | ||
| 190 | |||
| 191 | |||
| 192 | enum tps65217_regulator_id { | ||
| 193 | /* DCDC's */ | ||
| 194 | TPS65217_DCDC_1, | ||
| 195 | TPS65217_DCDC_2, | ||
| 196 | TPS65217_DCDC_3, | ||
| 197 | /* LDOs */ | ||
| 198 | TPS65217_LDO_1, | ||
| 199 | TPS65217_LDO_2, | ||
| 200 | TPS65217_LDO_3, | ||
| 201 | TPS65217_LDO_4, | ||
| 202 | }; | ||
| 203 | |||
| 204 | #define TPS65217_MAX_REG_ID TPS65217_LDO_4 | ||
| 205 | |||
| 206 | /* Number of step-down converters available */ | ||
| 207 | #define TPS65217_NUM_DCDC 3 | ||
| 208 | /* Number of LDO voltage regulators available */ | ||
| 209 | #define TPS65217_NUM_LDO 4 | ||
| 210 | /* Number of total regulators available */ | ||
| 211 | #define TPS65217_NUM_REGULATOR (TPS65217_NUM_DCDC + TPS65217_NUM_LDO) | ||
| 212 | |||
| 213 | /** | ||
| 214 | * struct tps65217_board - packages regulator init data | ||
| 215 | * @tps65217_regulator_data: regulator initialization values | ||
| 216 | * | ||
| 217 | * Board data may be used to initialize regulator. | ||
| 218 | */ | ||
| 219 | struct tps65217_board { | ||
| 220 | struct regulator_init_data *tps65217_init_data; | ||
| 221 | }; | ||
| 222 | |||
| 223 | /** | ||
| 224 | * struct tps_info - packages regulator constraints | ||
| 225 | * @name: Voltage regulator name | ||
| 226 | * @min_uV: minimum micro volts | ||
| 227 | * @max_uV: minimum micro volts | ||
| 228 | * @vsel_to_uv: Function pointer to get voltage from selector | ||
| 229 | * @uv_to_vsel: Function pointer to get selector from voltage | ||
| 230 | * @table: Table for non-uniform voltage step-size | ||
| 231 | * @table_len: Length of the voltage table | ||
| 232 | * @enable_mask: Regulator enable mask bits | ||
| 233 | * @set_vout_reg: Regulator output voltage set register | ||
| 234 | * @set_vout_mask: Regulator output voltage set mask | ||
| 235 | * | ||
| 236 | * This data is used to check the regualtor voltage limits while setting. | ||
| 237 | */ | ||
| 238 | struct tps_info { | ||
| 239 | const char *name; | ||
| 240 | int min_uV; | ||
| 241 | int max_uV; | ||
| 242 | int (*vsel_to_uv)(unsigned int vsel); | ||
| 243 | int (*uv_to_vsel)(int uV, unsigned int *vsel); | ||
| 244 | const int *table; | ||
| 245 | unsigned int table_len; | ||
| 246 | unsigned int enable_mask; | ||
| 247 | unsigned int set_vout_reg; | ||
| 248 | unsigned int set_vout_mask; | ||
| 249 | }; | ||
| 250 | |||
| 251 | /** | ||
| 252 | * struct tps65217 - tps65217 sub-driver chip access routines | ||
| 253 | * | ||
| 254 | * Device data may be used to access the TPS65217 chip | ||
| 255 | */ | ||
| 256 | |||
| 257 | struct tps65217 { | ||
| 258 | struct device *dev; | ||
| 259 | struct tps65217_board *pdata; | ||
| 260 | struct regulator_desc desc[TPS65217_NUM_REGULATOR]; | ||
| 261 | struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; | ||
| 262 | struct tps_info *info[TPS65217_NUM_REGULATOR]; | ||
| 263 | struct regmap *regmap; | ||
| 264 | |||
| 265 | /* Client devices */ | ||
| 266 | struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR]; | ||
| 267 | }; | ||
| 268 | |||
| 269 | static inline struct tps65217 *dev_to_tps65217(struct device *dev) | ||
| 270 | { | ||
| 271 | return dev_get_drvdata(dev); | ||
| 272 | } | ||
| 273 | |||
| 274 | int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, | ||
| 275 | unsigned int *val); | ||
| 276 | int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, | ||
| 277 | unsigned int val, unsigned int level); | ||
| 278 | int tps65217_set_bits(struct tps65217 *tps, unsigned int reg, | ||
| 279 | unsigned int mask, unsigned int val, unsigned int level); | ||
| 280 | int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, | ||
| 281 | unsigned int mask, unsigned int level); | ||
| 282 | |||
| 283 | #endif /* __LINUX_MFD_TPS65217_H */ | ||
diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 76700b5eee92..e34886397f90 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #ifndef __LINUX_MFD_TPS65910_H | 17 | #ifndef __LINUX_MFD_TPS65910_H |
| 18 | #define __LINUX_MFD_TPS65910_H | 18 | #define __LINUX_MFD_TPS65910_H |
| 19 | 19 | ||
| 20 | #include <linux/gpio.h> | ||
| 21 | |||
| 20 | /* TPS chip id list */ | 22 | /* TPS chip id list */ |
| 21 | #define TPS65910 0 | 23 | #define TPS65910 0 |
| 22 | #define TPS65911 1 | 24 | #define TPS65911 1 |
| @@ -796,6 +798,7 @@ struct tps65910_board { | |||
| 796 | struct tps65910 { | 798 | struct tps65910 { |
| 797 | struct device *dev; | 799 | struct device *dev; |
| 798 | struct i2c_client *i2c_client; | 800 | struct i2c_client *i2c_client; |
| 801 | struct regmap *regmap; | ||
| 799 | struct mutex io_mutex; | 802 | struct mutex io_mutex; |
| 800 | unsigned int id; | 803 | unsigned int id; |
| 801 | int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest); | 804 | int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest); |
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index dc3e05011689..893267bb6229 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h | |||
| @@ -22,7 +22,6 @@ struct wm8994_ldo_pdata { | |||
| 22 | /** GPIOs to enable regulator, 0 or less if not available */ | 22 | /** GPIOs to enable regulator, 0 or less if not available */ |
| 23 | int enable; | 23 | int enable; |
| 24 | 24 | ||
| 25 | const char *supply; | ||
| 26 | const struct regulator_init_data *init_data; | 25 | const struct regulator_init_data *init_data; |
| 27 | }; | 26 | }; |
| 28 | 27 | ||
diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 76579f964a29..7bd73bbdfd1b 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h | |||
| @@ -26,7 +26,26 @@ enum ab8500_regulator_id { | |||
| 26 | AB8500_NUM_REGULATORS, | 26 | AB8500_NUM_REGULATORS, |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | /* AB8500 register initialization */ | 29 | /* AB9450 regulators */ |
| 30 | enum ab9540_regulator_id { | ||
| 31 | AB9540_LDO_AUX1, | ||
| 32 | AB9540_LDO_AUX2, | ||
| 33 | AB9540_LDO_AUX3, | ||
| 34 | AB9540_LDO_AUX4, | ||
| 35 | AB9540_LDO_INTCORE, | ||
| 36 | AB9540_LDO_TVOUT, | ||
| 37 | AB9540_LDO_USB, | ||
| 38 | AB9540_LDO_AUDIO, | ||
| 39 | AB9540_LDO_ANAMIC1, | ||
| 40 | AB9540_LDO_ANAMIC2, | ||
| 41 | AB9540_LDO_DMIC, | ||
| 42 | AB9540_LDO_ANA, | ||
| 43 | AB9540_SYSCLKREQ_2, | ||
| 44 | AB9540_SYSCLKREQ_4, | ||
| 45 | AB9540_NUM_REGULATORS, | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* AB8500 and AB9540 register initialization */ | ||
| 30 | struct ab8500_regulator_reg_init { | 49 | struct ab8500_regulator_reg_init { |
| 31 | int id; | 50 | int id; |
| 32 | u8 value; | 51 | u8 value; |
| @@ -71,4 +90,53 @@ enum ab8500_regulator_reg { | |||
| 71 | AB8500_NUM_REGULATOR_REGISTERS, | 90 | AB8500_NUM_REGULATOR_REGISTERS, |
| 72 | }; | 91 | }; |
| 73 | 92 | ||
| 93 | |||
| 94 | /* AB9540 registers */ | ||
| 95 | enum ab9540_regulator_reg { | ||
| 96 | AB9540_REGUREQUESTCTRL1, | ||
| 97 | AB9540_REGUREQUESTCTRL2, | ||
| 98 | AB9540_REGUREQUESTCTRL3, | ||
| 99 | AB9540_REGUREQUESTCTRL4, | ||
| 100 | AB9540_REGUSYSCLKREQ1HPVALID1, | ||
| 101 | AB9540_REGUSYSCLKREQ1HPVALID2, | ||
| 102 | AB9540_REGUHWHPREQ1VALID1, | ||
| 103 | AB9540_REGUHWHPREQ1VALID2, | ||
| 104 | AB9540_REGUHWHPREQ2VALID1, | ||
| 105 | AB9540_REGUHWHPREQ2VALID2, | ||
| 106 | AB9540_REGUSWHPREQVALID1, | ||
| 107 | AB9540_REGUSWHPREQVALID2, | ||
| 108 | AB9540_REGUSYSCLKREQVALID1, | ||
| 109 | AB9540_REGUSYSCLKREQVALID2, | ||
| 110 | AB9540_REGUVAUX4REQVALID, | ||
| 111 | AB9540_REGUMISC1, | ||
| 112 | AB9540_VAUDIOSUPPLY, | ||
| 113 | AB9540_REGUCTRL1VAMIC, | ||
| 114 | AB9540_VSMPS1REGU, | ||
| 115 | AB9540_VSMPS2REGU, | ||
| 116 | AB9540_VSMPS3REGU, /* NOTE! PRCMU register */ | ||
| 117 | AB9540_VPLLVANAREGU, | ||
| 118 | AB9540_EXTSUPPLYREGU, | ||
| 119 | AB9540_VAUX12REGU, | ||
| 120 | AB9540_VRF1VAUX3REGU, | ||
| 121 | AB9540_VSMPS1SEL1, | ||
| 122 | AB9540_VSMPS1SEL2, | ||
| 123 | AB9540_VSMPS1SEL3, | ||
| 124 | AB9540_VSMPS2SEL1, | ||
| 125 | AB9540_VSMPS2SEL2, | ||
| 126 | AB9540_VSMPS2SEL3, | ||
| 127 | AB9540_VSMPS3SEL1, /* NOTE! PRCMU register */ | ||
| 128 | AB9540_VSMPS3SEL2, /* NOTE! PRCMU register */ | ||
| 129 | AB9540_VAUX1SEL, | ||
| 130 | AB9540_VAUX2SEL, | ||
| 131 | AB9540_VRF1VAUX3SEL, | ||
| 132 | AB9540_REGUCTRL2SPARE, | ||
| 133 | AB9540_VAUX4REQCTRL, | ||
| 134 | AB9540_VAUX4REGU, | ||
| 135 | AB9540_VAUX4SEL, | ||
| 136 | AB9540_REGUCTRLDISCH, | ||
| 137 | AB9540_REGUCTRLDISCH2, | ||
| 138 | AB9540_REGUCTRLDISCH3, | ||
| 139 | AB9540_NUM_REGULATOR_REGISTERS, | ||
| 140 | }; | ||
| 141 | |||
| 74 | #endif | 142 | #endif |
