diff options
Diffstat (limited to 'drivers/mfd')
42 files changed, 3916 insertions, 1182 deletions
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 1489c3540f96..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 | ||
@@ -848,8 +898,9 @@ config MCP_SA11X0 | |||
848 | 898 | ||
849 | # Chip drivers | 899 | # Chip drivers |
850 | config MCP_UCB1200 | 900 | config MCP_UCB1200 |
851 | tristate "Support for UCB1200 / UCB1300" | 901 | bool "Support for UCB1200 / UCB1300" |
852 | depends on MCP | 902 | depends on MCP_SA11X0 |
903 | select MCP | ||
853 | 904 | ||
854 | config MCP_UCB1200_TS | 905 | config MCP_UCB1200_TS |
855 | tristate "Touchscreen interface support" | 906 | tristate "Touchscreen interface support" |
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/mcp-core.c b/drivers/mfd/mcp-core.c index 32c82de81ada..62e5e3617eb0 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c | |||
@@ -19,8 +19,6 @@ | |||
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/mfd/mcp.h> | 20 | #include <linux/mfd/mcp.h> |
21 | 21 | ||
22 | #include <mach/dma.h> | ||
23 | |||
24 | 22 | ||
25 | #define to_mcp(d) container_of(d, struct mcp, attached_device) | 23 | #define to_mcp(d) container_of(d, struct mcp, attached_device) |
26 | #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) | 24 | #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) |
@@ -47,39 +45,11 @@ static int mcp_bus_remove(struct device *dev) | |||
47 | return 0; | 45 | return 0; |
48 | } | 46 | } |
49 | 47 | ||
50 | static int mcp_bus_suspend(struct device *dev, pm_message_t state) | ||
51 | { | ||
52 | struct mcp *mcp = to_mcp(dev); | ||
53 | int ret = 0; | ||
54 | |||
55 | if (dev->driver) { | ||
56 | struct mcp_driver *drv = to_mcp_driver(dev->driver); | ||
57 | |||
58 | ret = drv->suspend(mcp, state); | ||
59 | } | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static int mcp_bus_resume(struct device *dev) | ||
64 | { | ||
65 | struct mcp *mcp = to_mcp(dev); | ||
66 | int ret = 0; | ||
67 | |||
68 | if (dev->driver) { | ||
69 | struct mcp_driver *drv = to_mcp_driver(dev->driver); | ||
70 | |||
71 | ret = drv->resume(mcp); | ||
72 | } | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | static struct bus_type mcp_bus_type = { | 48 | static struct bus_type mcp_bus_type = { |
77 | .name = "mcp", | 49 | .name = "mcp", |
78 | .match = mcp_bus_match, | 50 | .match = mcp_bus_match, |
79 | .probe = mcp_bus_probe, | 51 | .probe = mcp_bus_probe, |
80 | .remove = mcp_bus_remove, | 52 | .remove = mcp_bus_remove, |
81 | .suspend = mcp_bus_suspend, | ||
82 | .resume = mcp_bus_resume, | ||
83 | }; | 53 | }; |
84 | 54 | ||
85 | /** | 55 | /** |
@@ -207,6 +177,7 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) | |||
207 | mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL); | 177 | mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL); |
208 | if (mcp) { | 178 | if (mcp) { |
209 | spin_lock_init(&mcp->lock); | 179 | spin_lock_init(&mcp->lock); |
180 | device_initialize(&mcp->attached_device); | ||
210 | mcp->attached_device.parent = parent; | 181 | mcp->attached_device.parent = parent; |
211 | mcp->attached_device.bus = &mcp_bus_type; | 182 | mcp->attached_device.bus = &mcp_bus_type; |
212 | mcp->attached_device.dma_mask = parent->dma_mask; | 183 | mcp->attached_device.dma_mask = parent->dma_mask; |
@@ -216,18 +187,25 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) | |||
216 | } | 187 | } |
217 | EXPORT_SYMBOL(mcp_host_alloc); | 188 | EXPORT_SYMBOL(mcp_host_alloc); |
218 | 189 | ||
219 | int mcp_host_register(struct mcp *mcp) | 190 | int mcp_host_add(struct mcp *mcp, void *pdata) |
220 | { | 191 | { |
192 | mcp->attached_device.platform_data = pdata; | ||
221 | dev_set_name(&mcp->attached_device, "mcp0"); | 193 | dev_set_name(&mcp->attached_device, "mcp0"); |
222 | return device_register(&mcp->attached_device); | 194 | return device_add(&mcp->attached_device); |
195 | } | ||
196 | EXPORT_SYMBOL(mcp_host_add); | ||
197 | |||
198 | void mcp_host_del(struct mcp *mcp) | ||
199 | { | ||
200 | device_del(&mcp->attached_device); | ||
223 | } | 201 | } |
224 | EXPORT_SYMBOL(mcp_host_register); | 202 | EXPORT_SYMBOL(mcp_host_del); |
225 | 203 | ||
226 | void mcp_host_unregister(struct mcp *mcp) | 204 | void mcp_host_free(struct mcp *mcp) |
227 | { | 205 | { |
228 | device_unregister(&mcp->attached_device); | 206 | put_device(&mcp->attached_device); |
229 | } | 207 | } |
230 | EXPORT_SYMBOL(mcp_host_unregister); | 208 | EXPORT_SYMBOL(mcp_host_free); |
231 | 209 | ||
232 | int mcp_driver_register(struct mcp_driver *mcpdrv) | 210 | int mcp_driver_register(struct mcp_driver *mcpdrv) |
233 | { | 211 | { |
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 4a27c2b9a891..c54e244ca0cf 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c | |||
@@ -13,50 +13,60 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/io.h> | ||
16 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/pm.h> | ||
21 | #include <linux/mfd/mcp.h> | 23 | #include <linux/mfd/mcp.h> |
22 | 24 | ||
23 | #include <mach/dma.h> | ||
24 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
25 | #include <asm/mach-types.h> | 26 | #include <asm/mach-types.h> |
26 | #include <mach/mcp.h> | 27 | #include <mach/mcp.h> |
27 | 28 | ||
28 | #include <mach/assabet.h> | 29 | #define DRIVER_NAME "sa11x0-mcp" |
29 | |||
30 | 30 | ||
31 | struct mcp_sa11x0 { | 31 | struct mcp_sa11x0 { |
32 | u32 mccr0; | 32 | void __iomem *base0; |
33 | u32 mccr1; | 33 | void __iomem *base1; |
34 | u32 mccr0; | ||
35 | u32 mccr1; | ||
34 | }; | 36 | }; |
35 | 37 | ||
38 | /* Register offsets */ | ||
39 | #define MCCR0(m) ((m)->base0 + 0x00) | ||
40 | #define MCDR0(m) ((m)->base0 + 0x08) | ||
41 | #define MCDR1(m) ((m)->base0 + 0x0c) | ||
42 | #define MCDR2(m) ((m)->base0 + 0x10) | ||
43 | #define MCSR(m) ((m)->base0 + 0x18) | ||
44 | #define MCCR1(m) ((m)->base1 + 0x00) | ||
45 | |||
36 | #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) | 46 | #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) |
37 | 47 | ||
38 | static void | 48 | static void |
39 | mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) | 49 | mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) |
40 | { | 50 | { |
41 | unsigned int mccr0; | 51 | struct mcp_sa11x0 *m = priv(mcp); |
42 | 52 | ||
43 | divisor /= 32; | 53 | divisor /= 32; |
44 | 54 | ||
45 | mccr0 = Ser4MCCR0 & ~0x00007f00; | 55 | m->mccr0 &= ~0x00007f00; |
46 | mccr0 |= divisor << 8; | 56 | m->mccr0 |= divisor << 8; |
47 | Ser4MCCR0 = mccr0; | 57 | writel_relaxed(m->mccr0, MCCR0(m)); |
48 | } | 58 | } |
49 | 59 | ||
50 | static void | 60 | static void |
51 | mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) | 61 | mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) |
52 | { | 62 | { |
53 | unsigned int mccr0; | 63 | struct mcp_sa11x0 *m = priv(mcp); |
54 | 64 | ||
55 | divisor /= 32; | 65 | divisor /= 32; |
56 | 66 | ||
57 | mccr0 = Ser4MCCR0 & ~0x0000007f; | 67 | m->mccr0 &= ~0x0000007f; |
58 | mccr0 |= divisor; | 68 | m->mccr0 |= divisor; |
59 | Ser4MCCR0 = mccr0; | 69 | writel_relaxed(m->mccr0, MCCR0(m)); |
60 | } | 70 | } |
61 | 71 | ||
62 | /* | 72 | /* |
@@ -68,14 +78,15 @@ mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) | |||
68 | static void | 78 | static void |
69 | mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) | 79 | mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) |
70 | { | 80 | { |
81 | struct mcp_sa11x0 *m = priv(mcp); | ||
71 | int ret = -ETIME; | 82 | int ret = -ETIME; |
72 | int i; | 83 | int i; |
73 | 84 | ||
74 | Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); | 85 | writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m)); |
75 | 86 | ||
76 | for (i = 0; i < 2; i++) { | 87 | for (i = 0; i < 2; i++) { |
77 | udelay(mcp->rw_timeout); | 88 | udelay(mcp->rw_timeout); |
78 | if (Ser4MCSR & MCSR_CWC) { | 89 | if (readl_relaxed(MCSR(m)) & MCSR_CWC) { |
79 | ret = 0; | 90 | ret = 0; |
80 | break; | 91 | break; |
81 | } | 92 | } |
@@ -94,15 +105,16 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) | |||
94 | static unsigned int | 105 | static unsigned int |
95 | mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) | 106 | mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) |
96 | { | 107 | { |
108 | struct mcp_sa11x0 *m = priv(mcp); | ||
97 | int ret = -ETIME; | 109 | int ret = -ETIME; |
98 | int i; | 110 | int i; |
99 | 111 | ||
100 | Ser4MCDR2 = reg << 17 | MCDR2_Rd; | 112 | writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m)); |
101 | 113 | ||
102 | for (i = 0; i < 2; i++) { | 114 | for (i = 0; i < 2; i++) { |
103 | udelay(mcp->rw_timeout); | 115 | udelay(mcp->rw_timeout); |
104 | if (Ser4MCSR & MCSR_CRC) { | 116 | if (readl_relaxed(MCSR(m)) & MCSR_CRC) { |
105 | ret = Ser4MCDR2 & 0xffff; | 117 | ret = readl_relaxed(MCDR2(m)) & 0xffff; |
106 | break; | 118 | break; |
107 | } | 119 | } |
108 | } | 120 | } |
@@ -115,13 +127,19 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) | |||
115 | 127 | ||
116 | static void mcp_sa11x0_enable(struct mcp *mcp) | 128 | static void mcp_sa11x0_enable(struct mcp *mcp) |
117 | { | 129 | { |
118 | Ser4MCSR = -1; | 130 | struct mcp_sa11x0 *m = priv(mcp); |
119 | Ser4MCCR0 |= MCCR0_MCE; | 131 | |
132 | writel(-1, MCSR(m)); | ||
133 | m->mccr0 |= MCCR0_MCE; | ||
134 | writel_relaxed(m->mccr0, MCCR0(m)); | ||
120 | } | 135 | } |
121 | 136 | ||
122 | static void mcp_sa11x0_disable(struct mcp *mcp) | 137 | static void mcp_sa11x0_disable(struct mcp *mcp) |
123 | { | 138 | { |
124 | Ser4MCCR0 &= ~MCCR0_MCE; | 139 | struct mcp_sa11x0 *m = priv(mcp); |
140 | |||
141 | m->mccr0 &= ~MCCR0_MCE; | ||
142 | writel_relaxed(m->mccr0, MCCR0(m)); | ||
125 | } | 143 | } |
126 | 144 | ||
127 | /* | 145 | /* |
@@ -136,55 +154,64 @@ static struct mcp_ops mcp_sa11x0 = { | |||
136 | .disable = mcp_sa11x0_disable, | 154 | .disable = mcp_sa11x0_disable, |
137 | }; | 155 | }; |
138 | 156 | ||
139 | static int mcp_sa11x0_probe(struct platform_device *pdev) | 157 | static int mcp_sa11x0_probe(struct platform_device *dev) |
140 | { | 158 | { |
141 | struct mcp_plat_data *data = pdev->dev.platform_data; | 159 | struct mcp_plat_data *data = dev->dev.platform_data; |
160 | struct resource *mem0, *mem1; | ||
161 | struct mcp_sa11x0 *m; | ||
142 | struct mcp *mcp; | 162 | struct mcp *mcp; |
143 | int ret; | 163 | int ret; |
144 | 164 | ||
145 | if (!data) | 165 | if (!data) |
146 | return -ENODEV; | 166 | return -ENODEV; |
147 | 167 | ||
148 | if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) | 168 | mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); |
149 | return -EBUSY; | 169 | mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); |
170 | if (!mem0 || !mem1) | ||
171 | return -ENXIO; | ||
172 | |||
173 | if (!request_mem_region(mem0->start, resource_size(mem0), | ||
174 | DRIVER_NAME)) { | ||
175 | ret = -EBUSY; | ||
176 | goto err_mem0; | ||
177 | } | ||
150 | 178 | ||
151 | mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0)); | 179 | if (!request_mem_region(mem1->start, resource_size(mem1), |
180 | DRIVER_NAME)) { | ||
181 | ret = -EBUSY; | ||
182 | goto err_mem1; | ||
183 | } | ||
184 | |||
185 | mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0)); | ||
152 | if (!mcp) { | 186 | if (!mcp) { |
153 | ret = -ENOMEM; | 187 | ret = -ENOMEM; |
154 | goto release; | 188 | goto err_alloc; |
155 | } | 189 | } |
156 | 190 | ||
157 | mcp->owner = THIS_MODULE; | 191 | mcp->owner = THIS_MODULE; |
158 | mcp->ops = &mcp_sa11x0; | 192 | mcp->ops = &mcp_sa11x0; |
159 | mcp->sclk_rate = data->sclk_rate; | 193 | mcp->sclk_rate = data->sclk_rate; |
160 | mcp->dma_audio_rd = DMA_Ser4MCP0Rd; | ||
161 | mcp->dma_audio_wr = DMA_Ser4MCP0Wr; | ||
162 | mcp->dma_telco_rd = DMA_Ser4MCP1Rd; | ||
163 | mcp->dma_telco_wr = DMA_Ser4MCP1Wr; | ||
164 | mcp->gpio_base = data->gpio_base; | ||
165 | 194 | ||
166 | platform_set_drvdata(pdev, mcp); | 195 | m = priv(mcp); |
196 | m->mccr0 = data->mccr0 | 0x7f7f; | ||
197 | m->mccr1 = data->mccr1; | ||
167 | 198 | ||
168 | if (machine_is_assabet()) { | 199 | m->base0 = ioremap(mem0->start, resource_size(mem0)); |
169 | ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); | 200 | m->base1 = ioremap(mem1->start, resource_size(mem1)); |
201 | if (!m->base0 || !m->base1) { | ||
202 | ret = -ENOMEM; | ||
203 | goto err_ioremap; | ||
170 | } | 204 | } |
171 | 205 | ||
172 | /* | 206 | platform_set_drvdata(dev, mcp); |
173 | * Setup the PPC unit correctly. | ||
174 | */ | ||
175 | PPDR &= ~PPC_RXD4; | ||
176 | PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; | ||
177 | PSDR |= PPC_RXD4; | ||
178 | PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); | ||
179 | PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); | ||
180 | 207 | ||
181 | /* | 208 | /* |
182 | * Initialise device. Note that we initially | 209 | * Initialise device. Note that we initially |
183 | * set the sampling rate to minimum. | 210 | * set the sampling rate to minimum. |
184 | */ | 211 | */ |
185 | Ser4MCSR = -1; | 212 | writel_relaxed(-1, MCSR(m)); |
186 | Ser4MCCR1 = data->mccr1; | 213 | writel_relaxed(m->mccr1, MCCR1(m)); |
187 | Ser4MCCR0 = data->mccr0 | 0x7f7f; | 214 | writel_relaxed(m->mccr0, MCCR0(m)); |
188 | 215 | ||
189 | /* | 216 | /* |
190 | * Calculate the read/write timeout (us) from the bit clock | 217 | * Calculate the read/write timeout (us) from the bit clock |
@@ -194,62 +221,90 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) | |||
194 | mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / | 221 | mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / |
195 | mcp->sclk_rate; | 222 | mcp->sclk_rate; |
196 | 223 | ||
197 | ret = mcp_host_register(mcp); | 224 | ret = mcp_host_add(mcp, data->codec_pdata); |
198 | if (ret == 0) | 225 | if (ret == 0) |
199 | goto out; | 226 | return 0; |
200 | 227 | ||
201 | release: | 228 | platform_set_drvdata(dev, NULL); |
202 | release_mem_region(0x80060000, 0x60); | ||
203 | platform_set_drvdata(pdev, NULL); | ||
204 | 229 | ||
205 | out: | 230 | err_ioremap: |
231 | iounmap(m->base1); | ||
232 | iounmap(m->base0); | ||
233 | mcp_host_free(mcp); | ||
234 | err_alloc: | ||
235 | release_mem_region(mem1->start, resource_size(mem1)); | ||
236 | err_mem1: | ||
237 | release_mem_region(mem0->start, resource_size(mem0)); | ||
238 | err_mem0: | ||
206 | return ret; | 239 | return ret; |
207 | } | 240 | } |
208 | 241 | ||
209 | static int mcp_sa11x0_remove(struct platform_device *dev) | 242 | static int mcp_sa11x0_remove(struct platform_device *dev) |
210 | { | 243 | { |
211 | struct mcp *mcp = platform_get_drvdata(dev); | 244 | struct mcp *mcp = platform_get_drvdata(dev); |
245 | struct mcp_sa11x0 *m = priv(mcp); | ||
246 | struct resource *mem0, *mem1; | ||
247 | |||
248 | if (m->mccr0 & MCCR0_MCE) | ||
249 | dev_warn(&dev->dev, | ||
250 | "device left active (missing disable call?)\n"); | ||
251 | |||
252 | mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
253 | mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); | ||
212 | 254 | ||
213 | platform_set_drvdata(dev, NULL); | 255 | platform_set_drvdata(dev, NULL); |
214 | mcp_host_unregister(mcp); | 256 | mcp_host_del(mcp); |
215 | release_mem_region(0x80060000, 0x60); | 257 | iounmap(m->base1); |
258 | iounmap(m->base0); | ||
259 | mcp_host_free(mcp); | ||
260 | release_mem_region(mem1->start, resource_size(mem1)); | ||
261 | release_mem_region(mem0->start, resource_size(mem0)); | ||
216 | 262 | ||
217 | return 0; | 263 | return 0; |
218 | } | 264 | } |
219 | 265 | ||
220 | static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state) | 266 | #ifdef CONFIG_PM_SLEEP |
267 | static int mcp_sa11x0_suspend(struct device *dev) | ||
221 | { | 268 | { |
222 | struct mcp *mcp = platform_get_drvdata(dev); | 269 | struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev)); |
270 | |||
271 | if (m->mccr0 & MCCR0_MCE) | ||
272 | dev_warn(dev, "device left active (missing disable call?)\n"); | ||
223 | 273 | ||
224 | priv(mcp)->mccr0 = Ser4MCCR0; | 274 | writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m)); |
225 | priv(mcp)->mccr1 = Ser4MCCR1; | ||
226 | Ser4MCCR0 &= ~MCCR0_MCE; | ||
227 | 275 | ||
228 | return 0; | 276 | return 0; |
229 | } | 277 | } |
230 | 278 | ||
231 | static int mcp_sa11x0_resume(struct platform_device *dev) | 279 | static int mcp_sa11x0_resume(struct device *dev) |
232 | { | 280 | { |
233 | struct mcp *mcp = platform_get_drvdata(dev); | 281 | struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev)); |
234 | 282 | ||
235 | Ser4MCCR1 = priv(mcp)->mccr1; | 283 | writel_relaxed(m->mccr1, MCCR1(m)); |
236 | Ser4MCCR0 = priv(mcp)->mccr0; | 284 | writel_relaxed(m->mccr0, MCCR0(m)); |
237 | 285 | ||
238 | return 0; | 286 | return 0; |
239 | } | 287 | } |
240 | 288 | #endif | |
241 | /* | 289 | |
242 | * The driver for the SA11x0 MCP port. | 290 | static const struct dev_pm_ops mcp_sa11x0_pm_ops = { |
243 | */ | 291 | #ifdef CONFIG_PM_SLEEP |
244 | MODULE_ALIAS("platform:sa11x0-mcp"); | 292 | .suspend = mcp_sa11x0_suspend, |
293 | .freeze = mcp_sa11x0_suspend, | ||
294 | .poweroff = mcp_sa11x0_suspend, | ||
295 | .resume_noirq = mcp_sa11x0_resume, | ||
296 | .thaw_noirq = mcp_sa11x0_resume, | ||
297 | .restore_noirq = mcp_sa11x0_resume, | ||
298 | #endif | ||
299 | }; | ||
245 | 300 | ||
246 | static struct platform_driver mcp_sa11x0_driver = { | 301 | static struct platform_driver mcp_sa11x0_driver = { |
247 | .probe = mcp_sa11x0_probe, | 302 | .probe = mcp_sa11x0_probe, |
248 | .remove = mcp_sa11x0_remove, | 303 | .remove = mcp_sa11x0_remove, |
249 | .suspend = mcp_sa11x0_suspend, | ||
250 | .resume = mcp_sa11x0_resume, | ||
251 | .driver = { | 304 | .driver = { |
252 | .name = "sa11x0-mcp", | 305 | .name = DRIVER_NAME, |
306 | .owner = THIS_MODULE, | ||
307 | .pm = &mcp_sa11x0_pm_ops, | ||
253 | }, | 308 | }, |
254 | }; | 309 | }; |
255 | 310 | ||
@@ -258,6 +313,7 @@ static struct platform_driver mcp_sa11x0_driver = { | |||
258 | */ | 313 | */ |
259 | module_platform_driver(mcp_sa11x0_driver); | 314 | module_platform_driver(mcp_sa11x0_driver); |
260 | 315 | ||
316 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
261 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); | 317 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); |
262 | MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); | 318 | MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); |
263 | MODULE_LICENSE("GPL"); | 319 | MODULE_LICENSE("GPL"); |
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/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c index cea9da60850d..b63c0756a669 100644 --- a/drivers/mfd/ucb1x00-assabet.c +++ b/drivers/mfd/ucb1x00-assabet.c | |||
@@ -11,14 +11,15 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/device.h> | ||
15 | #include <linux/err.h> | ||
14 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/gpio_keys.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/platform_device.h> | ||
15 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
16 | #include <linux/device.h> | ||
17 | #include <linux/mfd/ucb1x00.h> | 21 | #include <linux/mfd/ucb1x00.h> |
18 | 22 | ||
19 | #include <mach/dma.h> | ||
20 | |||
21 | |||
22 | #define UCB1X00_ATTR(name,input)\ | 23 | #define UCB1X00_ATTR(name,input)\ |
23 | static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ | 24 | static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ |
24 | char *buf) \ | 25 | char *buf) \ |
@@ -38,14 +39,45 @@ UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2); | |||
38 | 39 | ||
39 | static int ucb1x00_assabet_add(struct ucb1x00_dev *dev) | 40 | static int ucb1x00_assabet_add(struct ucb1x00_dev *dev) |
40 | { | 41 | { |
41 | device_create_file(&dev->ucb->dev, &dev_attr_vbatt); | 42 | struct ucb1x00 *ucb = dev->ucb; |
42 | device_create_file(&dev->ucb->dev, &dev_attr_vcharger); | 43 | struct platform_device *pdev; |
43 | device_create_file(&dev->ucb->dev, &dev_attr_batt_temp); | 44 | struct gpio_keys_platform_data keys; |
45 | static struct gpio_keys_button buttons[6]; | ||
46 | unsigned i; | ||
47 | |||
48 | memset(buttons, 0, sizeof(buttons)); | ||
49 | memset(&keys, 0, sizeof(keys)); | ||
50 | |||
51 | for (i = 0; i < ARRAY_SIZE(buttons); i++) { | ||
52 | buttons[i].code = BTN_0 + i; | ||
53 | buttons[i].gpio = ucb->gpio.base + i; | ||
54 | buttons[i].type = EV_KEY; | ||
55 | buttons[i].can_disable = true; | ||
56 | } | ||
57 | |||
58 | keys.buttons = buttons; | ||
59 | keys.nbuttons = ARRAY_SIZE(buttons); | ||
60 | keys.poll_interval = 50; | ||
61 | keys.name = "ucb1x00"; | ||
62 | |||
63 | pdev = platform_device_register_data(&ucb->dev, "gpio-keys", -1, | ||
64 | &keys, sizeof(keys)); | ||
65 | |||
66 | device_create_file(&ucb->dev, &dev_attr_vbatt); | ||
67 | device_create_file(&ucb->dev, &dev_attr_vcharger); | ||
68 | device_create_file(&ucb->dev, &dev_attr_batt_temp); | ||
69 | |||
70 | dev->priv = pdev; | ||
44 | return 0; | 71 | return 0; |
45 | } | 72 | } |
46 | 73 | ||
47 | static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev) | 74 | static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev) |
48 | { | 75 | { |
76 | struct platform_device *pdev = dev->priv; | ||
77 | |||
78 | if (!IS_ERR(pdev)) | ||
79 | platform_device_unregister(pdev); | ||
80 | |||
49 | device_remove_file(&dev->ucb->dev, &dev_attr_batt_temp); | 81 | device_remove_file(&dev->ucb->dev, &dev_attr_batt_temp); |
50 | device_remove_file(&dev->ucb->dev, &dev_attr_vcharger); | 82 | device_remove_file(&dev->ucb->dev, &dev_attr_vcharger); |
51 | device_remove_file(&dev->ucb->dev, &dev_attr_vbatt); | 83 | device_remove_file(&dev->ucb->dev, &dev_attr_vbatt); |
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index febc90cdef7e..70f02daeb22a 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c | |||
@@ -23,14 +23,12 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/irq.h> | ||
26 | #include <linux/device.h> | 27 | #include <linux/device.h> |
27 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
28 | #include <linux/mfd/ucb1x00.h> | 29 | #include <linux/mfd/ucb1x00.h> |
30 | #include <linux/pm.h> | ||
29 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
30 | #include <linux/semaphore.h> | ||
31 | |||
32 | #include <mach/dma.h> | ||
33 | #include <mach/hardware.h> | ||
34 | 32 | ||
35 | static DEFINE_MUTEX(ucb1x00_mutex); | 33 | static DEFINE_MUTEX(ucb1x00_mutex); |
36 | static LIST_HEAD(ucb1x00_drivers); | 34 | static LIST_HEAD(ucb1x00_drivers); |
@@ -102,7 +100,7 @@ void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear) | |||
102 | * ucb1x00_enable must have been called to enable the comms | 100 | * ucb1x00_enable must have been called to enable the comms |
103 | * before using this function. | 101 | * before using this function. |
104 | * | 102 | * |
105 | * This function does not take any semaphores or spinlocks. | 103 | * This function does not take any mutexes or spinlocks. |
106 | */ | 104 | */ |
107 | unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) | 105 | unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) |
108 | { | 106 | { |
@@ -120,14 +118,22 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
120 | else | 118 | else |
121 | ucb->io_out &= ~(1 << offset); | 119 | ucb->io_out &= ~(1 << offset); |
122 | 120 | ||
121 | ucb1x00_enable(ucb); | ||
123 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); | 122 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); |
123 | ucb1x00_disable(ucb); | ||
124 | spin_unlock_irqrestore(&ucb->io_lock, flags); | 124 | spin_unlock_irqrestore(&ucb->io_lock, flags); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) | 127 | static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) |
128 | { | 128 | { |
129 | struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); | 129 | struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); |
130 | return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset); | 130 | unsigned val; |
131 | |||
132 | ucb1x00_enable(ucb); | ||
133 | val = ucb1x00_reg_read(ucb, UCB_IO_DATA); | ||
134 | ucb1x00_disable(ucb); | ||
135 | |||
136 | return val & (1 << offset); | ||
131 | } | 137 | } |
132 | 138 | ||
133 | static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 139 | static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
@@ -137,7 +143,9 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | |||
137 | 143 | ||
138 | spin_lock_irqsave(&ucb->io_lock, flags); | 144 | spin_lock_irqsave(&ucb->io_lock, flags); |
139 | ucb->io_dir &= ~(1 << offset); | 145 | ucb->io_dir &= ~(1 << offset); |
146 | ucb1x00_enable(ucb); | ||
140 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); | 147 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); |
148 | ucb1x00_disable(ucb); | ||
141 | spin_unlock_irqrestore(&ucb->io_lock, flags); | 149 | spin_unlock_irqrestore(&ucb->io_lock, flags); |
142 | 150 | ||
143 | return 0; | 151 | return 0; |
@@ -157,6 +165,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
157 | else | 165 | else |
158 | ucb->io_out &= ~mask; | 166 | ucb->io_out &= ~mask; |
159 | 167 | ||
168 | ucb1x00_enable(ucb); | ||
160 | if (old != ucb->io_out) | 169 | if (old != ucb->io_out) |
161 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); | 170 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); |
162 | 171 | ||
@@ -164,11 +173,19 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
164 | ucb->io_dir |= mask; | 173 | ucb->io_dir |= mask; |
165 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); | 174 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); |
166 | } | 175 | } |
176 | ucb1x00_disable(ucb); | ||
167 | spin_unlock_irqrestore(&ucb->io_lock, flags); | 177 | spin_unlock_irqrestore(&ucb->io_lock, flags); |
168 | 178 | ||
169 | return 0; | 179 | return 0; |
170 | } | 180 | } |
171 | 181 | ||
182 | static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset) | ||
183 | { | ||
184 | struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); | ||
185 | |||
186 | return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO; | ||
187 | } | ||
188 | |||
172 | /* | 189 | /* |
173 | * UCB1300 data sheet says we must: | 190 | * UCB1300 data sheet says we must: |
174 | * 1. enable ADC => 5us (including reference startup time) | 191 | * 1. enable ADC => 5us (including reference startup time) |
@@ -186,7 +203,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
186 | * Any code wishing to use the ADC converter must call this | 203 | * Any code wishing to use the ADC converter must call this |
187 | * function prior to using it. | 204 | * function prior to using it. |
188 | * | 205 | * |
189 | * This function takes the ADC semaphore to prevent two or more | 206 | * This function takes the ADC mutex to prevent two or more |
190 | * concurrent uses, and therefore may sleep. As a result, it | 207 | * concurrent uses, and therefore may sleep. As a result, it |
191 | * can only be called from process context, not interrupt | 208 | * can only be called from process context, not interrupt |
192 | * context. | 209 | * context. |
@@ -196,7 +213,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
196 | */ | 213 | */ |
197 | void ucb1x00_adc_enable(struct ucb1x00 *ucb) | 214 | void ucb1x00_adc_enable(struct ucb1x00 *ucb) |
198 | { | 215 | { |
199 | down(&ucb->adc_sem); | 216 | mutex_lock(&ucb->adc_mutex); |
200 | 217 | ||
201 | ucb->adc_cr |= UCB_ADC_ENA; | 218 | ucb->adc_cr |= UCB_ADC_ENA; |
202 | 219 | ||
@@ -218,7 +235,7 @@ void ucb1x00_adc_enable(struct ucb1x00 *ucb) | |||
218 | * complete (2 frames max without sync). | 235 | * complete (2 frames max without sync). |
219 | * | 236 | * |
220 | * If called for a synchronised ADC conversion, it may sleep | 237 | * If called for a synchronised ADC conversion, it may sleep |
221 | * with the ADC semaphore held. | 238 | * with the ADC mutex held. |
222 | */ | 239 | */ |
223 | unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) | 240 | unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) |
224 | { | 241 | { |
@@ -246,7 +263,7 @@ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) | |||
246 | * ucb1x00_adc_disable - disable the ADC converter | 263 | * ucb1x00_adc_disable - disable the ADC converter |
247 | * @ucb: UCB1x00 structure describing chip | 264 | * @ucb: UCB1x00 structure describing chip |
248 | * | 265 | * |
249 | * Disable the ADC converter and release the ADC semaphore. | 266 | * Disable the ADC converter and release the ADC mutex. |
250 | */ | 267 | */ |
251 | void ucb1x00_adc_disable(struct ucb1x00 *ucb) | 268 | void ucb1x00_adc_disable(struct ucb1x00 *ucb) |
252 | { | 269 | { |
@@ -254,7 +271,7 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb) | |||
254 | ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); | 271 | ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); |
255 | ucb1x00_disable(ucb); | 272 | ucb1x00_disable(ucb); |
256 | 273 | ||
257 | up(&ucb->adc_sem); | 274 | mutex_unlock(&ucb->adc_mutex); |
258 | } | 275 | } |
259 | 276 | ||
260 | /* | 277 | /* |
@@ -265,10 +282,9 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb) | |||
265 | * SIBCLK to talk to the chip. We leave the clock running until | 282 | * SIBCLK to talk to the chip. We leave the clock running until |
266 | * we have finished processing all interrupts from the chip. | 283 | * we have finished processing all interrupts from the chip. |
267 | */ | 284 | */ |
268 | static irqreturn_t ucb1x00_irq(int irqnr, void *devid) | 285 | static void ucb1x00_irq(unsigned int irq, struct irq_desc *desc) |
269 | { | 286 | { |
270 | struct ucb1x00 *ucb = devid; | 287 | struct ucb1x00 *ucb = irq_desc_get_handler_data(desc); |
271 | struct ucb1x00_irq *irq; | ||
272 | unsigned int isr, i; | 288 | unsigned int isr, i; |
273 | 289 | ||
274 | ucb1x00_enable(ucb); | 290 | ucb1x00_enable(ucb); |
@@ -276,157 +292,104 @@ static irqreturn_t ucb1x00_irq(int irqnr, void *devid) | |||
276 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); | 292 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); |
277 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); | 293 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); |
278 | 294 | ||
279 | for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++) | 295 | for (i = 0; i < 16 && isr; i++, isr >>= 1, irq++) |
280 | if (isr & 1 && irq->fn) | 296 | if (isr & 1) |
281 | irq->fn(i, irq->devid); | 297 | generic_handle_irq(ucb->irq_base + i); |
282 | ucb1x00_disable(ucb); | 298 | ucb1x00_disable(ucb); |
283 | |||
284 | return IRQ_HANDLED; | ||
285 | } | 299 | } |
286 | 300 | ||
287 | /** | 301 | static void ucb1x00_irq_update(struct ucb1x00 *ucb, unsigned mask) |
288 | * ucb1x00_hook_irq - hook a UCB1x00 interrupt | ||
289 | * @ucb: UCB1x00 structure describing chip | ||
290 | * @idx: interrupt index | ||
291 | * @fn: function to call when interrupt is triggered | ||
292 | * @devid: device id to pass to interrupt handler | ||
293 | * | ||
294 | * Hook the specified interrupt. You can only register one handler | ||
295 | * for each interrupt source. The interrupt source is not enabled | ||
296 | * by this function; use ucb1x00_enable_irq instead. | ||
297 | * | ||
298 | * Interrupt handlers will be called with other interrupts enabled. | ||
299 | * | ||
300 | * Returns zero on success, or one of the following errors: | ||
301 | * -EINVAL if the interrupt index is invalid | ||
302 | * -EBUSY if the interrupt has already been hooked | ||
303 | */ | ||
304 | int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid) | ||
305 | { | 302 | { |
306 | struct ucb1x00_irq *irq; | 303 | ucb1x00_enable(ucb); |
307 | int ret = -EINVAL; | 304 | if (ucb->irq_ris_enbl & mask) |
308 | 305 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | |
309 | if (idx < 16) { | 306 | ucb->irq_mask); |
310 | irq = ucb->irq_handler + idx; | 307 | if (ucb->irq_fal_enbl & mask) |
311 | ret = -EBUSY; | 308 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & |
312 | 309 | ucb->irq_mask); | |
313 | spin_lock_irq(&ucb->lock); | 310 | ucb1x00_disable(ucb); |
314 | if (irq->fn == NULL) { | ||
315 | irq->devid = devid; | ||
316 | irq->fn = fn; | ||
317 | ret = 0; | ||
318 | } | ||
319 | spin_unlock_irq(&ucb->lock); | ||
320 | } | ||
321 | return ret; | ||
322 | } | 311 | } |
323 | 312 | ||
324 | /** | 313 | static void ucb1x00_irq_noop(struct irq_data *data) |
325 | * ucb1x00_enable_irq - enable an UCB1x00 interrupt source | ||
326 | * @ucb: UCB1x00 structure describing chip | ||
327 | * @idx: interrupt index | ||
328 | * @edges: interrupt edges to enable | ||
329 | * | ||
330 | * Enable the specified interrupt to trigger on %UCB_RISING, | ||
331 | * %UCB_FALLING or both edges. The interrupt should have been | ||
332 | * hooked by ucb1x00_hook_irq. | ||
333 | */ | ||
334 | void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) | ||
335 | { | 314 | { |
336 | unsigned long flags; | 315 | } |
337 | 316 | ||
338 | if (idx < 16) { | 317 | static void ucb1x00_irq_mask(struct irq_data *data) |
339 | spin_lock_irqsave(&ucb->lock, flags); | 318 | { |
319 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); | ||
320 | unsigned mask = 1 << (data->irq - ucb->irq_base); | ||
340 | 321 | ||
341 | ucb1x00_enable(ucb); | 322 | raw_spin_lock(&ucb->irq_lock); |
342 | if (edges & UCB_RISING) { | 323 | ucb->irq_mask &= ~mask; |
343 | ucb->irq_ris_enbl |= 1 << idx; | 324 | ucb1x00_irq_update(ucb, mask); |
344 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); | 325 | raw_spin_unlock(&ucb->irq_lock); |
345 | } | ||
346 | if (edges & UCB_FALLING) { | ||
347 | ucb->irq_fal_enbl |= 1 << idx; | ||
348 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); | ||
349 | } | ||
350 | ucb1x00_disable(ucb); | ||
351 | spin_unlock_irqrestore(&ucb->lock, flags); | ||
352 | } | ||
353 | } | 326 | } |
354 | 327 | ||
355 | /** | 328 | static void ucb1x00_irq_unmask(struct irq_data *data) |
356 | * ucb1x00_disable_irq - disable an UCB1x00 interrupt source | ||
357 | * @ucb: UCB1x00 structure describing chip | ||
358 | * @edges: interrupt edges to disable | ||
359 | * | ||
360 | * Disable the specified interrupt triggering on the specified | ||
361 | * (%UCB_RISING, %UCB_FALLING or both) edges. | ||
362 | */ | ||
363 | void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) | ||
364 | { | 329 | { |
365 | unsigned long flags; | 330 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); |
331 | unsigned mask = 1 << (data->irq - ucb->irq_base); | ||
366 | 332 | ||
367 | if (idx < 16) { | 333 | raw_spin_lock(&ucb->irq_lock); |
368 | spin_lock_irqsave(&ucb->lock, flags); | 334 | ucb->irq_mask |= mask; |
369 | 335 | ucb1x00_irq_update(ucb, mask); | |
370 | ucb1x00_enable(ucb); | 336 | raw_spin_unlock(&ucb->irq_lock); |
371 | if (edges & UCB_RISING) { | ||
372 | ucb->irq_ris_enbl &= ~(1 << idx); | ||
373 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); | ||
374 | } | ||
375 | if (edges & UCB_FALLING) { | ||
376 | ucb->irq_fal_enbl &= ~(1 << idx); | ||
377 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); | ||
378 | } | ||
379 | ucb1x00_disable(ucb); | ||
380 | spin_unlock_irqrestore(&ucb->lock, flags); | ||
381 | } | ||
382 | } | 337 | } |
383 | 338 | ||
384 | /** | 339 | static int ucb1x00_irq_set_type(struct irq_data *data, unsigned int type) |
385 | * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt | ||
386 | * @ucb: UCB1x00 structure describing chip | ||
387 | * @idx: interrupt index | ||
388 | * @devid: device id. | ||
389 | * | ||
390 | * Disable the interrupt source and remove the handler. devid must | ||
391 | * match the devid passed when hooking the interrupt. | ||
392 | * | ||
393 | * Returns zero on success, or one of the following errors: | ||
394 | * -EINVAL if the interrupt index is invalid | ||
395 | * -ENOENT if devid does not match | ||
396 | */ | ||
397 | int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid) | ||
398 | { | 340 | { |
399 | struct ucb1x00_irq *irq; | 341 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); |
400 | int ret; | 342 | unsigned mask = 1 << (data->irq - ucb->irq_base); |
401 | 343 | ||
402 | if (idx >= 16) | 344 | raw_spin_lock(&ucb->irq_lock); |
403 | goto bad; | 345 | if (type & IRQ_TYPE_EDGE_RISING) |
346 | ucb->irq_ris_enbl |= mask; | ||
347 | else | ||
348 | ucb->irq_ris_enbl &= ~mask; | ||
404 | 349 | ||
405 | irq = ucb->irq_handler + idx; | 350 | if (type & IRQ_TYPE_EDGE_FALLING) |
406 | ret = -ENOENT; | 351 | ucb->irq_fal_enbl |= mask; |
352 | else | ||
353 | ucb->irq_fal_enbl &= ~mask; | ||
354 | if (ucb->irq_mask & mask) { | ||
355 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | ||
356 | ucb->irq_mask); | ||
357 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & | ||
358 | ucb->irq_mask); | ||
359 | } | ||
360 | raw_spin_unlock(&ucb->irq_lock); | ||
407 | 361 | ||
408 | spin_lock_irq(&ucb->lock); | 362 | return 0; |
409 | if (irq->devid == devid) { | 363 | } |
410 | ucb->irq_ris_enbl &= ~(1 << idx); | ||
411 | ucb->irq_fal_enbl &= ~(1 << idx); | ||
412 | 364 | ||
413 | ucb1x00_enable(ucb); | 365 | static int ucb1x00_irq_set_wake(struct irq_data *data, unsigned int on) |
414 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); | 366 | { |
415 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); | 367 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); |
416 | ucb1x00_disable(ucb); | 368 | struct ucb1x00_plat_data *pdata = ucb->mcp->attached_device.platform_data; |
369 | unsigned mask = 1 << (data->irq - ucb->irq_base); | ||
417 | 370 | ||
418 | irq->fn = NULL; | 371 | if (!pdata || !pdata->can_wakeup) |
419 | irq->devid = NULL; | 372 | return -EINVAL; |
420 | ret = 0; | ||
421 | } | ||
422 | spin_unlock_irq(&ucb->lock); | ||
423 | return ret; | ||
424 | 373 | ||
425 | bad: | 374 | raw_spin_lock(&ucb->irq_lock); |
426 | printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx); | 375 | if (on) |
427 | return -EINVAL; | 376 | ucb->irq_wake |= mask; |
377 | else | ||
378 | ucb->irq_wake &= ~mask; | ||
379 | raw_spin_unlock(&ucb->irq_lock); | ||
380 | |||
381 | return 0; | ||
428 | } | 382 | } |
429 | 383 | ||
384 | static struct irq_chip ucb1x00_irqchip = { | ||
385 | .name = "ucb1x00", | ||
386 | .irq_ack = ucb1x00_irq_noop, | ||
387 | .irq_mask = ucb1x00_irq_mask, | ||
388 | .irq_unmask = ucb1x00_irq_unmask, | ||
389 | .irq_set_type = ucb1x00_irq_set_type, | ||
390 | .irq_set_wake = ucb1x00_irq_set_wake, | ||
391 | }; | ||
392 | |||
430 | static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) | 393 | static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) |
431 | { | 394 | { |
432 | struct ucb1x00_dev *dev; | 395 | struct ucb1x00_dev *dev; |
@@ -440,8 +403,8 @@ static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) | |||
440 | ret = drv->add(dev); | 403 | ret = drv->add(dev); |
441 | 404 | ||
442 | if (ret == 0) { | 405 | if (ret == 0) { |
443 | list_add(&dev->dev_node, &ucb->devs); | 406 | list_add_tail(&dev->dev_node, &ucb->devs); |
444 | list_add(&dev->drv_node, &drv->devs); | 407 | list_add_tail(&dev->drv_node, &drv->devs); |
445 | } else { | 408 | } else { |
446 | kfree(dev); | 409 | kfree(dev); |
447 | } | 410 | } |
@@ -533,98 +496,126 @@ static struct class ucb1x00_class = { | |||
533 | 496 | ||
534 | static int ucb1x00_probe(struct mcp *mcp) | 497 | static int ucb1x00_probe(struct mcp *mcp) |
535 | { | 498 | { |
536 | struct ucb1x00 *ucb; | 499 | struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; |
537 | struct ucb1x00_driver *drv; | 500 | struct ucb1x00_driver *drv; |
538 | unsigned int id; | 501 | struct ucb1x00 *ucb; |
502 | unsigned id, i, irq_base; | ||
539 | int ret = -ENODEV; | 503 | int ret = -ENODEV; |
540 | int temp; | 504 | |
505 | /* Tell the platform to deassert the UCB1x00 reset */ | ||
506 | if (pdata && pdata->reset) | ||
507 | pdata->reset(UCB_RST_PROBE); | ||
541 | 508 | ||
542 | mcp_enable(mcp); | 509 | mcp_enable(mcp); |
543 | id = mcp_reg_read(mcp, UCB_ID); | 510 | id = mcp_reg_read(mcp, UCB_ID); |
511 | mcp_disable(mcp); | ||
544 | 512 | ||
545 | if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { | 513 | if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { |
546 | printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); | 514 | printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); |
547 | goto err_disable; | 515 | goto out; |
548 | } | 516 | } |
549 | 517 | ||
550 | ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL); | 518 | ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL); |
551 | ret = -ENOMEM; | 519 | ret = -ENOMEM; |
552 | if (!ucb) | 520 | if (!ucb) |
553 | goto err_disable; | 521 | goto out; |
554 | |||
555 | 522 | ||
523 | device_initialize(&ucb->dev); | ||
556 | ucb->dev.class = &ucb1x00_class; | 524 | ucb->dev.class = &ucb1x00_class; |
557 | ucb->dev.parent = &mcp->attached_device; | 525 | ucb->dev.parent = &mcp->attached_device; |
558 | dev_set_name(&ucb->dev, "ucb1x00"); | 526 | dev_set_name(&ucb->dev, "ucb1x00"); |
559 | 527 | ||
560 | spin_lock_init(&ucb->lock); | 528 | raw_spin_lock_init(&ucb->irq_lock); |
561 | spin_lock_init(&ucb->io_lock); | 529 | spin_lock_init(&ucb->io_lock); |
562 | sema_init(&ucb->adc_sem, 1); | 530 | mutex_init(&ucb->adc_mutex); |
563 | 531 | ||
564 | ucb->id = id; | 532 | ucb->id = id; |
565 | ucb->mcp = mcp; | 533 | ucb->mcp = mcp; |
534 | |||
535 | ret = device_add(&ucb->dev); | ||
536 | if (ret) | ||
537 | goto err_dev_add; | ||
538 | |||
539 | ucb1x00_enable(ucb); | ||
566 | ucb->irq = ucb1x00_detect_irq(ucb); | 540 | ucb->irq = ucb1x00_detect_irq(ucb); |
541 | ucb1x00_disable(ucb); | ||
567 | if (ucb->irq == NO_IRQ) { | 542 | if (ucb->irq == NO_IRQ) { |
568 | printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); | 543 | dev_err(&ucb->dev, "IRQ probe failed\n"); |
569 | ret = -ENODEV; | 544 | ret = -ENODEV; |
570 | goto err_free; | 545 | goto err_no_irq; |
571 | } | 546 | } |
572 | 547 | ||
573 | ucb->gpio.base = -1; | 548 | ucb->gpio.base = -1; |
574 | if (mcp->gpio_base != 0) { | 549 | irq_base = pdata ? pdata->irq_base : 0; |
550 | ucb->irq_base = irq_alloc_descs(-1, irq_base, 16, -1); | ||
551 | if (ucb->irq_base < 0) { | ||
552 | dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n", | ||
553 | ucb->irq_base); | ||
554 | goto err_irq_alloc; | ||
555 | } | ||
556 | |||
557 | for (i = 0; i < 16; i++) { | ||
558 | unsigned irq = ucb->irq_base + i; | ||
559 | |||
560 | irq_set_chip_and_handler(irq, &ucb1x00_irqchip, handle_edge_irq); | ||
561 | irq_set_chip_data(irq, ucb); | ||
562 | set_irq_flags(irq, IRQF_VALID | IRQ_NOREQUEST); | ||
563 | } | ||
564 | |||
565 | irq_set_irq_type(ucb->irq, IRQ_TYPE_EDGE_RISING); | ||
566 | irq_set_handler_data(ucb->irq, ucb); | ||
567 | irq_set_chained_handler(ucb->irq, ucb1x00_irq); | ||
568 | |||
569 | if (pdata && pdata->gpio_base) { | ||
575 | ucb->gpio.label = dev_name(&ucb->dev); | 570 | ucb->gpio.label = dev_name(&ucb->dev); |
576 | ucb->gpio.base = mcp->gpio_base; | 571 | ucb->gpio.dev = &ucb->dev; |
572 | ucb->gpio.owner = THIS_MODULE; | ||
573 | ucb->gpio.base = pdata->gpio_base; | ||
577 | ucb->gpio.ngpio = 10; | 574 | ucb->gpio.ngpio = 10; |
578 | ucb->gpio.set = ucb1x00_gpio_set; | 575 | ucb->gpio.set = ucb1x00_gpio_set; |
579 | ucb->gpio.get = ucb1x00_gpio_get; | 576 | ucb->gpio.get = ucb1x00_gpio_get; |
580 | ucb->gpio.direction_input = ucb1x00_gpio_direction_input; | 577 | ucb->gpio.direction_input = ucb1x00_gpio_direction_input; |
581 | ucb->gpio.direction_output = ucb1x00_gpio_direction_output; | 578 | ucb->gpio.direction_output = ucb1x00_gpio_direction_output; |
579 | ucb->gpio.to_irq = ucb1x00_to_irq; | ||
582 | ret = gpiochip_add(&ucb->gpio); | 580 | ret = gpiochip_add(&ucb->gpio); |
583 | if (ret) | 581 | if (ret) |
584 | goto err_free; | 582 | goto err_gpio_add; |
585 | } else | 583 | } else |
586 | dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); | 584 | dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); |
587 | 585 | ||
588 | ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, | ||
589 | "UCB1x00", ucb); | ||
590 | if (ret) { | ||
591 | printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", | ||
592 | ucb->irq, ret); | ||
593 | goto err_gpio; | ||
594 | } | ||
595 | |||
596 | mcp_set_drvdata(mcp, ucb); | 586 | mcp_set_drvdata(mcp, ucb); |
597 | 587 | ||
598 | ret = device_register(&ucb->dev); | 588 | if (pdata) |
599 | if (ret) | 589 | device_set_wakeup_capable(&ucb->dev, pdata->can_wakeup); |
600 | goto err_irq; | ||
601 | |||
602 | 590 | ||
603 | INIT_LIST_HEAD(&ucb->devs); | 591 | INIT_LIST_HEAD(&ucb->devs); |
604 | mutex_lock(&ucb1x00_mutex); | 592 | mutex_lock(&ucb1x00_mutex); |
605 | list_add(&ucb->node, &ucb1x00_devices); | 593 | list_add_tail(&ucb->node, &ucb1x00_devices); |
606 | list_for_each_entry(drv, &ucb1x00_drivers, node) { | 594 | list_for_each_entry(drv, &ucb1x00_drivers, node) { |
607 | ucb1x00_add_dev(ucb, drv); | 595 | ucb1x00_add_dev(ucb, drv); |
608 | } | 596 | } |
609 | mutex_unlock(&ucb1x00_mutex); | 597 | mutex_unlock(&ucb1x00_mutex); |
610 | 598 | ||
611 | goto out; | 599 | return ret; |
612 | 600 | ||
613 | err_irq: | 601 | err_gpio_add: |
614 | free_irq(ucb->irq, ucb); | 602 | irq_set_chained_handler(ucb->irq, NULL); |
615 | err_gpio: | 603 | err_irq_alloc: |
616 | if (ucb->gpio.base != -1) | 604 | if (ucb->irq_base > 0) |
617 | temp = gpiochip_remove(&ucb->gpio); | 605 | irq_free_descs(ucb->irq_base, 16); |
618 | err_free: | 606 | err_no_irq: |
619 | kfree(ucb); | 607 | device_del(&ucb->dev); |
620 | err_disable: | 608 | err_dev_add: |
621 | mcp_disable(mcp); | 609 | put_device(&ucb->dev); |
622 | out: | 610 | out: |
611 | if (pdata && pdata->reset) | ||
612 | pdata->reset(UCB_RST_PROBE_FAIL); | ||
623 | return ret; | 613 | return ret; |
624 | } | 614 | } |
625 | 615 | ||
626 | static void ucb1x00_remove(struct mcp *mcp) | 616 | static void ucb1x00_remove(struct mcp *mcp) |
627 | { | 617 | { |
618 | struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; | ||
628 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 619 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); |
629 | struct list_head *l, *n; | 620 | struct list_head *l, *n; |
630 | int ret; | 621 | int ret; |
@@ -643,8 +634,12 @@ static void ucb1x00_remove(struct mcp *mcp) | |||
643 | dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret); | 634 | dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret); |
644 | } | 635 | } |
645 | 636 | ||
646 | free_irq(ucb->irq, ucb); | 637 | irq_set_chained_handler(ucb->irq, NULL); |
638 | irq_free_descs(ucb->irq_base, 16); | ||
647 | device_unregister(&ucb->dev); | 639 | device_unregister(&ucb->dev); |
640 | |||
641 | if (pdata && pdata->reset) | ||
642 | pdata->reset(UCB_RST_REMOVE); | ||
648 | } | 643 | } |
649 | 644 | ||
650 | int ucb1x00_register_driver(struct ucb1x00_driver *drv) | 645 | int ucb1x00_register_driver(struct ucb1x00_driver *drv) |
@@ -653,7 +648,7 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv) | |||
653 | 648 | ||
654 | INIT_LIST_HEAD(&drv->devs); | 649 | INIT_LIST_HEAD(&drv->devs); |
655 | mutex_lock(&ucb1x00_mutex); | 650 | mutex_lock(&ucb1x00_mutex); |
656 | list_add(&drv->node, &ucb1x00_drivers); | 651 | list_add_tail(&drv->node, &ucb1x00_drivers); |
657 | list_for_each_entry(ucb, &ucb1x00_devices, node) { | 652 | list_for_each_entry(ucb, &ucb1x00_devices, node) { |
658 | ucb1x00_add_dev(ucb, drv); | 653 | ucb1x00_add_dev(ucb, drv); |
659 | } | 654 | } |
@@ -674,44 +669,86 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv) | |||
674 | mutex_unlock(&ucb1x00_mutex); | 669 | mutex_unlock(&ucb1x00_mutex); |
675 | } | 670 | } |
676 | 671 | ||
677 | static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) | 672 | static int ucb1x00_suspend(struct device *dev) |
678 | { | 673 | { |
679 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 674 | struct ucb1x00_plat_data *pdata = dev->platform_data; |
680 | struct ucb1x00_dev *dev; | 675 | struct ucb1x00 *ucb = dev_get_drvdata(dev); |
676 | struct ucb1x00_dev *udev; | ||
681 | 677 | ||
682 | mutex_lock(&ucb1x00_mutex); | 678 | mutex_lock(&ucb1x00_mutex); |
683 | list_for_each_entry(dev, &ucb->devs, dev_node) { | 679 | list_for_each_entry(udev, &ucb->devs, dev_node) { |
684 | if (dev->drv->suspend) | 680 | if (udev->drv->suspend) |
685 | dev->drv->suspend(dev, state); | 681 | udev->drv->suspend(udev); |
686 | } | 682 | } |
687 | mutex_unlock(&ucb1x00_mutex); | 683 | mutex_unlock(&ucb1x00_mutex); |
684 | |||
685 | if (ucb->irq_wake) { | ||
686 | unsigned long flags; | ||
687 | |||
688 | raw_spin_lock_irqsave(&ucb->irq_lock, flags); | ||
689 | ucb1x00_enable(ucb); | ||
690 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | ||
691 | ucb->irq_wake); | ||
692 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & | ||
693 | ucb->irq_wake); | ||
694 | ucb1x00_disable(ucb); | ||
695 | raw_spin_unlock_irqrestore(&ucb->irq_lock, flags); | ||
696 | |||
697 | enable_irq_wake(ucb->irq); | ||
698 | } else if (pdata && pdata->reset) | ||
699 | pdata->reset(UCB_RST_SUSPEND); | ||
700 | |||
688 | return 0; | 701 | return 0; |
689 | } | 702 | } |
690 | 703 | ||
691 | static int ucb1x00_resume(struct mcp *mcp) | 704 | static int ucb1x00_resume(struct device *dev) |
692 | { | 705 | { |
693 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 706 | struct ucb1x00_plat_data *pdata = dev->platform_data; |
694 | struct ucb1x00_dev *dev; | 707 | struct ucb1x00 *ucb = dev_get_drvdata(dev); |
708 | struct ucb1x00_dev *udev; | ||
709 | |||
710 | if (!ucb->irq_wake && pdata && pdata->reset) | ||
711 | pdata->reset(UCB_RST_RESUME); | ||
695 | 712 | ||
713 | ucb1x00_enable(ucb); | ||
696 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); | 714 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); |
697 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); | 715 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); |
716 | |||
717 | if (ucb->irq_wake) { | ||
718 | unsigned long flags; | ||
719 | |||
720 | raw_spin_lock_irqsave(&ucb->irq_lock, flags); | ||
721 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | ||
722 | ucb->irq_mask); | ||
723 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & | ||
724 | ucb->irq_mask); | ||
725 | raw_spin_unlock_irqrestore(&ucb->irq_lock, flags); | ||
726 | |||
727 | disable_irq_wake(ucb->irq); | ||
728 | } | ||
729 | ucb1x00_disable(ucb); | ||
730 | |||
698 | mutex_lock(&ucb1x00_mutex); | 731 | mutex_lock(&ucb1x00_mutex); |
699 | list_for_each_entry(dev, &ucb->devs, dev_node) { | 732 | list_for_each_entry(udev, &ucb->devs, dev_node) { |
700 | if (dev->drv->resume) | 733 | if (udev->drv->resume) |
701 | dev->drv->resume(dev); | 734 | udev->drv->resume(udev); |
702 | } | 735 | } |
703 | mutex_unlock(&ucb1x00_mutex); | 736 | mutex_unlock(&ucb1x00_mutex); |
704 | return 0; | 737 | return 0; |
705 | } | 738 | } |
706 | 739 | ||
740 | static const struct dev_pm_ops ucb1x00_pm_ops = { | ||
741 | SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume) | ||
742 | }; | ||
743 | |||
707 | static struct mcp_driver ucb1x00_driver = { | 744 | static struct mcp_driver ucb1x00_driver = { |
708 | .drv = { | 745 | .drv = { |
709 | .name = "ucb1x00", | 746 | .name = "ucb1x00", |
747 | .owner = THIS_MODULE, | ||
748 | .pm = &ucb1x00_pm_ops, | ||
710 | }, | 749 | }, |
711 | .probe = ucb1x00_probe, | 750 | .probe = ucb1x00_probe, |
712 | .remove = ucb1x00_remove, | 751 | .remove = ucb1x00_remove, |
713 | .suspend = ucb1x00_suspend, | ||
714 | .resume = ucb1x00_resume, | ||
715 | }; | 752 | }; |
716 | 753 | ||
717 | static int __init ucb1x00_init(void) | 754 | static int __init ucb1x00_init(void) |
@@ -742,14 +779,10 @@ EXPORT_SYMBOL(ucb1x00_adc_enable); | |||
742 | EXPORT_SYMBOL(ucb1x00_adc_read); | 779 | EXPORT_SYMBOL(ucb1x00_adc_read); |
743 | EXPORT_SYMBOL(ucb1x00_adc_disable); | 780 | EXPORT_SYMBOL(ucb1x00_adc_disable); |
744 | 781 | ||
745 | EXPORT_SYMBOL(ucb1x00_hook_irq); | ||
746 | EXPORT_SYMBOL(ucb1x00_free_irq); | ||
747 | EXPORT_SYMBOL(ucb1x00_enable_irq); | ||
748 | EXPORT_SYMBOL(ucb1x00_disable_irq); | ||
749 | |||
750 | EXPORT_SYMBOL(ucb1x00_register_driver); | 782 | EXPORT_SYMBOL(ucb1x00_register_driver); |
751 | EXPORT_SYMBOL(ucb1x00_unregister_driver); | 783 | EXPORT_SYMBOL(ucb1x00_unregister_driver); |
752 | 784 | ||
785 | MODULE_ALIAS("mcp:ucb1x00"); | ||
753 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); | 786 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); |
754 | MODULE_DESCRIPTION("UCB1x00 core driver"); | 787 | MODULE_DESCRIPTION("UCB1x00 core driver"); |
755 | MODULE_LICENSE("GPL"); | 788 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 63a3cbdfa3f3..1e0e20c0e082 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c | |||
@@ -20,8 +20,9 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/moduleparam.h> | 21 | #include <linux/moduleparam.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/smp.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/spinlock.h> | ||
25 | #include <linux/completion.h> | 26 | #include <linux/completion.h> |
26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
@@ -32,7 +33,6 @@ | |||
32 | #include <linux/kthread.h> | 33 | #include <linux/kthread.h> |
33 | #include <linux/mfd/ucb1x00.h> | 34 | #include <linux/mfd/ucb1x00.h> |
34 | 35 | ||
35 | #include <mach/dma.h> | ||
36 | #include <mach/collie.h> | 36 | #include <mach/collie.h> |
37 | #include <asm/mach-types.h> | 37 | #include <asm/mach-types.h> |
38 | 38 | ||
@@ -42,6 +42,8 @@ struct ucb1x00_ts { | |||
42 | struct input_dev *idev; | 42 | struct input_dev *idev; |
43 | struct ucb1x00 *ucb; | 43 | struct ucb1x00 *ucb; |
44 | 44 | ||
45 | spinlock_t irq_lock; | ||
46 | unsigned irq_disabled; | ||
45 | wait_queue_head_t irq_wait; | 47 | wait_queue_head_t irq_wait; |
46 | struct task_struct *rtask; | 48 | struct task_struct *rtask; |
47 | u16 x_res; | 49 | u16 x_res; |
@@ -238,7 +240,12 @@ static int ucb1x00_thread(void *_ts) | |||
238 | if (ucb1x00_ts_pen_down(ts)) { | 240 | if (ucb1x00_ts_pen_down(ts)) { |
239 | set_current_state(TASK_INTERRUPTIBLE); | 241 | set_current_state(TASK_INTERRUPTIBLE); |
240 | 242 | ||
241 | ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); | 243 | spin_lock_irq(&ts->irq_lock); |
244 | if (ts->irq_disabled) { | ||
245 | ts->irq_disabled = 0; | ||
246 | enable_irq(ts->ucb->irq_base + UCB_IRQ_TSPX); | ||
247 | } | ||
248 | spin_unlock_irq(&ts->irq_lock); | ||
242 | ucb1x00_disable(ts->ucb); | 249 | ucb1x00_disable(ts->ucb); |
243 | 250 | ||
244 | /* | 251 | /* |
@@ -281,23 +288,37 @@ static int ucb1x00_thread(void *_ts) | |||
281 | * We only detect touch screen _touches_ with this interrupt | 288 | * We only detect touch screen _touches_ with this interrupt |
282 | * handler, and even then we just schedule our task. | 289 | * handler, and even then we just schedule our task. |
283 | */ | 290 | */ |
284 | static void ucb1x00_ts_irq(int idx, void *id) | 291 | static irqreturn_t ucb1x00_ts_irq(int irq, void *id) |
285 | { | 292 | { |
286 | struct ucb1x00_ts *ts = id; | 293 | struct ucb1x00_ts *ts = id; |
287 | 294 | ||
288 | ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); | 295 | spin_lock(&ts->irq_lock); |
296 | ts->irq_disabled = 1; | ||
297 | disable_irq_nosync(ts->ucb->irq_base + UCB_IRQ_TSPX); | ||
298 | spin_unlock(&ts->irq_lock); | ||
289 | wake_up(&ts->irq_wait); | 299 | wake_up(&ts->irq_wait); |
300 | |||
301 | return IRQ_HANDLED; | ||
290 | } | 302 | } |
291 | 303 | ||
292 | static int ucb1x00_ts_open(struct input_dev *idev) | 304 | static int ucb1x00_ts_open(struct input_dev *idev) |
293 | { | 305 | { |
294 | struct ucb1x00_ts *ts = input_get_drvdata(idev); | 306 | struct ucb1x00_ts *ts = input_get_drvdata(idev); |
307 | unsigned long flags = 0; | ||
295 | int ret = 0; | 308 | int ret = 0; |
296 | 309 | ||
297 | BUG_ON(ts->rtask); | 310 | BUG_ON(ts->rtask); |
298 | 311 | ||
312 | if (machine_is_collie()) | ||
313 | flags = IRQF_TRIGGER_RISING; | ||
314 | else | ||
315 | flags = IRQF_TRIGGER_FALLING; | ||
316 | |||
317 | ts->irq_disabled = 0; | ||
318 | |||
299 | init_waitqueue_head(&ts->irq_wait); | 319 | init_waitqueue_head(&ts->irq_wait); |
300 | ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); | 320 | ret = request_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ucb1x00_ts_irq, |
321 | flags, "ucb1x00-ts", ts); | ||
301 | if (ret < 0) | 322 | if (ret < 0) |
302 | goto out; | 323 | goto out; |
303 | 324 | ||
@@ -314,7 +335,7 @@ static int ucb1x00_ts_open(struct input_dev *idev) | |||
314 | if (!IS_ERR(ts->rtask)) { | 335 | if (!IS_ERR(ts->rtask)) { |
315 | ret = 0; | 336 | ret = 0; |
316 | } else { | 337 | } else { |
317 | ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); | 338 | free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts); |
318 | ts->rtask = NULL; | 339 | ts->rtask = NULL; |
319 | ret = -EFAULT; | 340 | ret = -EFAULT; |
320 | } | 341 | } |
@@ -334,7 +355,7 @@ static void ucb1x00_ts_close(struct input_dev *idev) | |||
334 | kthread_stop(ts->rtask); | 355 | kthread_stop(ts->rtask); |
335 | 356 | ||
336 | ucb1x00_enable(ts->ucb); | 357 | ucb1x00_enable(ts->ucb); |
337 | ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); | 358 | free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts); |
338 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); | 359 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); |
339 | ucb1x00_disable(ts->ucb); | 360 | ucb1x00_disable(ts->ucb); |
340 | } | 361 | } |
@@ -359,11 +380,13 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) | |||
359 | ts->ucb = dev->ucb; | 380 | ts->ucb = dev->ucb; |
360 | ts->idev = idev; | 381 | ts->idev = idev; |
361 | ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; | 382 | ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; |
383 | spin_lock_init(&ts->irq_lock); | ||
362 | 384 | ||
363 | idev->name = "Touchscreen panel"; | 385 | idev->name = "Touchscreen panel"; |
364 | idev->id.product = ts->ucb->id; | 386 | idev->id.product = ts->ucb->id; |
365 | idev->open = ucb1x00_ts_open; | 387 | idev->open = ucb1x00_ts_open; |
366 | idev->close = ucb1x00_ts_close; | 388 | idev->close = ucb1x00_ts_close; |
389 | idev->dev.parent = &ts->ucb->dev; | ||
367 | 390 | ||
368 | idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); | 391 | idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); |
369 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 392 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
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 bc0c5096539a..bfd25af6ecb1 100644 --- a/drivers/mfd/wm8994-regmap.c +++ b/drivers/mfd/wm8994-regmap.c | |||
@@ -15,11 +15,11 @@ | |||
15 | #include <linux/mfd/wm8994/core.h> | 15 | #include <linux/mfd/wm8994/core.h> |
16 | #include <linux/mfd/wm8994/registers.h> | 16 | #include <linux/mfd/wm8994/registers.h> |
17 | #include <linux/regmap.h> | 17 | #include <linux/regmap.h> |
18 | #include <linux/device.h> | ||
18 | 19 | ||
19 | #include "wm8994.h" | 20 | #include "wm8994.h" |
20 | 21 | ||
21 | static struct reg_default wm1811_defaults[] = { | 22 | static struct reg_default wm1811_defaults[] = { |
22 | { 0x0000, 0x1811 }, /* R0 - Software Reset */ | ||
23 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ | 23 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ |
24 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ | 24 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ |
25 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ | 25 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ |
@@ -60,7 +60,7 @@ static struct reg_default wm1811_defaults[] = { | |||
60 | { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */ | 60 | { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */ |
61 | { 0x0037, 0x0000 }, /* R55 - Additional Control */ | 61 | { 0x0037, 0x0000 }, /* R55 - Additional Control */ |
62 | { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */ | 62 | { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */ |
63 | { 0x0039, 0x0180 }, /* R57 - AntiPOP (2) */ | 63 | { 0x0039, 0x0000 }, /* R57 - AntiPOP (2) */ |
64 | { 0x003B, 0x000D }, /* R59 - LDO 1 */ | 64 | { 0x003B, 0x000D }, /* R59 - LDO 1 */ |
65 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ | 65 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ |
66 | { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */ | 66 | { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */ |
@@ -68,16 +68,12 @@ static struct reg_default wm1811_defaults[] = { | |||
68 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ | 68 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ |
69 | { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */ | 69 | { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */ |
70 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ | 70 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ |
71 | { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */ | ||
72 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ | 71 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ |
73 | { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */ | ||
74 | { 0x0059, 0x0000 }, /* R89 - DC Servo (4) */ | 72 | { 0x0059, 0x0000 }, /* R89 - DC Servo (4) */ |
75 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ | 73 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ |
76 | { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */ | 74 | { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */ |
77 | { 0x00D0, 0x7600 }, /* R208 - Mic Detect 1 */ | 75 | { 0x00D0, 0x7600 }, /* R208 - Mic Detect 1 */ |
78 | { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */ | 76 | { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */ |
79 | { 0x00D2, 0x0000 }, /* R210 - Mic Detect 3 */ | ||
80 | { 0x0100, 0x0100 }, /* R256 - Chip Revision */ | ||
81 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ | 77 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ |
82 | { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */ | 78 | { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */ |
83 | { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */ | 79 | { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */ |
@@ -87,7 +83,6 @@ static struct reg_default wm1811_defaults[] = { | |||
87 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ | 83 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ |
88 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ | 84 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ |
89 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ | 85 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ |
90 | { 0x0212, 0x0000 }, /* R530 - Rate Status */ | ||
91 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ | 86 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ |
92 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ | 87 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ |
93 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ | 88 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ |
@@ -217,8 +212,6 @@ static struct reg_default wm1811_defaults[] = { | |||
217 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ | 212 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ |
218 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ | 213 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ |
219 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ | 214 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ |
220 | { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */ | ||
221 | { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */ | ||
222 | { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */ | 215 | { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */ |
223 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ | 216 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ |
224 | { 0x0739, 0xDFEF }, /* R1849 - Interrupt Status 2 Mask */ | 217 | { 0x0739, 0xDFEF }, /* R1849 - Interrupt Status 2 Mask */ |
@@ -227,7 +220,6 @@ static struct reg_default wm1811_defaults[] = { | |||
227 | }; | 220 | }; |
228 | 221 | ||
229 | static struct reg_default wm8994_defaults[] = { | 222 | static struct reg_default wm8994_defaults[] = { |
230 | { 0x0000, 0x8994 }, /* R0 - Software Reset */ | ||
231 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ | 223 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ |
232 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ | 224 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ |
233 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ | 225 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ |
@@ -274,12 +266,9 @@ static struct reg_default wm8994_defaults[] = { | |||
274 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ | 266 | { 0x003C, 0x0003 }, /* R60 - LDO 2 */ |
275 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ | 267 | { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */ |
276 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ | 268 | { 0x0051, 0x0004 }, /* R81 - Class W (1) */ |
277 | { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */ | ||
278 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ | 269 | { 0x0055, 0x054A }, /* R85 - DC Servo (2) */ |
279 | { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */ | 270 | { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */ |
280 | { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */ | ||
281 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ | 271 | { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */ |
282 | { 0x0100, 0x0003 }, /* R256 - Chip Revision */ | ||
283 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ | 272 | { 0x0101, 0x8004 }, /* R257 - Control Interface */ |
284 | { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */ | 273 | { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */ |
285 | { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */ | 274 | { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */ |
@@ -291,7 +280,6 @@ static struct reg_default wm8994_defaults[] = { | |||
291 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ | 280 | { 0x0209, 0x0000 }, /* R521 - Clocking (2) */ |
292 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ | 281 | { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */ |
293 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ | 282 | { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */ |
294 | { 0x0212, 0x0000 }, /* R530 - Rate Status */ | ||
295 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ | 283 | { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */ |
296 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ | 284 | { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */ |
297 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ | 285 | { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */ |
@@ -444,9 +432,6 @@ static struct reg_default wm8994_defaults[] = { | |||
444 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ | 432 | { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */ |
445 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ | 433 | { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */ |
446 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ | 434 | { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */ |
447 | { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */ | ||
448 | { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */ | ||
449 | { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */ | ||
450 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ | 435 | { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */ |
451 | { 0x0739, 0xFFFF }, /* R1849 - Interrupt Status 2 Mask */ | 436 | { 0x0739, 0xFFFF }, /* R1849 - Interrupt Status 2 Mask */ |
452 | { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */ | 437 | { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */ |
@@ -454,7 +439,6 @@ static struct reg_default wm8994_defaults[] = { | |||
454 | }; | 439 | }; |
455 | 440 | ||
456 | static struct reg_default wm8958_defaults[] = { | 441 | static struct reg_default wm8958_defaults[] = { |
457 | { 0x0000, 0x8958 }, /* R0 - Software Reset */ | ||
458 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ | 442 | { 0x0001, 0x0000 }, /* R1 - Power Management (1) */ |
459 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ | 443 | { 0x0002, 0x6000 }, /* R2 - Power Management (2) */ |
460 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ | 444 | { 0x0003, 0x0000 }, /* R3 - Power Management (3) */ |
@@ -969,6 +953,7 @@ static bool wm8994_readable_register(struct device *dev, unsigned int reg) | |||
969 | { | 953 | { |
970 | switch (reg) { | 954 | switch (reg) { |
971 | case WM8994_DC_SERVO_READBACK: | 955 | case WM8994_DC_SERVO_READBACK: |
956 | case WM8994_MICBIAS: | ||
972 | case WM8994_WRITE_SEQUENCER_CTRL_1: | 957 | case WM8994_WRITE_SEQUENCER_CTRL_1: |
973 | case WM8994_WRITE_SEQUENCER_CTRL_2: | 958 | case WM8994_WRITE_SEQUENCER_CTRL_2: |
974 | case WM8994_AIF1_ADC2_LEFT_VOLUME: | 959 | case WM8994_AIF1_ADC2_LEFT_VOLUME: |