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 |