diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-08-16 13:42:58 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-08-16 13:42:58 -0400 |
commit | e4862f2f6f5653dfb67f3ba2b6f0bc74516ed51a (patch) | |
tree | 1db5a0540a4eecfad9b7daee476b985e82ddc810 /drivers/mfd | |
parent | ec62dbd7eb8e3dddb221da89ecbcea0fc3dee8c1 (diff) | |
parent | b2c1e07b81a126e5846dfc3d36f559d861df59f4 (diff) |
Merge branch 'for-2.6.36' into for-2.6.37
Fairly simple conflicts, the most serious ones are the i.MX ones which I
suspect now need another rename.
Conflicts:
arch/arm/mach-mx2/clock_imx27.c
arch/arm/mach-mx2/devices.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-zoom2.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/fsl/mpc5200_dma.h
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/pxa/spitz.c
Diffstat (limited to 'drivers/mfd')
38 files changed, 2562 insertions, 137 deletions
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 2c65a2c57294..07933f3f7e4c 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -74,12 +74,12 @@ static struct mfd_cell backlight_devs[] = { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | static struct resource led_resources[] = { | 76 | static struct resource led_resources[] = { |
77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB2B), | 77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B), |
78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB2C), | 78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C), |
79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB2D), | 79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D), |
80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB1B), | 80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B), |
81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB1C), | 81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C), |
82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB1D), | 82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D), |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define PM8606_LED_DEVS(_i) \ | 85 | #define PM8606_LED_DEVS(_i) \ |
@@ -428,52 +428,44 @@ static int __devinit device_gpadc_init(struct pm860x_chip *chip, | |||
428 | { | 428 | { |
429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | 429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ |
430 | : chip->companion; | 430 | : chip->companion; |
431 | int use_gpadc = 0, data, ret; | 431 | int data; |
432 | int ret; | ||
432 | 433 | ||
433 | /* initialize GPADC without activating it */ | 434 | /* initialize GPADC without activating it */ |
434 | 435 | ||
435 | if (pdata && pdata->touch) { | 436 | if (!pdata || !pdata->touch) |
436 | /* set GPADC MISC1 register */ | 437 | return -EINVAL; |
437 | data = 0; | ||
438 | data |= (pdata->touch->gpadc_prebias << 1) | ||
439 | & PM8607_GPADC_PREBIAS_MASK; | ||
440 | data |= (pdata->touch->slot_cycle << 3) | ||
441 | & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
442 | data |= (pdata->touch->off_scale << 5) | ||
443 | & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) | ||
445 | & PM8607_GPADC_SW_CAL_MASK; | ||
446 | if (data) { | ||
447 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
448 | if (ret < 0) | ||
449 | goto out; | ||
450 | } | ||
451 | /* set tsi prebias time */ | ||
452 | if (pdata->touch->tsi_prebias) { | ||
453 | data = pdata->touch->tsi_prebias; | ||
454 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); | ||
455 | if (ret < 0) | ||
456 | goto out; | ||
457 | } | ||
458 | /* set prebias & prechg time of pen detect */ | ||
459 | data = 0; | ||
460 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
461 | data |= (pdata->touch->pen_prechg << 5) | ||
462 | & PM8607_PD_PRECHG_MASK; | ||
463 | if (data) { | ||
464 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
465 | if (ret < 0) | ||
466 | goto out; | ||
467 | } | ||
468 | 438 | ||
469 | use_gpadc = 1; | 439 | /* set GPADC MISC1 register */ |
440 | data = 0; | ||
441 | data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; | ||
442 | data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
443 | data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; | ||
445 | if (data) { | ||
446 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
447 | if (ret < 0) | ||
448 | goto out; | ||
470 | } | 449 | } |
471 | 450 | /* set tsi prebias time */ | |
472 | /* turn on GPADC */ | 451 | if (pdata->touch->tsi_prebias) { |
473 | if (use_gpadc) { | 452 | data = pdata->touch->tsi_prebias; |
474 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | 453 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); |
475 | PM8607_GPADC_EN, PM8607_GPADC_EN); | 454 | if (ret < 0) |
455 | goto out; | ||
476 | } | 456 | } |
457 | /* set prebias & prechg time of pen detect */ | ||
458 | data = 0; | ||
459 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
460 | data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; | ||
461 | if (data) { | ||
462 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
463 | if (ret < 0) | ||
464 | goto out; | ||
465 | } | ||
466 | |||
467 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | ||
468 | PM8607_GPADC_EN, PM8607_GPADC_EN); | ||
477 | out: | 469 | out: |
478 | return ret; | 470 | return ret; |
479 | } | 471 | } |
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c index c933b64d1283..bc02e6b21608 100644 --- a/drivers/mfd/88pm860x-i2c.c +++ b/drivers/mfd/88pm860x-i2c.c | |||
@@ -200,8 +200,6 @@ static int __devexit pm860x_remove(struct i2c_client *client) | |||
200 | 200 | ||
201 | pm860x_device_exit(chip); | 201 | pm860x_device_exit(chip); |
202 | i2c_unregister_device(chip->companion); | 202 | i2c_unregister_device(chip->companion); |
203 | i2c_set_clientdata(chip->client, NULL); | ||
204 | i2c_set_clientdata(client, NULL); | ||
205 | kfree(chip); | 203 | kfree(chip); |
206 | return 0; | 204 | return 0; |
207 | } | 205 | } |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9da0e504bbe9..db51ea1c6082 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -7,7 +7,16 @@ menuconfig MFD_SUPPORT | |||
7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | default y | 8 | default y |
9 | help | 9 | help |
10 | Configure MFD device drivers. | 10 | Multifunction devices embed several functions (e.g. GPIOs, |
11 | touchscreens, keyboards, current regulators, power management chips, | ||
12 | etc...) in one single integrated circuit. They usually talk to the | ||
13 | main CPU through one or more IRQ lines and low speed data busses (SPI, | ||
14 | I2C, etc..). They appear as one single device to the main system | ||
15 | through the data bus and the MFD framework allows for sub devices | ||
16 | (a.k.a. functions) to appear as discrete platform devices. | ||
17 | MFDs are typically found on embedded platforms. | ||
18 | |||
19 | This option alone does not add any kernel code. | ||
11 | 20 | ||
12 | if MFD_SUPPORT | 21 | if MFD_SUPPORT |
13 | 22 | ||
@@ -177,6 +186,38 @@ config TWL4030_CODEC | |||
177 | select MFD_CORE | 186 | select MFD_CORE |
178 | default n | 187 | default n |
179 | 188 | ||
189 | config TWL6030_PWM | ||
190 | tristate "TWL6030 PWM (Pulse Width Modulator) Support" | ||
191 | depends on TWL4030_CORE | ||
192 | select HAVE_PWM | ||
193 | default n | ||
194 | help | ||
195 | Say yes here if you want support for TWL6030 PWM. | ||
196 | This is used to control charging LED brightness. | ||
197 | |||
198 | config MFD_STMPE | ||
199 | bool "Support STMicroelectronics STMPE" | ||
200 | depends on I2C=y && GENERIC_HARDIRQS | ||
201 | select MFD_CORE | ||
202 | help | ||
203 | Support for the STMPE family of I/O Expanders from | ||
204 | STMicroelectronics. | ||
205 | |||
206 | Currently supported devices are: | ||
207 | |||
208 | STMPE811: GPIO, Touchscreen | ||
209 | STMPE1601: GPIO, Keypad | ||
210 | STMPE2401: GPIO, Keypad | ||
211 | STMPE2403: GPIO, Keypad | ||
212 | |||
213 | This driver provides common support for accessing the device, | ||
214 | additional drivers must be enabled in order to use the functionality | ||
215 | of the device. Currently available sub drivers are: | ||
216 | |||
217 | GPIO: stmpe-gpio | ||
218 | Keypad: stmpe-keypad | ||
219 | Touchscreen: stmpe-ts | ||
220 | |||
180 | config MFD_TC35892 | 221 | config MFD_TC35892 |
181 | bool "Support Toshiba TC35892" | 222 | bool "Support Toshiba TC35892" |
182 | depends on I2C=y && GENERIC_HARDIRQS | 223 | depends on I2C=y && GENERIC_HARDIRQS |
@@ -252,6 +293,16 @@ config MFD_MAX8925 | |||
252 | accessing the device, additional drivers must be enabled in order | 293 | accessing the device, additional drivers must be enabled in order |
253 | to use the functionality of the device. | 294 | to use the functionality of the device. |
254 | 295 | ||
296 | config MFD_MAX8998 | ||
297 | bool "Maxim Semiconductor MAX8998 PMIC Support" | ||
298 | depends on I2C=y | ||
299 | select MFD_CORE | ||
300 | help | ||
301 | Say yes here to support for Maxim Semiconductor MAX8998. This is | ||
302 | a Power Management IC. This driver provies common support for | ||
303 | accessing the device, additional drivers must be enabled in order | ||
304 | to use the functionality of the device. | ||
305 | |||
255 | config MFD_WM8400 | 306 | config MFD_WM8400 |
256 | tristate "Support Wolfson Microelectronics WM8400" | 307 | tristate "Support Wolfson Microelectronics WM8400" |
257 | select MFD_CORE | 308 | select MFD_CORE |
@@ -482,6 +533,28 @@ config MFD_JANZ_CMODIO | |||
482 | host many different types of MODULbus daughterboards, including | 533 | host many different types of MODULbus daughterboards, including |
483 | CAN and GPIO controllers. | 534 | CAN and GPIO controllers. |
484 | 535 | ||
536 | config MFD_JZ4740_ADC | ||
537 | tristate "Support for the JZ4740 SoC ADC core" | ||
538 | select MFD_CORE | ||
539 | depends on MACH_JZ4740 | ||
540 | help | ||
541 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. | ||
542 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. | ||
543 | |||
544 | config MFD_TPS6586X | ||
545 | tristate "TPS6586x Power Management chips" | ||
546 | depends on I2C && GPIOLIB | ||
547 | select MFD_CORE | ||
548 | help | ||
549 | If you say yes here you get support for the TPS6586X series of | ||
550 | Power Management chips. | ||
551 | This driver provides common support for accessing the device, | ||
552 | additional drivers must be enabled in order to use the | ||
553 | functionality of the device. | ||
554 | |||
555 | This driver can also be built as a module. If so, the module | ||
556 | will be called tps6586x. | ||
557 | |||
485 | endif # MFD_SUPPORT | 558 | endif # MFD_SUPPORT |
486 | 559 | ||
487 | menu "Multimedia Capabilities Port drivers" | 560 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index fb503e77dc60..feaeeaeeddb7 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o | |||
15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o | 15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o |
16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o | 16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o |
17 | 17 | ||
18 | obj-$(CONFIG_MFD_STMPE) += stmpe.o | ||
18 | obj-$(CONFIG_MFD_TC35892) += tc35892.o | 19 | obj-$(CONFIG_MFD_TC35892) += tc35892.o |
19 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o | 20 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o |
20 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o | 21 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o |
@@ -36,6 +37,7 @@ obj-$(CONFIG_MENELAUS) += menelaus.o | |||
36 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o | 37 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o |
37 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | 38 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o |
38 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | 39 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o |
40 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | ||
39 | 41 | ||
40 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o | 42 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o |
41 | 43 | ||
@@ -56,6 +58,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o | |||
56 | obj-$(CONFIG_PMIC_DA903X) += da903x.o | 58 | obj-$(CONFIG_PMIC_DA903X) += da903x.o |
57 | max8925-objs := max8925-core.o max8925-i2c.o | 59 | max8925-objs := max8925-core.o max8925-i2c.o |
58 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 60 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
61 | obj-$(CONFIG_MFD_MAX8998) += max8998.o | ||
59 | 62 | ||
60 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o | 63 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o |
61 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o | 64 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o |
@@ -71,3 +74,5 @@ obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | |||
71 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o | 74 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o |
72 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o | 75 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o |
73 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o | 76 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o |
77 | obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o | ||
78 | obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o | ||
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 53ebfee548fa..66379b413906 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -957,7 +957,6 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
957 | i2c_unregister_device(ab3100->testreg_client); | 957 | i2c_unregister_device(ab3100->testreg_client); |
958 | exit_no_testreg_client: | 958 | exit_no_testreg_client: |
959 | exit_no_detect: | 959 | exit_no_detect: |
960 | i2c_set_clientdata(client, NULL); | ||
961 | kfree(ab3100); | 960 | kfree(ab3100); |
962 | return err; | 961 | return err; |
963 | } | 962 | } |
@@ -979,7 +978,6 @@ static int __exit ab3100_remove(struct i2c_client *client) | |||
979 | * their notifiers so deactivate IRQ | 978 | * their notifiers so deactivate IRQ |
980 | */ | 979 | */ |
981 | free_irq(client->irq, ab3100); | 980 | free_irq(client->irq, ab3100); |
982 | i2c_set_clientdata(client, NULL); | ||
983 | kfree(ab3100); | 981 | kfree(ab3100); |
984 | return 0; | 982 | return 0; |
985 | } | 983 | } |
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index 63d2b727ddbb..8440010eb2b8 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c | |||
@@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
199 | 199 | ||
200 | err = ab3100_otp_read(otp); | 200 | err = ab3100_otp_read(otp); |
201 | if (err) | 201 | if (err) |
202 | return err; | 202 | goto err_otp_read; |
203 | 203 | ||
204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); | 204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); |
205 | 205 | ||
@@ -208,21 +208,21 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
208 | err = device_create_file(&pdev->dev, | 208 | err = device_create_file(&pdev->dev, |
209 | &ab3100_otp_attrs[i]); | 209 | &ab3100_otp_attrs[i]); |
210 | if (err) | 210 | if (err) |
211 | goto out_no_sysfs; | 211 | goto err_create_file; |
212 | } | 212 | } |
213 | 213 | ||
214 | /* debugfs entries */ | 214 | /* debugfs entries */ |
215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); | 215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); |
216 | if (err) | 216 | if (err) |
217 | goto out_no_debugfs; | 217 | goto err_init_debugfs; |
218 | 218 | ||
219 | return 0; | 219 | return 0; |
220 | 220 | ||
221 | out_no_sysfs: | 221 | err_init_debugfs: |
222 | for (i = 0; i < ARRAY_SIZE(ab3100_otp_attrs); i++) | 222 | err_create_file: |
223 | device_remove_file(&pdev->dev, | 223 | while (--i >= 0) |
224 | &ab3100_otp_attrs[i]); | 224 | device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); |
225 | out_no_debugfs: | 225 | err_otp_read: |
226 | kfree(otp); | 226 | kfree(otp); |
227 | return err; | 227 | return err; |
228 | } | 228 | } |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index 1060f8e1c40a..8a98739e6d9c 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c | |||
@@ -589,16 +589,16 @@ static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | |||
589 | } | 589 | } |
590 | 590 | ||
591 | /* | 591 | /* |
592 | * The exported register access functionality. | 592 | * The register access functionality. |
593 | */ | 593 | */ |
594 | int ab3550_get_chip_id(struct device *dev) | 594 | static int ab3550_get_chip_id(struct device *dev) |
595 | { | 595 | { |
596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); | 596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); |
597 | return (int)ab->chip_id; | 597 | return (int)ab->chip_id; |
598 | } | 598 | } |
599 | 599 | ||
600 | int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | 600 | static int ab3550_mask_and_set_register_interruptible(struct device *dev, |
601 | u8 reg, u8 bitmask, u8 bitvalues) | 601 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) |
602 | { | 602 | { |
603 | struct ab3550 *ab; | 603 | struct ab3550 *ab; |
604 | struct platform_device *pdev = to_platform_device(dev); | 604 | struct platform_device *pdev = to_platform_device(dev); |
@@ -612,15 +612,15 @@ int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | |||
612 | bitmask, bitvalues); | 612 | bitmask, bitvalues); |
613 | } | 613 | } |
614 | 614 | ||
615 | int ab3550_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | 615 | static int ab3550_set_register_interruptible(struct device *dev, u8 bank, |
616 | u8 value) | 616 | u8 reg, u8 value) |
617 | { | 617 | { |
618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | 618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, |
619 | value); | 619 | value); |
620 | } | 620 | } |
621 | 621 | ||
622 | int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | 622 | static int ab3550_get_register_interruptible(struct device *dev, u8 bank, |
623 | u8 *value) | 623 | u8 reg, u8 *value) |
624 | { | 624 | { |
625 | struct ab3550 *ab; | 625 | struct ab3550 *ab; |
626 | struct platform_device *pdev = to_platform_device(dev); | 626 | struct platform_device *pdev = to_platform_device(dev); |
@@ -633,7 +633,7 @@ int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | |||
633 | return get_register_interruptible(ab, bank, reg, value); | 633 | return get_register_interruptible(ab, bank, reg, value); |
634 | } | 634 | } |
635 | 635 | ||
636 | int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | 636 | static int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, |
637 | u8 first_reg, u8 *regvals, u8 numregs) | 637 | u8 first_reg, u8 *regvals, u8 numregs) |
638 | { | 638 | { |
639 | struct ab3550 *ab; | 639 | struct ab3550 *ab; |
@@ -649,7 +649,8 @@ int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | |||
649 | numregs); | 649 | numregs); |
650 | } | 650 | } |
651 | 651 | ||
652 | int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | 652 | static int ab3550_event_registers_startup_state_get(struct device *dev, |
653 | u8 *event) | ||
653 | { | 654 | { |
654 | struct ab3550 *ab; | 655 | struct ab3550 *ab; |
655 | 656 | ||
@@ -661,7 +662,7 @@ int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | |||
661 | return 0; | 662 | return 0; |
662 | } | 663 | } |
663 | 664 | ||
664 | int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) | 665 | static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) |
665 | { | 666 | { |
666 | struct ab3550 *ab; | 667 | struct ab3550 *ab; |
667 | struct ab3550_platform_data *plf_data; | 668 | struct ab3550_platform_data *plf_data; |
@@ -1362,7 +1363,6 @@ static int __exit ab3550_remove(struct i2c_client *client) | |||
1362 | * their notifiers so deactivate IRQ | 1363 | * their notifiers so deactivate IRQ |
1363 | */ | 1364 | */ |
1364 | free_irq(client->irq, ab); | 1365 | free_irq(client->irq, ab); |
1365 | i2c_set_clientdata(client, NULL); | ||
1366 | kfree(ab); | 1366 | kfree(ab); |
1367 | return 0; | 1367 | return 0; |
1368 | } | 1368 | } |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index f3d26fa9c34d..defa786dee34 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/mfd/core.h> | 17 | #include <linux/mfd/core.h> |
18 | #include <linux/mfd/ab8500.h> | 18 | #include <linux/mfd/ab8500.h> |
19 | #include <linux/regulator/ab8500.h> | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * Interrupt register offsets | 22 | * Interrupt register offsets |
@@ -352,6 +353,7 @@ static struct mfd_cell ab8500_devs[] = { | |||
352 | { .name = "ab8500-audio", }, | 353 | { .name = "ab8500-audio", }, |
353 | { .name = "ab8500-usb", }, | 354 | { .name = "ab8500-usb", }, |
354 | { .name = "ab8500-pwm", }, | 355 | { .name = "ab8500-pwm", }, |
356 | { .name = "ab8500-regulator", }, | ||
355 | }; | 357 | }; |
356 | 358 | ||
357 | int __devinit ab8500_init(struct ab8500 *ab8500) | 359 | int __devinit ab8500_init(struct ab8500 *ab8500) |
@@ -411,7 +413,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
411 | goto out_removeirq; | 413 | goto out_removeirq; |
412 | } | 414 | } |
413 | 415 | ||
414 | ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs, | 416 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, |
415 | ARRAY_SIZE(ab8500_devs), NULL, | 417 | ARRAY_SIZE(ab8500_devs), NULL, |
416 | ab8500->irq_base); | 418 | ab8500->irq_base); |
417 | if (ret) | 419 | if (ret) |
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c index b81d4f768ef6..e1c8b62b086d 100644 --- a/drivers/mfd/ab8500-spi.c +++ b/drivers/mfd/ab8500-spi.c | |||
@@ -68,7 +68,12 @@ static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr) | |||
68 | 68 | ||
69 | ret = spi_sync(spi, &msg); | 69 | ret = spi_sync(spi, &msg); |
70 | if (!ret) | 70 | if (!ret) |
71 | ret = ab8500->rx_buf[0]; | 71 | /* |
72 | * Only the 8 lowermost bytes are | ||
73 | * defined with value, the rest may | ||
74 | * vary depending on chip/board noise. | ||
75 | */ | ||
76 | ret = ab8500->rx_buf[0] & 0xFFU; | ||
72 | 77 | ||
73 | return ret; | 78 | return ret; |
74 | } | 79 | } |
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 3b3b97ec32a7..f12720dbe126 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c | |||
@@ -36,7 +36,7 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops) | |||
36 | struct abx500_device_entry *dev_entry; | 36 | struct abx500_device_entry *dev_entry; |
37 | 37 | ||
38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); | 38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); |
39 | if (IS_ERR(dev_entry)) { | 39 | if (!dev_entry) { |
40 | dev_err(dev, "register_ops kzalloc failed"); | 40 | dev_err(dev, "register_ops kzalloc failed"); |
41 | return -ENOMEM; | 41 | return -ENOMEM; |
42 | } | 42 | } |
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 005532865654..3122139b4300 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c | |||
@@ -302,7 +302,6 @@ out_free_irq: | |||
302 | free_irq(chip->irq, chip); | 302 | free_irq(chip->irq, chip); |
303 | 303 | ||
304 | out_free_chip: | 304 | out_free_chip: |
305 | i2c_set_clientdata(client, NULL); | ||
306 | kfree(chip); | 305 | kfree(chip); |
307 | 306 | ||
308 | return ret; | 307 | return ret; |
@@ -317,7 +316,6 @@ static int __devexit adp5520_remove(struct i2c_client *client) | |||
317 | 316 | ||
318 | adp5520_remove_subdevs(chip); | 317 | adp5520_remove_subdevs(chip); |
319 | adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); | 318 | adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); |
320 | i2c_set_clientdata(client, NULL); | ||
321 | kfree(chip); | 319 | kfree(chip); |
322 | return 0; | 320 | return 0; |
323 | } | 321 | } |
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 3ad915d0589c..c07aece900fb 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c | |||
@@ -534,7 +534,6 @@ static int __devinit da903x_probe(struct i2c_client *client, | |||
534 | out_free_irq: | 534 | out_free_irq: |
535 | free_irq(client->irq, chip); | 535 | free_irq(client->irq, chip); |
536 | out_free_chip: | 536 | out_free_chip: |
537 | i2c_set_clientdata(client, NULL); | ||
538 | kfree(chip); | 537 | kfree(chip); |
539 | return ret; | 538 | return ret; |
540 | } | 539 | } |
@@ -544,7 +543,6 @@ static int __devexit da903x_remove(struct i2c_client *client) | |||
544 | struct da903x_chip *chip = i2c_get_clientdata(client); | 543 | struct da903x_chip *chip = i2c_get_clientdata(client); |
545 | 544 | ||
546 | da903x_remove_subdevs(chip); | 545 | da903x_remove_subdevs(chip); |
547 | i2c_set_clientdata(client, NULL); | ||
548 | kfree(chip); | 546 | kfree(chip); |
549 | return 0; | 547 | return 0; |
550 | } | 548 | } |
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 3e75f02e4778..33c923d215c7 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c | |||
@@ -94,7 +94,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
95 | if (!res) { | 95 | if (!res) { |
96 | dev_err(&pdev->dev, "no DMA resource\n"); | 96 | dev_err(&pdev->dev, "no DMA resource\n"); |
97 | return -ENXIO; | 97 | ret = -ENXIO; |
98 | goto fail4; | ||
98 | } | 99 | } |
99 | 100 | ||
100 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; | 101 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; |
@@ -104,7 +105,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
104 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 105 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
105 | if (!res) { | 106 | if (!res) { |
106 | dev_err(&pdev->dev, "no DMA resource\n"); | 107 | dev_err(&pdev->dev, "no DMA resource\n"); |
107 | return -ENXIO; | 108 | ret = -ENXIO; |
109 | goto fail4; | ||
108 | } | 110 | } |
109 | 111 | ||
110 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; | 112 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; |
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 9ed630799acc..36a166bcdb08 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/mfd/core.h> | 22 | #include <linux/mfd/core.h> |
22 | 23 | ||
23 | #include <linux/mfd/janz.h> | 24 | #include <linux/mfd/janz.h> |
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c new file mode 100644 index 000000000000..3ad492cb6c41 --- /dev/null +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -0,0 +1,394 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 SoC ADC driver | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | * This driver synchronizes access to the JZ4740 ADC core between the | ||
15 | * JZ4740 battery and hwmon drivers. | ||
16 | */ | ||
17 | |||
18 | #include <linux/err.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | |||
27 | #include <linux/clk.h> | ||
28 | #include <linux/mfd/core.h> | ||
29 | |||
30 | #include <linux/jz4740-adc.h> | ||
31 | |||
32 | |||
33 | #define JZ_REG_ADC_ENABLE 0x00 | ||
34 | #define JZ_REG_ADC_CFG 0x04 | ||
35 | #define JZ_REG_ADC_CTRL 0x08 | ||
36 | #define JZ_REG_ADC_STATUS 0x0c | ||
37 | |||
38 | #define JZ_REG_ADC_TOUCHSCREEN_BASE 0x10 | ||
39 | #define JZ_REG_ADC_BATTERY_BASE 0x1c | ||
40 | #define JZ_REG_ADC_HWMON_BASE 0x20 | ||
41 | |||
42 | #define JZ_ADC_ENABLE_TOUCH BIT(2) | ||
43 | #define JZ_ADC_ENABLE_BATTERY BIT(1) | ||
44 | #define JZ_ADC_ENABLE_ADCIN BIT(0) | ||
45 | |||
46 | enum { | ||
47 | JZ_ADC_IRQ_ADCIN = 0, | ||
48 | JZ_ADC_IRQ_BATTERY, | ||
49 | JZ_ADC_IRQ_TOUCH, | ||
50 | JZ_ADC_IRQ_PENUP, | ||
51 | JZ_ADC_IRQ_PENDOWN, | ||
52 | }; | ||
53 | |||
54 | struct jz4740_adc { | ||
55 | struct resource *mem; | ||
56 | void __iomem *base; | ||
57 | |||
58 | int irq; | ||
59 | int irq_base; | ||
60 | |||
61 | struct clk *clk; | ||
62 | atomic_t clk_ref; | ||
63 | |||
64 | spinlock_t lock; | ||
65 | }; | ||
66 | |||
67 | static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq, | ||
68 | bool masked) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | uint8_t val; | ||
72 | |||
73 | irq -= adc->irq_base; | ||
74 | |||
75 | spin_lock_irqsave(&adc->lock, flags); | ||
76 | |||
77 | val = readb(adc->base + JZ_REG_ADC_CTRL); | ||
78 | if (masked) | ||
79 | val |= BIT(irq); | ||
80 | else | ||
81 | val &= ~BIT(irq); | ||
82 | writeb(val, adc->base + JZ_REG_ADC_CTRL); | ||
83 | |||
84 | spin_unlock_irqrestore(&adc->lock, flags); | ||
85 | } | ||
86 | |||
87 | static void jz4740_adc_irq_mask(unsigned int irq) | ||
88 | { | ||
89 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
90 | jz4740_adc_irq_set_masked(adc, irq, true); | ||
91 | } | ||
92 | |||
93 | static void jz4740_adc_irq_unmask(unsigned int irq) | ||
94 | { | ||
95 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
96 | jz4740_adc_irq_set_masked(adc, irq, false); | ||
97 | } | ||
98 | |||
99 | static void jz4740_adc_irq_ack(unsigned int irq) | ||
100 | { | ||
101 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
102 | |||
103 | irq -= adc->irq_base; | ||
104 | writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS); | ||
105 | } | ||
106 | |||
107 | static struct irq_chip jz4740_adc_irq_chip = { | ||
108 | .name = "jz4740-adc", | ||
109 | .mask = jz4740_adc_irq_mask, | ||
110 | .unmask = jz4740_adc_irq_unmask, | ||
111 | .ack = jz4740_adc_irq_ack, | ||
112 | }; | ||
113 | |||
114 | static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
115 | { | ||
116 | struct jz4740_adc *adc = get_irq_desc_data(desc); | ||
117 | uint8_t status; | ||
118 | unsigned int i; | ||
119 | |||
120 | status = readb(adc->base + JZ_REG_ADC_STATUS); | ||
121 | |||
122 | for (i = 0; i < 5; ++i) { | ||
123 | if (status & BIT(i)) | ||
124 | generic_handle_irq(adc->irq_base + i); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | |||
129 | /* Refcounting for the ADC clock is done in here instead of in the clock | ||
130 | * framework, because it is the only clock which is shared between multiple | ||
131 | * devices and thus is the only clock which needs refcounting */ | ||
132 | static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc) | ||
133 | { | ||
134 | if (atomic_inc_return(&adc->clk_ref) == 1) | ||
135 | clk_enable(adc->clk); | ||
136 | } | ||
137 | |||
138 | static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc) | ||
139 | { | ||
140 | if (atomic_dec_return(&adc->clk_ref) == 0) | ||
141 | clk_disable(adc->clk); | ||
142 | } | ||
143 | |||
144 | static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine, | ||
145 | bool enabled) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | uint8_t val; | ||
149 | |||
150 | spin_lock_irqsave(&adc->lock, flags); | ||
151 | |||
152 | val = readb(adc->base + JZ_REG_ADC_ENABLE); | ||
153 | if (enabled) | ||
154 | val |= BIT(engine); | ||
155 | else | ||
156 | val &= BIT(engine); | ||
157 | writeb(val, adc->base + JZ_REG_ADC_ENABLE); | ||
158 | |||
159 | spin_unlock_irqrestore(&adc->lock, flags); | ||
160 | } | ||
161 | |||
162 | static int jz4740_adc_cell_enable(struct platform_device *pdev) | ||
163 | { | ||
164 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
165 | |||
166 | jz4740_adc_clk_enable(adc); | ||
167 | jz4740_adc_set_enabled(adc, pdev->id, true); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int jz4740_adc_cell_disable(struct platform_device *pdev) | ||
173 | { | ||
174 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
175 | |||
176 | jz4740_adc_set_enabled(adc, pdev->id, false); | ||
177 | jz4740_adc_clk_disable(adc); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int jz4740_adc_set_config(struct device *dev, uint32_t mask, uint32_t val) | ||
183 | { | ||
184 | struct jz4740_adc *adc = dev_get_drvdata(dev); | ||
185 | unsigned long flags; | ||
186 | uint32_t cfg; | ||
187 | |||
188 | if (!adc) | ||
189 | return -ENODEV; | ||
190 | |||
191 | spin_lock_irqsave(&adc->lock, flags); | ||
192 | |||
193 | cfg = readl(adc->base + JZ_REG_ADC_CFG); | ||
194 | |||
195 | cfg &= ~mask; | ||
196 | cfg |= val; | ||
197 | |||
198 | writel(cfg, adc->base + JZ_REG_ADC_CFG); | ||
199 | |||
200 | spin_unlock_irqrestore(&adc->lock, flags); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(jz4740_adc_set_config); | ||
205 | |||
206 | static struct resource jz4740_hwmon_resources[] = { | ||
207 | { | ||
208 | .start = JZ_ADC_IRQ_ADCIN, | ||
209 | .flags = IORESOURCE_IRQ, | ||
210 | }, | ||
211 | { | ||
212 | .start = JZ_REG_ADC_HWMON_BASE, | ||
213 | .end = JZ_REG_ADC_HWMON_BASE + 3, | ||
214 | .flags = IORESOURCE_MEM, | ||
215 | }, | ||
216 | }; | ||
217 | |||
218 | static struct resource jz4740_battery_resources[] = { | ||
219 | { | ||
220 | .start = JZ_ADC_IRQ_BATTERY, | ||
221 | .flags = IORESOURCE_IRQ, | ||
222 | }, | ||
223 | { | ||
224 | .start = JZ_REG_ADC_BATTERY_BASE, | ||
225 | .end = JZ_REG_ADC_BATTERY_BASE + 3, | ||
226 | .flags = IORESOURCE_MEM, | ||
227 | }, | ||
228 | }; | ||
229 | |||
230 | const struct mfd_cell jz4740_adc_cells[] = { | ||
231 | { | ||
232 | .id = 0, | ||
233 | .name = "jz4740-hwmon", | ||
234 | .num_resources = ARRAY_SIZE(jz4740_hwmon_resources), | ||
235 | .resources = jz4740_hwmon_resources, | ||
236 | .platform_data = (void *)&jz4740_adc_cells[0], | ||
237 | .data_size = sizeof(struct mfd_cell), | ||
238 | |||
239 | .enable = jz4740_adc_cell_enable, | ||
240 | .disable = jz4740_adc_cell_disable, | ||
241 | }, | ||
242 | { | ||
243 | .id = 1, | ||
244 | .name = "jz4740-battery", | ||
245 | .num_resources = ARRAY_SIZE(jz4740_battery_resources), | ||
246 | .resources = jz4740_battery_resources, | ||
247 | .platform_data = (void *)&jz4740_adc_cells[1], | ||
248 | .data_size = sizeof(struct mfd_cell), | ||
249 | |||
250 | .enable = jz4740_adc_cell_enable, | ||
251 | .disable = jz4740_adc_cell_disable, | ||
252 | }, | ||
253 | }; | ||
254 | |||
255 | static int __devinit jz4740_adc_probe(struct platform_device *pdev) | ||
256 | { | ||
257 | int ret; | ||
258 | struct jz4740_adc *adc; | ||
259 | struct resource *mem_base; | ||
260 | int irq; | ||
261 | |||
262 | adc = kmalloc(sizeof(*adc), GFP_KERNEL); | ||
263 | if (!adc) { | ||
264 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | adc->irq = platform_get_irq(pdev, 0); | ||
269 | if (adc->irq < 0) { | ||
270 | ret = adc->irq; | ||
271 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); | ||
272 | goto err_free; | ||
273 | } | ||
274 | |||
275 | adc->irq_base = platform_get_irq(pdev, 1); | ||
276 | if (adc->irq_base < 0) { | ||
277 | ret = adc->irq_base; | ||
278 | dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret); | ||
279 | goto err_free; | ||
280 | } | ||
281 | |||
282 | mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
283 | if (!mem_base) { | ||
284 | ret = -ENOENT; | ||
285 | dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); | ||
286 | goto err_free; | ||
287 | } | ||
288 | |||
289 | /* Only request the shared registers for the MFD driver */ | ||
290 | adc->mem = request_mem_region(mem_base->start, JZ_REG_ADC_STATUS, | ||
291 | pdev->name); | ||
292 | if (!adc->mem) { | ||
293 | ret = -EBUSY; | ||
294 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
295 | goto err_free; | ||
296 | } | ||
297 | |||
298 | adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem)); | ||
299 | if (!adc->base) { | ||
300 | ret = -EBUSY; | ||
301 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
302 | goto err_release_mem_region; | ||
303 | } | ||
304 | |||
305 | adc->clk = clk_get(&pdev->dev, "adc"); | ||
306 | if (IS_ERR(adc->clk)) { | ||
307 | ret = PTR_ERR(adc->clk); | ||
308 | dev_err(&pdev->dev, "Failed to get clock: %d\n", ret); | ||
309 | goto err_iounmap; | ||
310 | } | ||
311 | |||
312 | spin_lock_init(&adc->lock); | ||
313 | atomic_set(&adc->clk_ref, 0); | ||
314 | |||
315 | platform_set_drvdata(pdev, adc); | ||
316 | |||
317 | for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) { | ||
318 | set_irq_chip_data(irq, adc); | ||
319 | set_irq_chip_and_handler(irq, &jz4740_adc_irq_chip, | ||
320 | handle_level_irq); | ||
321 | } | ||
322 | |||
323 | set_irq_data(adc->irq, adc); | ||
324 | set_irq_chained_handler(adc->irq, jz4740_adc_irq_demux); | ||
325 | |||
326 | writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); | ||
327 | writeb(0xff, adc->base + JZ_REG_ADC_CTRL); | ||
328 | |||
329 | ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, | ||
330 | ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base); | ||
331 | if (ret < 0) | ||
332 | goto err_clk_put; | ||
333 | |||
334 | return 0; | ||
335 | |||
336 | err_clk_put: | ||
337 | clk_put(adc->clk); | ||
338 | err_iounmap: | ||
339 | platform_set_drvdata(pdev, NULL); | ||
340 | iounmap(adc->base); | ||
341 | err_release_mem_region: | ||
342 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
343 | err_free: | ||
344 | kfree(adc); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit jz4740_adc_remove(struct platform_device *pdev) | ||
350 | { | ||
351 | struct jz4740_adc *adc = platform_get_drvdata(pdev); | ||
352 | |||
353 | mfd_remove_devices(&pdev->dev); | ||
354 | |||
355 | set_irq_data(adc->irq, NULL); | ||
356 | set_irq_chained_handler(adc->irq, NULL); | ||
357 | |||
358 | iounmap(adc->base); | ||
359 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
360 | |||
361 | clk_put(adc->clk); | ||
362 | |||
363 | platform_set_drvdata(pdev, NULL); | ||
364 | |||
365 | kfree(adc); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | struct platform_driver jz4740_adc_driver = { | ||
371 | .probe = jz4740_adc_probe, | ||
372 | .remove = __devexit_p(jz4740_adc_remove), | ||
373 | .driver = { | ||
374 | .name = "jz4740-adc", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | }; | ||
378 | |||
379 | static int __init jz4740_adc_init(void) | ||
380 | { | ||
381 | return platform_driver_register(&jz4740_adc_driver); | ||
382 | } | ||
383 | module_init(jz4740_adc_init); | ||
384 | |||
385 | static void __exit jz4740_adc_exit(void) | ||
386 | { | ||
387 | platform_driver_unregister(&jz4740_adc_driver); | ||
388 | } | ||
389 | module_exit(jz4740_adc_exit); | ||
390 | |||
391 | MODULE_DESCRIPTION("JZ4740 SoC ADC driver"); | ||
392 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_ALIAS("platform:jz4740-adc"); | ||
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index f621bcea3d02..04028a9ee082 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -90,6 +90,24 @@ static struct mfd_cell rtc_devs[] = { | |||
90 | }, | 90 | }, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static struct resource onkey_resources[] = { | ||
94 | { | ||
95 | .name = "max8925-onkey", | ||
96 | .start = MAX8925_IRQ_GPM_SW_3SEC, | ||
97 | .end = MAX8925_IRQ_GPM_SW_3SEC, | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static struct mfd_cell onkey_devs[] = { | ||
103 | { | ||
104 | .name = "max8925-onkey", | ||
105 | .num_resources = 1, | ||
106 | .resources = &onkey_resources[0], | ||
107 | .id = -1, | ||
108 | }, | ||
109 | }; | ||
110 | |||
93 | #define MAX8925_REG_RESOURCE(_start, _end) \ | 111 | #define MAX8925_REG_RESOURCE(_start, _end) \ |
94 | { \ | 112 | { \ |
95 | .start = MAX8925_##_start, \ | 113 | .start = MAX8925_##_start, \ |
@@ -596,6 +614,15 @@ int __devinit max8925_device_init(struct max8925_chip *chip, | |||
596 | dev_err(chip->dev, "Failed to add rtc subdev\n"); | 614 | dev_err(chip->dev, "Failed to add rtc subdev\n"); |
597 | goto out; | 615 | goto out; |
598 | } | 616 | } |
617 | |||
618 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
619 | ARRAY_SIZE(onkey_devs), | ||
620 | &onkey_resources[0], 0); | ||
621 | if (ret < 0) { | ||
622 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
623 | goto out_dev; | ||
624 | } | ||
625 | |||
599 | if (pdata && pdata->regulator[0]) { | 626 | if (pdata && pdata->regulator[0]) { |
600 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], | 627 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], |
601 | ARRAY_SIZE(regulator_devs), | 628 | ARRAY_SIZE(regulator_devs), |
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index e73f3f5252a8..0219115e00c7 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c | |||
@@ -173,7 +173,6 @@ static int __devexit max8925_remove(struct i2c_client *client) | |||
173 | max8925_device_exit(chip); | 173 | max8925_device_exit(chip); |
174 | i2c_unregister_device(chip->adc); | 174 | i2c_unregister_device(chip->adc); |
175 | i2c_unregister_device(chip->rtc); | 175 | i2c_unregister_device(chip->rtc); |
176 | i2c_set_clientdata(chip->i2c, NULL); | ||
177 | kfree(chip); | 176 | kfree(chip); |
178 | return 0; | 177 | return 0; |
179 | } | 178 | } |
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c new file mode 100644 index 000000000000..73e6f5c4efc9 --- /dev/null +++ b/drivers/mfd/max8998.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * max8698.c - mfd core driver for the Maxim 8998 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electronics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * Marek Szyprowski <m.szyprowski@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/mfd/core.h> | ||
30 | #include <linux/mfd/max8998.h> | ||
31 | #include <linux/mfd/max8998-private.h> | ||
32 | |||
33 | static struct mfd_cell max8998_devs[] = { | ||
34 | { | ||
35 | .name = "max8998-pmic", | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | static int max8998_i2c_device_read(struct max8998_dev *max8998, u8 reg, u8 *dest) | ||
40 | { | ||
41 | struct i2c_client *client = max8998->i2c_client; | ||
42 | int ret; | ||
43 | |||
44 | mutex_lock(&max8998->iolock); | ||
45 | ret = i2c_smbus_read_byte_data(client, reg); | ||
46 | mutex_unlock(&max8998->iolock); | ||
47 | if (ret < 0) | ||
48 | return ret; | ||
49 | |||
50 | ret &= 0xff; | ||
51 | *dest = ret; | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int max8998_i2c_device_write(struct max8998_dev *max8998, u8 reg, u8 value) | ||
56 | { | ||
57 | struct i2c_client *client = max8998->i2c_client; | ||
58 | int ret; | ||
59 | |||
60 | mutex_lock(&max8998->iolock); | ||
61 | ret = i2c_smbus_write_byte_data(client, reg, value); | ||
62 | mutex_unlock(&max8998->iolock); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | static int max8998_i2c_device_update(struct max8998_dev *max8998, u8 reg, | ||
67 | u8 val, u8 mask) | ||
68 | { | ||
69 | struct i2c_client *client = max8998->i2c_client; | ||
70 | int ret; | ||
71 | |||
72 | mutex_lock(&max8998->iolock); | ||
73 | ret = i2c_smbus_read_byte_data(client, reg); | ||
74 | if (ret >= 0) { | ||
75 | u8 old_val = ret & 0xff; | ||
76 | u8 new_val = (val & mask) | (old_val & (~mask)); | ||
77 | ret = i2c_smbus_write_byte_data(client, reg, new_val); | ||
78 | if (ret >= 0) | ||
79 | ret = 0; | ||
80 | } | ||
81 | mutex_unlock(&max8998->iolock); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int max8998_i2c_probe(struct i2c_client *i2c, | ||
86 | const struct i2c_device_id *id) | ||
87 | { | ||
88 | struct max8998_dev *max8998; | ||
89 | int ret = 0; | ||
90 | |||
91 | max8998 = kzalloc(sizeof(struct max8998_dev), GFP_KERNEL); | ||
92 | if (max8998 == NULL) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | i2c_set_clientdata(i2c, max8998); | ||
96 | max8998->dev = &i2c->dev; | ||
97 | max8998->i2c_client = i2c; | ||
98 | max8998->dev_read = max8998_i2c_device_read; | ||
99 | max8998->dev_write = max8998_i2c_device_write; | ||
100 | max8998->dev_update = max8998_i2c_device_update; | ||
101 | mutex_init(&max8998->iolock); | ||
102 | |||
103 | ret = mfd_add_devices(max8998->dev, -1, | ||
104 | max8998_devs, ARRAY_SIZE(max8998_devs), | ||
105 | NULL, 0); | ||
106 | if (ret < 0) | ||
107 | goto err; | ||
108 | |||
109 | return ret; | ||
110 | |||
111 | err: | ||
112 | mfd_remove_devices(max8998->dev); | ||
113 | kfree(max8998); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int max8998_i2c_remove(struct i2c_client *i2c) | ||
118 | { | ||
119 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); | ||
120 | |||
121 | mfd_remove_devices(max8998->dev); | ||
122 | kfree(max8998); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static const struct i2c_device_id max8998_i2c_id[] = { | ||
128 | { "max8998", 0 }, | ||
129 | { } | ||
130 | }; | ||
131 | MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); | ||
132 | |||
133 | static struct i2c_driver max8998_i2c_driver = { | ||
134 | .driver = { | ||
135 | .name = "max8998", | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | .probe = max8998_i2c_probe, | ||
139 | .remove = max8998_i2c_remove, | ||
140 | .id_table = max8998_i2c_id, | ||
141 | }; | ||
142 | |||
143 | static int __init max8998_i2c_init(void) | ||
144 | { | ||
145 | return i2c_add_driver(&max8998_i2c_driver); | ||
146 | } | ||
147 | /* init early so consumer devices can complete system boot */ | ||
148 | subsys_initcall(max8998_i2c_init); | ||
149 | |||
150 | static void __exit max8998_i2c_exit(void) | ||
151 | { | ||
152 | i2c_del_driver(&max8998_i2c_driver); | ||
153 | } | ||
154 | module_exit(max8998_i2c_exit); | ||
155 | |||
156 | MODULE_DESCRIPTION("MAXIM 8998 multi-function core driver"); | ||
157 | MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); | ||
158 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index fecf38a4f025..6df34989c1f6 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
@@ -11,9 +11,31 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/interrupt.h> | ||
14 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
15 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
16 | #include <linux/mfd/mc13783-private.h> | 19 | #include <linux/mfd/mc13783.h> |
20 | |||
21 | struct mc13783 { | ||
22 | struct spi_device *spidev; | ||
23 | struct mutex lock; | ||
24 | int irq; | ||
25 | int flags; | ||
26 | |||
27 | irq_handler_t irqhandler[MC13783_NUM_IRQ]; | ||
28 | void *irqdata[MC13783_NUM_IRQ]; | ||
29 | |||
30 | /* XXX these should go as platformdata to the regulator subdevice */ | ||
31 | struct mc13783_regulator_init_data *regulators; | ||
32 | int num_regulators; | ||
33 | }; | ||
34 | |||
35 | #define MC13783_REG_REVISION 7 | ||
36 | #define MC13783_REG_ADC_0 43 | ||
37 | #define MC13783_REG_ADC_1 44 | ||
38 | #define MC13783_REG_ADC_2 45 | ||
17 | 39 | ||
18 | #define MC13783_IRQSTAT0 0 | 40 | #define MC13783_IRQSTAT0 0 |
19 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) | 41 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) |
@@ -226,6 +248,12 @@ int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | |||
226 | } | 248 | } |
227 | EXPORT_SYMBOL(mc13783_reg_rmw); | 249 | EXPORT_SYMBOL(mc13783_reg_rmw); |
228 | 250 | ||
251 | int mc13783_get_flags(struct mc13783 *mc13783) | ||
252 | { | ||
253 | return mc13783->flags; | ||
254 | } | ||
255 | EXPORT_SYMBOL(mc13783_get_flags); | ||
256 | |||
229 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) | 257 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) |
230 | { | 258 | { |
231 | int ret; | 259 | int ret; |
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index 721948be12c7..4ba85bbdb4c1 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c | |||
@@ -128,6 +128,39 @@ | |||
128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ | 128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ |
129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ | 129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ |
130 | 130 | ||
131 | /* VCORE_CTRL1 register */ | ||
132 | #define VCORE_CTRL1_BYP_COMP (1 << 5) | ||
133 | #define VCORE_CTRL1_HW_NSW (1 << 7) | ||
134 | |||
135 | /* GPIO_CTRL register */ | ||
136 | #define GPIO_CTRL_SLOTSELEN (1 << 5) | ||
137 | #define GPIO_CTRL_SLPCTLEN (1 << 6) | ||
138 | #define GPIO1_DIR_INPUT (1 << 0) | ||
139 | #define GPIO2_DIR_INPUT (1 << 1) | ||
140 | #define GPIO3_DIR_INPUT (1 << 2) | ||
141 | |||
142 | /* MCT_CTRL1 register */ | ||
143 | #define MCT_CTRL1_S1_CMD_OD (1 << 2) | ||
144 | #define MCT_CTRL1_S2_CMD_OD (1 << 3) | ||
145 | |||
146 | /* MCT_CTRL2 register */ | ||
147 | #define MCT_CTRL2_VS2_SEL_D0 (1 << 0) | ||
148 | #define MCT_CTRL2_VS2_SEL_D1 (1 << 1) | ||
149 | #define MCT_CTRL2_S1CD_BUFEN (1 << 4) | ||
150 | #define MCT_CTRL2_S2CD_BUFEN (1 << 5) | ||
151 | #define MCT_CTRL2_S1CD_DBEN (1 << 6) | ||
152 | #define MCT_CTRL2_S2CD_BEN (1 << 7) | ||
153 | |||
154 | /* MCT_CTRL3 register */ | ||
155 | #define MCT_CTRL3_SLOT1_EN (1 << 0) | ||
156 | #define MCT_CTRL3_SLOT2_EN (1 << 1) | ||
157 | #define MCT_CTRL3_S1_AUTO_EN (1 << 2) | ||
158 | #define MCT_CTRL3_S2_AUTO_EN (1 << 3) | ||
159 | |||
160 | /* MCT_PIN_ST register */ | ||
161 | #define MCT_PIN_ST_S1_CD_ST (1 << 0) | ||
162 | #define MCT_PIN_ST_S2_CD_ST (1 << 1) | ||
163 | |||
131 | static void menelaus_work(struct work_struct *_menelaus); | 164 | static void menelaus_work(struct work_struct *_menelaus); |
132 | 165 | ||
133 | struct menelaus_chip { | 166 | struct menelaus_chip { |
@@ -249,10 +282,10 @@ static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw) | |||
249 | return; | 282 | return; |
250 | 283 | ||
251 | if (!(reg & 0x1)) | 284 | if (!(reg & 0x1)) |
252 | card_mask |= (1 << 0); | 285 | card_mask |= MCT_PIN_ST_S1_CD_ST; |
253 | 286 | ||
254 | if (!(reg & 0x2)) | 287 | if (!(reg & 0x2)) |
255 | card_mask |= (1 << 1); | 288 | card_mask |= MCT_PIN_ST_S2_CD_ST; |
256 | 289 | ||
257 | if (menelaus_hw->mmc_callback) | 290 | if (menelaus_hw->mmc_callback) |
258 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, | 291 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, |
@@ -277,14 +310,14 @@ int menelaus_set_mmc_opendrain(int slot, int enable) | |||
277 | val = ret; | 310 | val = ret; |
278 | if (slot == 1) { | 311 | if (slot == 1) { |
279 | if (enable) | 312 | if (enable) |
280 | val |= 1 << 2; | 313 | val |= MCT_CTRL1_S1_CMD_OD; |
281 | else | 314 | else |
282 | val &= ~(1 << 2); | 315 | val &= ~MCT_CTRL1_S1_CMD_OD; |
283 | } else { | 316 | } else { |
284 | if (enable) | 317 | if (enable) |
285 | val |= 1 << 3; | 318 | val |= MCT_CTRL1_S2_CMD_OD; |
286 | else | 319 | else |
287 | val &= ~(1 << 3); | 320 | val &= ~MCT_CTRL1_S2_CMD_OD; |
288 | } | 321 | } |
289 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); | 322 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); |
290 | mutex_unlock(&the_menelaus->lock); | 323 | mutex_unlock(&the_menelaus->lock); |
@@ -301,11 +334,11 @@ int menelaus_set_slot_sel(int enable) | |||
301 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 334 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
302 | if (ret < 0) | 335 | if (ret < 0) |
303 | goto out; | 336 | goto out; |
304 | ret |= 0x02; | 337 | ret |= GPIO2_DIR_INPUT; |
305 | if (enable) | 338 | if (enable) |
306 | ret |= 1 << 5; | 339 | ret |= GPIO_CTRL_SLOTSELEN; |
307 | else | 340 | else |
308 | ret &= ~(1 << 5); | 341 | ret &= ~GPIO_CTRL_SLOTSELEN; |
309 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); | 342 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); |
310 | out: | 343 | out: |
311 | mutex_unlock(&the_menelaus->lock); | 344 | mutex_unlock(&the_menelaus->lock); |
@@ -330,14 +363,14 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
330 | val = ret; | 363 | val = ret; |
331 | if (slot == 1) { | 364 | if (slot == 1) { |
332 | if (cd_en) | 365 | if (cd_en) |
333 | val |= (1 << 4) | (1 << 6); | 366 | val |= MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN; |
334 | else | 367 | else |
335 | val &= ~((1 << 4) | (1 << 6)); | 368 | val &= ~(MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN); |
336 | } else { | 369 | } else { |
337 | if (cd_en) | 370 | if (cd_en) |
338 | val |= (1 << 5) | (1 << 7); | 371 | val |= MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN; |
339 | else | 372 | else |
340 | val &= ~((1 << 5) | (1 << 7)); | 373 | val &= ~(MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN); |
341 | } | 374 | } |
342 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); | 375 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); |
343 | if (ret < 0) | 376 | if (ret < 0) |
@@ -349,25 +382,25 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
349 | val = ret; | 382 | val = ret; |
350 | if (slot == 1) { | 383 | if (slot == 1) { |
351 | if (enable) | 384 | if (enable) |
352 | val |= 1 << 0; | 385 | val |= MCT_CTRL3_SLOT1_EN; |
353 | else | 386 | else |
354 | val &= ~(1 << 0); | 387 | val &= ~MCT_CTRL3_SLOT1_EN; |
355 | } else { | 388 | } else { |
356 | int b; | 389 | int b; |
357 | 390 | ||
358 | if (enable) | 391 | if (enable) |
359 | ret |= 1 << 1; | 392 | val |= MCT_CTRL3_SLOT2_EN; |
360 | else | 393 | else |
361 | ret &= ~(1 << 1); | 394 | val &= ~MCT_CTRL3_SLOT2_EN; |
362 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); | 395 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); |
363 | b &= ~0x03; | 396 | b &= ~(MCT_CTRL2_VS2_SEL_D0 | MCT_CTRL2_VS2_SEL_D1); |
364 | b |= power; | 397 | b |= power; |
365 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); | 398 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); |
366 | if (ret < 0) | 399 | if (ret < 0) |
367 | goto out; | 400 | goto out; |
368 | } | 401 | } |
369 | /* Disable autonomous shutdown */ | 402 | /* Disable autonomous shutdown */ |
370 | val &= ~(0x03 << 2); | 403 | val &= ~(MCT_CTRL3_S1_AUTO_EN | MCT_CTRL3_S2_AUTO_EN); |
371 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); | 404 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); |
372 | out: | 405 | out: |
373 | mutex_unlock(&the_menelaus->lock); | 406 | mutex_unlock(&the_menelaus->lock); |
@@ -552,7 +585,7 @@ int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV) | |||
552 | if (!the_menelaus->vcore_hw_mode) { | 585 | if (!the_menelaus->vcore_hw_mode) { |
553 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); | 586 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); |
554 | /* HW mode, turn OFF byte comparator */ | 587 | /* HW mode, turn OFF byte comparator */ |
555 | val |= ((1 << 7) | (1 << 5)); | 588 | val |= (VCORE_CTRL1_HW_NSW | VCORE_CTRL1_BYP_COMP); |
556 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); | 589 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); |
557 | the_menelaus->vcore_hw_mode = 1; | 590 | the_menelaus->vcore_hw_mode = 1; |
558 | } | 591 | } |
@@ -749,7 +782,7 @@ int menelaus_set_regulator_sleep(int enable, u32 val) | |||
749 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 782 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
750 | if (ret < 0) | 783 | if (ret < 0) |
751 | goto out; | 784 | goto out; |
752 | t = ((1 << 6) | 0x04); | 785 | t = (GPIO_CTRL_SLPCTLEN | GPIO3_DIR_INPUT); |
753 | if (enable) | 786 | if (enable) |
754 | ret |= t; | 787 | ret |= t; |
755 | else | 788 | else |
@@ -1228,7 +1261,6 @@ fail2: | |||
1228 | free_irq(client->irq, menelaus); | 1261 | free_irq(client->irq, menelaus); |
1229 | flush_scheduled_work(); | 1262 | flush_scheduled_work(); |
1230 | fail1: | 1263 | fail1: |
1231 | i2c_set_clientdata(client, NULL); | ||
1232 | kfree(menelaus); | 1264 | kfree(menelaus); |
1233 | return err; | 1265 | return err; |
1234 | } | 1266 | } |
@@ -1238,7 +1270,6 @@ static int __exit menelaus_remove(struct i2c_client *client) | |||
1238 | struct menelaus_chip *menelaus = i2c_get_clientdata(client); | 1270 | struct menelaus_chip *menelaus = i2c_get_clientdata(client); |
1239 | 1271 | ||
1240 | free_irq(client->irq, menelaus); | 1272 | free_irq(client->irq, menelaus); |
1241 | i2c_set_clientdata(client, NULL); | ||
1242 | kfree(menelaus); | 1273 | kfree(menelaus); |
1243 | the_menelaus = NULL; | 1274 | the_menelaus = NULL; |
1244 | return 0; | 1275 | return 0; |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 7dd76bceaae8..1823a57b7d8f 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -70,7 +70,9 @@ static int mfd_add_device(struct device *parent, int id, | |||
70 | goto fail_res; | 70 | goto fail_res; |
71 | } | 71 | } |
72 | 72 | ||
73 | platform_device_add_resources(pdev, res, cell->num_resources); | 73 | ret = platform_device_add_resources(pdev, res, cell->num_resources); |
74 | if (ret) | ||
75 | goto fail_res; | ||
74 | 76 | ||
75 | ret = platform_device_add(pdev); | 77 | ret = platform_device_add(pdev); |
76 | if (ret) | 78 | if (ret) |
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 704736e6e9b9..23e585527285 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -336,7 +336,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
336 | return 0; | 336 | return 0; |
337 | 337 | ||
338 | err_free: | 338 | err_free: |
339 | i2c_set_clientdata(client, NULL); | ||
340 | kfree(pcf); | 339 | kfree(pcf); |
341 | 340 | ||
342 | return ret; | 341 | return ret; |
@@ -357,7 +356,6 @@ static int __devexit pcf50633_remove(struct i2c_client *client) | |||
357 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) | 356 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) |
358 | platform_device_unregister(pcf->regulator_pdev[i]); | 357 | platform_device_unregister(pcf->regulator_pdev[i]); |
359 | 358 | ||
360 | i2c_set_clientdata(client, NULL); | ||
361 | kfree(pcf); | 359 | kfree(pcf); |
362 | 360 | ||
363 | return 0; | 361 | return 0; |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c new file mode 100644 index 000000000000..0754c5e91995 --- /dev/null +++ b/drivers/mfd/stmpe.c | |||
@@ -0,0 +1,985 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mfd/core.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | #include "stmpe.h" | ||
17 | |||
18 | static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
19 | { | ||
20 | return stmpe->variant->enable(stmpe, blocks, true); | ||
21 | } | ||
22 | |||
23 | static int __stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
24 | { | ||
25 | return stmpe->variant->enable(stmpe, blocks, false); | ||
26 | } | ||
27 | |||
28 | static int __stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
29 | { | ||
30 | int ret; | ||
31 | |||
32 | ret = i2c_smbus_read_byte_data(stmpe->i2c, reg); | ||
33 | if (ret < 0) | ||
34 | dev_err(stmpe->dev, "failed to read reg %#x: %d\n", | ||
35 | reg, ret); | ||
36 | |||
37 | dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret); | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
43 | { | ||
44 | int ret; | ||
45 | |||
46 | dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val); | ||
47 | |||
48 | ret = i2c_smbus_write_byte_data(stmpe->i2c, reg, val); | ||
49 | if (ret < 0) | ||
50 | dev_err(stmpe->dev, "failed to write reg %#x: %d\n", | ||
51 | reg, ret); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | static int __stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
57 | { | ||
58 | int ret; | ||
59 | |||
60 | ret = __stmpe_reg_read(stmpe, reg); | ||
61 | if (ret < 0) | ||
62 | return ret; | ||
63 | |||
64 | ret &= ~mask; | ||
65 | ret |= val; | ||
66 | |||
67 | return __stmpe_reg_write(stmpe, reg, ret); | ||
68 | } | ||
69 | |||
70 | static int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, | ||
71 | u8 *values) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = i2c_smbus_read_i2c_block_data(stmpe->i2c, reg, length, values); | ||
76 | if (ret < 0) | ||
77 | dev_err(stmpe->dev, "failed to read regs %#x: %d\n", | ||
78 | reg, ret); | ||
79 | |||
80 | dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret); | ||
81 | stmpe_dump_bytes("stmpe rd: ", values, length); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
87 | const u8 *values) | ||
88 | { | ||
89 | int ret; | ||
90 | |||
91 | dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length); | ||
92 | stmpe_dump_bytes("stmpe wr: ", values, length); | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(stmpe->i2c, reg, length, | ||
95 | values); | ||
96 | if (ret < 0) | ||
97 | dev_err(stmpe->dev, "failed to write regs %#x: %d\n", | ||
98 | reg, ret); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * stmpe_enable - enable blocks on an STMPE device | ||
105 | * @stmpe: Device to work on | ||
106 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
107 | */ | ||
108 | int stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
109 | { | ||
110 | int ret; | ||
111 | |||
112 | mutex_lock(&stmpe->lock); | ||
113 | ret = __stmpe_enable(stmpe, blocks); | ||
114 | mutex_unlock(&stmpe->lock); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | EXPORT_SYMBOL_GPL(stmpe_enable); | ||
119 | |||
120 | /** | ||
121 | * stmpe_disable - disable blocks on an STMPE device | ||
122 | * @stmpe: Device to work on | ||
123 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
124 | */ | ||
125 | int stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | mutex_lock(&stmpe->lock); | ||
130 | ret = __stmpe_disable(stmpe, blocks); | ||
131 | mutex_unlock(&stmpe->lock); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(stmpe_disable); | ||
136 | |||
137 | /** | ||
138 | * stmpe_reg_read() - read a single STMPE register | ||
139 | * @stmpe: Device to read from | ||
140 | * @reg: Register to read | ||
141 | */ | ||
142 | int stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | mutex_lock(&stmpe->lock); | ||
147 | ret = __stmpe_reg_read(stmpe, reg); | ||
148 | mutex_unlock(&stmpe->lock); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | EXPORT_SYMBOL_GPL(stmpe_reg_read); | ||
153 | |||
154 | /** | ||
155 | * stmpe_reg_write() - write a single STMPE register | ||
156 | * @stmpe: Device to write to | ||
157 | * @reg: Register to write | ||
158 | * @val: Value to write | ||
159 | */ | ||
160 | int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | mutex_lock(&stmpe->lock); | ||
165 | ret = __stmpe_reg_write(stmpe, reg, val); | ||
166 | mutex_unlock(&stmpe->lock); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(stmpe_reg_write); | ||
171 | |||
172 | /** | ||
173 | * stmpe_set_bits() - set the value of a bitfield in a STMPE register | ||
174 | * @stmpe: Device to write to | ||
175 | * @reg: Register to write | ||
176 | * @mask: Mask of bits to set | ||
177 | * @val: Value to set | ||
178 | */ | ||
179 | int stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
180 | { | ||
181 | int ret; | ||
182 | |||
183 | mutex_lock(&stmpe->lock); | ||
184 | ret = __stmpe_set_bits(stmpe, reg, mask, val); | ||
185 | mutex_unlock(&stmpe->lock); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(stmpe_set_bits); | ||
190 | |||
191 | /** | ||
192 | * stmpe_block_read() - read multiple STMPE registers | ||
193 | * @stmpe: Device to read from | ||
194 | * @reg: First register | ||
195 | * @length: Number of registers | ||
196 | * @values: Buffer to write to | ||
197 | */ | ||
198 | int stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values) | ||
199 | { | ||
200 | int ret; | ||
201 | |||
202 | mutex_lock(&stmpe->lock); | ||
203 | ret = __stmpe_block_read(stmpe, reg, length, values); | ||
204 | mutex_unlock(&stmpe->lock); | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(stmpe_block_read); | ||
209 | |||
210 | /** | ||
211 | * stmpe_block_write() - write multiple STMPE registers | ||
212 | * @stmpe: Device to write to | ||
213 | * @reg: First register | ||
214 | * @length: Number of registers | ||
215 | * @values: Values to write | ||
216 | */ | ||
217 | int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
218 | const u8 *values) | ||
219 | { | ||
220 | int ret; | ||
221 | |||
222 | mutex_lock(&stmpe->lock); | ||
223 | ret = __stmpe_block_write(stmpe, reg, length, values); | ||
224 | mutex_unlock(&stmpe->lock); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(stmpe_block_write); | ||
229 | |||
230 | /** | ||
231 | * stmpe_set_altfunc: set the alternate function for STMPE pins | ||
232 | * @stmpe: Device to configure | ||
233 | * @pins: Bitmask of pins to affect | ||
234 | * @block: block to enable alternate functions for | ||
235 | * | ||
236 | * @pins is assumed to have a bit set for each of the bits whose alternate | ||
237 | * function is to be changed, numbered according to the GPIOXY numbers. | ||
238 | * | ||
239 | * If the GPIO module is not enabled, this function automatically enables it in | ||
240 | * order to perform the change. | ||
241 | */ | ||
242 | int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block) | ||
243 | { | ||
244 | struct stmpe_variant_info *variant = stmpe->variant; | ||
245 | u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; | ||
246 | int af_bits = variant->af_bits; | ||
247 | int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); | ||
248 | int afperreg = 8 / af_bits; | ||
249 | int mask = (1 << af_bits) - 1; | ||
250 | u8 regs[numregs]; | ||
251 | int af; | ||
252 | int ret; | ||
253 | |||
254 | mutex_lock(&stmpe->lock); | ||
255 | |||
256 | ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
257 | if (ret < 0) | ||
258 | goto out; | ||
259 | |||
260 | ret = __stmpe_block_read(stmpe, regaddr, numregs, regs); | ||
261 | if (ret < 0) | ||
262 | goto out; | ||
263 | |||
264 | af = variant->get_altfunc(stmpe, block); | ||
265 | |||
266 | while (pins) { | ||
267 | int pin = __ffs(pins); | ||
268 | int regoffset = numregs - (pin / afperreg) - 1; | ||
269 | int pos = (pin % afperreg) * (8 / afperreg); | ||
270 | |||
271 | regs[regoffset] &= ~(mask << pos); | ||
272 | regs[regoffset] |= af << pos; | ||
273 | |||
274 | pins &= ~(1 << pin); | ||
275 | } | ||
276 | |||
277 | ret = __stmpe_block_write(stmpe, regaddr, numregs, regs); | ||
278 | |||
279 | out: | ||
280 | mutex_unlock(&stmpe->lock); | ||
281 | return ret; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(stmpe_set_altfunc); | ||
284 | |||
285 | /* | ||
286 | * GPIO (all variants) | ||
287 | */ | ||
288 | |||
289 | static struct resource stmpe_gpio_resources[] = { | ||
290 | /* Start and end filled dynamically */ | ||
291 | { | ||
292 | .flags = IORESOURCE_IRQ, | ||
293 | }, | ||
294 | }; | ||
295 | |||
296 | static struct mfd_cell stmpe_gpio_cell = { | ||
297 | .name = "stmpe-gpio", | ||
298 | .resources = stmpe_gpio_resources, | ||
299 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), | ||
300 | }; | ||
301 | |||
302 | /* | ||
303 | * Keypad (1601, 2401, 2403) | ||
304 | */ | ||
305 | |||
306 | static struct resource stmpe_keypad_resources[] = { | ||
307 | { | ||
308 | .name = "KEYPAD", | ||
309 | .start = 0, | ||
310 | .end = 0, | ||
311 | .flags = IORESOURCE_IRQ, | ||
312 | }, | ||
313 | { | ||
314 | .name = "KEYPAD_OVER", | ||
315 | .start = 1, | ||
316 | .end = 1, | ||
317 | .flags = IORESOURCE_IRQ, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static struct mfd_cell stmpe_keypad_cell = { | ||
322 | .name = "stmpe-keypad", | ||
323 | .resources = stmpe_keypad_resources, | ||
324 | .num_resources = ARRAY_SIZE(stmpe_keypad_resources), | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | * Touchscreen (STMPE811) | ||
329 | */ | ||
330 | |||
331 | static struct resource stmpe_ts_resources[] = { | ||
332 | { | ||
333 | .name = "TOUCH_DET", | ||
334 | .start = 0, | ||
335 | .end = 0, | ||
336 | .flags = IORESOURCE_IRQ, | ||
337 | }, | ||
338 | { | ||
339 | .name = "FIFO_TH", | ||
340 | .start = 1, | ||
341 | .end = 1, | ||
342 | .flags = IORESOURCE_IRQ, | ||
343 | }, | ||
344 | }; | ||
345 | |||
346 | static struct mfd_cell stmpe_ts_cell = { | ||
347 | .name = "stmpe-ts", | ||
348 | .resources = stmpe_ts_resources, | ||
349 | .num_resources = ARRAY_SIZE(stmpe_ts_resources), | ||
350 | }; | ||
351 | |||
352 | /* | ||
353 | * STMPE811 | ||
354 | */ | ||
355 | |||
356 | static const u8 stmpe811_regs[] = { | ||
357 | [STMPE_IDX_CHIP_ID] = STMPE811_REG_CHIP_ID, | ||
358 | [STMPE_IDX_ICR_LSB] = STMPE811_REG_INT_CTRL, | ||
359 | [STMPE_IDX_IER_LSB] = STMPE811_REG_INT_EN, | ||
360 | [STMPE_IDX_ISR_MSB] = STMPE811_REG_INT_STA, | ||
361 | [STMPE_IDX_GPMR_LSB] = STMPE811_REG_GPIO_MP_STA, | ||
362 | [STMPE_IDX_GPSR_LSB] = STMPE811_REG_GPIO_SET_PIN, | ||
363 | [STMPE_IDX_GPCR_LSB] = STMPE811_REG_GPIO_CLR_PIN, | ||
364 | [STMPE_IDX_GPDR_LSB] = STMPE811_REG_GPIO_DIR, | ||
365 | [STMPE_IDX_GPRER_LSB] = STMPE811_REG_GPIO_RE, | ||
366 | [STMPE_IDX_GPFER_LSB] = STMPE811_REG_GPIO_FE, | ||
367 | [STMPE_IDX_GPAFR_U_MSB] = STMPE811_REG_GPIO_AF, | ||
368 | [STMPE_IDX_IEGPIOR_LSB] = STMPE811_REG_GPIO_INT_EN, | ||
369 | [STMPE_IDX_ISGPIOR_MSB] = STMPE811_REG_GPIO_INT_STA, | ||
370 | [STMPE_IDX_GPEDR_MSB] = STMPE811_REG_GPIO_ED, | ||
371 | }; | ||
372 | |||
373 | static struct stmpe_variant_block stmpe811_blocks[] = { | ||
374 | { | ||
375 | .cell = &stmpe_gpio_cell, | ||
376 | .irq = STMPE811_IRQ_GPIOC, | ||
377 | .block = STMPE_BLOCK_GPIO, | ||
378 | }, | ||
379 | { | ||
380 | .cell = &stmpe_ts_cell, | ||
381 | .irq = STMPE811_IRQ_TOUCH_DET, | ||
382 | .block = STMPE_BLOCK_TOUCHSCREEN, | ||
383 | }, | ||
384 | }; | ||
385 | |||
386 | static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, | ||
387 | bool enable) | ||
388 | { | ||
389 | unsigned int mask = 0; | ||
390 | |||
391 | if (blocks & STMPE_BLOCK_GPIO) | ||
392 | mask |= STMPE811_SYS_CTRL2_GPIO_OFF; | ||
393 | |||
394 | if (blocks & STMPE_BLOCK_ADC) | ||
395 | mask |= STMPE811_SYS_CTRL2_ADC_OFF; | ||
396 | |||
397 | if (blocks & STMPE_BLOCK_TOUCHSCREEN) | ||
398 | mask |= STMPE811_SYS_CTRL2_TSC_OFF; | ||
399 | |||
400 | return __stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask, | ||
401 | enable ? 0 : mask); | ||
402 | } | ||
403 | |||
404 | static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
405 | { | ||
406 | /* 0 for touchscreen, 1 for GPIO */ | ||
407 | return block != STMPE_BLOCK_TOUCHSCREEN; | ||
408 | } | ||
409 | |||
410 | static struct stmpe_variant_info stmpe811 = { | ||
411 | .name = "stmpe811", | ||
412 | .id_val = 0x0811, | ||
413 | .id_mask = 0xffff, | ||
414 | .num_gpios = 8, | ||
415 | .af_bits = 1, | ||
416 | .regs = stmpe811_regs, | ||
417 | .blocks = stmpe811_blocks, | ||
418 | .num_blocks = ARRAY_SIZE(stmpe811_blocks), | ||
419 | .num_irqs = STMPE811_NR_INTERNAL_IRQS, | ||
420 | .enable = stmpe811_enable, | ||
421 | .get_altfunc = stmpe811_get_altfunc, | ||
422 | }; | ||
423 | |||
424 | /* | ||
425 | * STMPE1601 | ||
426 | */ | ||
427 | |||
428 | static const u8 stmpe1601_regs[] = { | ||
429 | [STMPE_IDX_CHIP_ID] = STMPE1601_REG_CHIP_ID, | ||
430 | [STMPE_IDX_ICR_LSB] = STMPE1601_REG_ICR_LSB, | ||
431 | [STMPE_IDX_IER_LSB] = STMPE1601_REG_IER_LSB, | ||
432 | [STMPE_IDX_ISR_MSB] = STMPE1601_REG_ISR_MSB, | ||
433 | [STMPE_IDX_GPMR_LSB] = STMPE1601_REG_GPIO_MP_LSB, | ||
434 | [STMPE_IDX_GPSR_LSB] = STMPE1601_REG_GPIO_SET_LSB, | ||
435 | [STMPE_IDX_GPCR_LSB] = STMPE1601_REG_GPIO_CLR_LSB, | ||
436 | [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, | ||
437 | [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, | ||
438 | [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, | ||
439 | [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, | ||
440 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, | ||
441 | [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, | ||
442 | [STMPE_IDX_GPEDR_MSB] = STMPE1601_REG_GPIO_ED_MSB, | ||
443 | }; | ||
444 | |||
445 | static struct stmpe_variant_block stmpe1601_blocks[] = { | ||
446 | { | ||
447 | .cell = &stmpe_gpio_cell, | ||
448 | .irq = STMPE24XX_IRQ_GPIOC, | ||
449 | .block = STMPE_BLOCK_GPIO, | ||
450 | }, | ||
451 | { | ||
452 | .cell = &stmpe_keypad_cell, | ||
453 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
454 | .block = STMPE_BLOCK_KEYPAD, | ||
455 | }, | ||
456 | }; | ||
457 | |||
458 | /* supported autosleep timeout delay (in msecs) */ | ||
459 | static const int stmpe_autosleep_delay[] = { | ||
460 | 4, 16, 32, 64, 128, 256, 512, 1024, | ||
461 | }; | ||
462 | |||
463 | static int stmpe_round_timeout(int timeout) | ||
464 | { | ||
465 | int i; | ||
466 | |||
467 | for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) { | ||
468 | if (stmpe_autosleep_delay[i] >= timeout) | ||
469 | return i; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * requests for delays longer than supported should not return the | ||
474 | * longest supported delay | ||
475 | */ | ||
476 | return -EINVAL; | ||
477 | } | ||
478 | |||
479 | static int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | if (!stmpe->variant->enable_autosleep) | ||
484 | return -ENOSYS; | ||
485 | |||
486 | mutex_lock(&stmpe->lock); | ||
487 | ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout); | ||
488 | mutex_unlock(&stmpe->lock); | ||
489 | |||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * Both stmpe 1601/2403 support same layout for autosleep | ||
495 | */ | ||
496 | static int stmpe1601_autosleep(struct stmpe *stmpe, | ||
497 | int autosleep_timeout) | ||
498 | { | ||
499 | int ret, timeout; | ||
500 | |||
501 | /* choose the best available timeout */ | ||
502 | timeout = stmpe_round_timeout(autosleep_timeout); | ||
503 | if (timeout < 0) { | ||
504 | dev_err(stmpe->dev, "invalid timeout\n"); | ||
505 | return timeout; | ||
506 | } | ||
507 | |||
508 | ret = __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
509 | STMPE1601_AUTOSLEEP_TIMEOUT_MASK, | ||
510 | timeout); | ||
511 | if (ret < 0) | ||
512 | return ret; | ||
513 | |||
514 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
515 | STPME1601_AUTOSLEEP_ENABLE, | ||
516 | STPME1601_AUTOSLEEP_ENABLE); | ||
517 | } | ||
518 | |||
519 | static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks, | ||
520 | bool enable) | ||
521 | { | ||
522 | unsigned int mask = 0; | ||
523 | |||
524 | if (blocks & STMPE_BLOCK_GPIO) | ||
525 | mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO; | ||
526 | |||
527 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
528 | mask |= STMPE1601_SYS_CTRL_ENABLE_KPC; | ||
529 | |||
530 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask, | ||
531 | enable ? mask : 0); | ||
532 | } | ||
533 | |||
534 | static int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
535 | { | ||
536 | switch (block) { | ||
537 | case STMPE_BLOCK_PWM: | ||
538 | return 2; | ||
539 | |||
540 | case STMPE_BLOCK_KEYPAD: | ||
541 | return 1; | ||
542 | |||
543 | case STMPE_BLOCK_GPIO: | ||
544 | default: | ||
545 | return 0; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static struct stmpe_variant_info stmpe1601 = { | ||
550 | .name = "stmpe1601", | ||
551 | .id_val = 0x0210, | ||
552 | .id_mask = 0xfff0, /* at least 0x0210 and 0x0212 */ | ||
553 | .num_gpios = 16, | ||
554 | .af_bits = 2, | ||
555 | .regs = stmpe1601_regs, | ||
556 | .blocks = stmpe1601_blocks, | ||
557 | .num_blocks = ARRAY_SIZE(stmpe1601_blocks), | ||
558 | .num_irqs = STMPE1601_NR_INTERNAL_IRQS, | ||
559 | .enable = stmpe1601_enable, | ||
560 | .get_altfunc = stmpe1601_get_altfunc, | ||
561 | .enable_autosleep = stmpe1601_autosleep, | ||
562 | }; | ||
563 | |||
564 | /* | ||
565 | * STMPE24XX | ||
566 | */ | ||
567 | |||
568 | static const u8 stmpe24xx_regs[] = { | ||
569 | [STMPE_IDX_CHIP_ID] = STMPE24XX_REG_CHIP_ID, | ||
570 | [STMPE_IDX_ICR_LSB] = STMPE24XX_REG_ICR_LSB, | ||
571 | [STMPE_IDX_IER_LSB] = STMPE24XX_REG_IER_LSB, | ||
572 | [STMPE_IDX_ISR_MSB] = STMPE24XX_REG_ISR_MSB, | ||
573 | [STMPE_IDX_GPMR_LSB] = STMPE24XX_REG_GPMR_LSB, | ||
574 | [STMPE_IDX_GPSR_LSB] = STMPE24XX_REG_GPSR_LSB, | ||
575 | [STMPE_IDX_GPCR_LSB] = STMPE24XX_REG_GPCR_LSB, | ||
576 | [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, | ||
577 | [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, | ||
578 | [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, | ||
579 | [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, | ||
580 | [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, | ||
581 | [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, | ||
582 | [STMPE_IDX_GPEDR_MSB] = STMPE24XX_REG_GPEDR_MSB, | ||
583 | }; | ||
584 | |||
585 | static struct stmpe_variant_block stmpe24xx_blocks[] = { | ||
586 | { | ||
587 | .cell = &stmpe_gpio_cell, | ||
588 | .irq = STMPE24XX_IRQ_GPIOC, | ||
589 | .block = STMPE_BLOCK_GPIO, | ||
590 | }, | ||
591 | { | ||
592 | .cell = &stmpe_keypad_cell, | ||
593 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
594 | .block = STMPE_BLOCK_KEYPAD, | ||
595 | }, | ||
596 | }; | ||
597 | |||
598 | static int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks, | ||
599 | bool enable) | ||
600 | { | ||
601 | unsigned int mask = 0; | ||
602 | |||
603 | if (blocks & STMPE_BLOCK_GPIO) | ||
604 | mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO; | ||
605 | |||
606 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
607 | mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC; | ||
608 | |||
609 | return __stmpe_set_bits(stmpe, STMPE24XX_REG_SYS_CTRL, mask, | ||
610 | enable ? mask : 0); | ||
611 | } | ||
612 | |||
613 | static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
614 | { | ||
615 | switch (block) { | ||
616 | case STMPE_BLOCK_ROTATOR: | ||
617 | return 2; | ||
618 | |||
619 | case STMPE_BLOCK_KEYPAD: | ||
620 | return 1; | ||
621 | |||
622 | case STMPE_BLOCK_GPIO: | ||
623 | default: | ||
624 | return 0; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | static struct stmpe_variant_info stmpe2401 = { | ||
629 | .name = "stmpe2401", | ||
630 | .id_val = 0x0101, | ||
631 | .id_mask = 0xffff, | ||
632 | .num_gpios = 24, | ||
633 | .af_bits = 2, | ||
634 | .regs = stmpe24xx_regs, | ||
635 | .blocks = stmpe24xx_blocks, | ||
636 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
637 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
638 | .enable = stmpe24xx_enable, | ||
639 | .get_altfunc = stmpe24xx_get_altfunc, | ||
640 | }; | ||
641 | |||
642 | static struct stmpe_variant_info stmpe2403 = { | ||
643 | .name = "stmpe2403", | ||
644 | .id_val = 0x0120, | ||
645 | .id_mask = 0xffff, | ||
646 | .num_gpios = 24, | ||
647 | .af_bits = 2, | ||
648 | .regs = stmpe24xx_regs, | ||
649 | .blocks = stmpe24xx_blocks, | ||
650 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
651 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
652 | .enable = stmpe24xx_enable, | ||
653 | .get_altfunc = stmpe24xx_get_altfunc, | ||
654 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ | ||
655 | }; | ||
656 | |||
657 | static struct stmpe_variant_info *stmpe_variant_info[] = { | ||
658 | [STMPE811] = &stmpe811, | ||
659 | [STMPE1601] = &stmpe1601, | ||
660 | [STMPE2401] = &stmpe2401, | ||
661 | [STMPE2403] = &stmpe2403, | ||
662 | }; | ||
663 | |||
664 | static irqreturn_t stmpe_irq(int irq, void *data) | ||
665 | { | ||
666 | struct stmpe *stmpe = data; | ||
667 | struct stmpe_variant_info *variant = stmpe->variant; | ||
668 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
669 | u8 israddr = stmpe->regs[STMPE_IDX_ISR_MSB]; | ||
670 | u8 isr[num]; | ||
671 | int ret; | ||
672 | int i; | ||
673 | |||
674 | ret = stmpe_block_read(stmpe, israddr, num, isr); | ||
675 | if (ret < 0) | ||
676 | return IRQ_NONE; | ||
677 | |||
678 | for (i = 0; i < num; i++) { | ||
679 | int bank = num - i - 1; | ||
680 | u8 status = isr[i]; | ||
681 | u8 clear; | ||
682 | |||
683 | status &= stmpe->ier[bank]; | ||
684 | if (!status) | ||
685 | continue; | ||
686 | |||
687 | clear = status; | ||
688 | while (status) { | ||
689 | int bit = __ffs(status); | ||
690 | int line = bank * 8 + bit; | ||
691 | |||
692 | handle_nested_irq(stmpe->irq_base + line); | ||
693 | status &= ~(1 << bit); | ||
694 | } | ||
695 | |||
696 | stmpe_reg_write(stmpe, israddr + i, clear); | ||
697 | } | ||
698 | |||
699 | return IRQ_HANDLED; | ||
700 | } | ||
701 | |||
702 | static void stmpe_irq_lock(unsigned int irq) | ||
703 | { | ||
704 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
705 | |||
706 | mutex_lock(&stmpe->irq_lock); | ||
707 | } | ||
708 | |||
709 | static void stmpe_irq_sync_unlock(unsigned int irq) | ||
710 | { | ||
711 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
712 | struct stmpe_variant_info *variant = stmpe->variant; | ||
713 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
714 | int i; | ||
715 | |||
716 | for (i = 0; i < num; i++) { | ||
717 | u8 new = stmpe->ier[i]; | ||
718 | u8 old = stmpe->oldier[i]; | ||
719 | |||
720 | if (new == old) | ||
721 | continue; | ||
722 | |||
723 | stmpe->oldier[i] = new; | ||
724 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB] - i, new); | ||
725 | } | ||
726 | |||
727 | mutex_unlock(&stmpe->irq_lock); | ||
728 | } | ||
729 | |||
730 | static void stmpe_irq_mask(unsigned int irq) | ||
731 | { | ||
732 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
733 | int offset = irq - stmpe->irq_base; | ||
734 | int regoffset = offset / 8; | ||
735 | int mask = 1 << (offset % 8); | ||
736 | |||
737 | stmpe->ier[regoffset] &= ~mask; | ||
738 | } | ||
739 | |||
740 | static void stmpe_irq_unmask(unsigned int irq) | ||
741 | { | ||
742 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
743 | int offset = irq - stmpe->irq_base; | ||
744 | int regoffset = offset / 8; | ||
745 | int mask = 1 << (offset % 8); | ||
746 | |||
747 | stmpe->ier[regoffset] |= mask; | ||
748 | } | ||
749 | |||
750 | static struct irq_chip stmpe_irq_chip = { | ||
751 | .name = "stmpe", | ||
752 | .bus_lock = stmpe_irq_lock, | ||
753 | .bus_sync_unlock = stmpe_irq_sync_unlock, | ||
754 | .mask = stmpe_irq_mask, | ||
755 | .unmask = stmpe_irq_unmask, | ||
756 | }; | ||
757 | |||
758 | static int __devinit stmpe_irq_init(struct stmpe *stmpe) | ||
759 | { | ||
760 | int num_irqs = stmpe->variant->num_irqs; | ||
761 | int base = stmpe->irq_base; | ||
762 | int irq; | ||
763 | |||
764 | for (irq = base; irq < base + num_irqs; irq++) { | ||
765 | set_irq_chip_data(irq, stmpe); | ||
766 | set_irq_chip_and_handler(irq, &stmpe_irq_chip, | ||
767 | handle_edge_irq); | ||
768 | set_irq_nested_thread(irq, 1); | ||
769 | #ifdef CONFIG_ARM | ||
770 | set_irq_flags(irq, IRQF_VALID); | ||
771 | #else | ||
772 | set_irq_noprobe(irq); | ||
773 | #endif | ||
774 | } | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static void stmpe_irq_remove(struct stmpe *stmpe) | ||
780 | { | ||
781 | int num_irqs = stmpe->variant->num_irqs; | ||
782 | int base = stmpe->irq_base; | ||
783 | int irq; | ||
784 | |||
785 | for (irq = base; irq < base + num_irqs; irq++) { | ||
786 | #ifdef CONFIG_ARM | ||
787 | set_irq_flags(irq, 0); | ||
788 | #endif | ||
789 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
790 | set_irq_chip_data(irq, NULL); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | static int __devinit stmpe_chip_init(struct stmpe *stmpe) | ||
795 | { | ||
796 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; | ||
797 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; | ||
798 | struct stmpe_variant_info *variant = stmpe->variant; | ||
799 | u8 icr = STMPE_ICR_LSB_GIM; | ||
800 | unsigned int id; | ||
801 | u8 data[2]; | ||
802 | int ret; | ||
803 | |||
804 | ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID], | ||
805 | ARRAY_SIZE(data), data); | ||
806 | if (ret < 0) | ||
807 | return ret; | ||
808 | |||
809 | id = (data[0] << 8) | data[1]; | ||
810 | if ((id & variant->id_mask) != variant->id_val) { | ||
811 | dev_err(stmpe->dev, "unknown chip id: %#x\n", id); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id); | ||
816 | |||
817 | /* Disable all modules -- subdrivers should enable what they need. */ | ||
818 | ret = stmpe_disable(stmpe, ~0); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
822 | if (irq_trigger == IRQF_TRIGGER_FALLING || | ||
823 | irq_trigger == IRQF_TRIGGER_RISING) | ||
824 | icr |= STMPE_ICR_LSB_EDGE; | ||
825 | |||
826 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
827 | irq_trigger == IRQF_TRIGGER_HIGH) | ||
828 | icr |= STMPE_ICR_LSB_HIGH; | ||
829 | |||
830 | if (stmpe->pdata->irq_invert_polarity) | ||
831 | icr ^= STMPE_ICR_LSB_HIGH; | ||
832 | |||
833 | if (stmpe->pdata->autosleep) { | ||
834 | ret = stmpe_autosleep(stmpe, autosleep_timeout); | ||
835 | if (ret) | ||
836 | return ret; | ||
837 | } | ||
838 | |||
839 | return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); | ||
840 | } | ||
841 | |||
842 | static int __devinit stmpe_add_device(struct stmpe *stmpe, | ||
843 | struct mfd_cell *cell, int irq) | ||
844 | { | ||
845 | return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, | ||
846 | NULL, stmpe->irq_base + irq); | ||
847 | } | ||
848 | |||
849 | static int __devinit stmpe_devices_init(struct stmpe *stmpe) | ||
850 | { | ||
851 | struct stmpe_variant_info *variant = stmpe->variant; | ||
852 | unsigned int platform_blocks = stmpe->pdata->blocks; | ||
853 | int ret = -EINVAL; | ||
854 | int i; | ||
855 | |||
856 | for (i = 0; i < variant->num_blocks; i++) { | ||
857 | struct stmpe_variant_block *block = &variant->blocks[i]; | ||
858 | |||
859 | if (!(platform_blocks & block->block)) | ||
860 | continue; | ||
861 | |||
862 | platform_blocks &= ~block->block; | ||
863 | ret = stmpe_add_device(stmpe, block->cell, block->irq); | ||
864 | if (ret) | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | if (platform_blocks) | ||
869 | dev_warn(stmpe->dev, | ||
870 | "platform wants blocks (%#x) not present on variant", | ||
871 | platform_blocks); | ||
872 | |||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | static int __devinit stmpe_probe(struct i2c_client *i2c, | ||
877 | const struct i2c_device_id *id) | ||
878 | { | ||
879 | struct stmpe_platform_data *pdata = i2c->dev.platform_data; | ||
880 | struct stmpe *stmpe; | ||
881 | int ret; | ||
882 | |||
883 | if (!pdata) | ||
884 | return -EINVAL; | ||
885 | |||
886 | stmpe = kzalloc(sizeof(struct stmpe), GFP_KERNEL); | ||
887 | if (!stmpe) | ||
888 | return -ENOMEM; | ||
889 | |||
890 | mutex_init(&stmpe->irq_lock); | ||
891 | mutex_init(&stmpe->lock); | ||
892 | |||
893 | stmpe->dev = &i2c->dev; | ||
894 | stmpe->i2c = i2c; | ||
895 | |||
896 | stmpe->pdata = pdata; | ||
897 | stmpe->irq_base = pdata->irq_base; | ||
898 | |||
899 | stmpe->partnum = id->driver_data; | ||
900 | stmpe->variant = stmpe_variant_info[stmpe->partnum]; | ||
901 | stmpe->regs = stmpe->variant->regs; | ||
902 | stmpe->num_gpios = stmpe->variant->num_gpios; | ||
903 | |||
904 | i2c_set_clientdata(i2c, stmpe); | ||
905 | |||
906 | ret = stmpe_chip_init(stmpe); | ||
907 | if (ret) | ||
908 | goto out_free; | ||
909 | |||
910 | ret = stmpe_irq_init(stmpe); | ||
911 | if (ret) | ||
912 | goto out_free; | ||
913 | |||
914 | ret = request_threaded_irq(stmpe->i2c->irq, NULL, stmpe_irq, | ||
915 | pdata->irq_trigger | IRQF_ONESHOT, | ||
916 | "stmpe", stmpe); | ||
917 | if (ret) { | ||
918 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret); | ||
919 | goto out_removeirq; | ||
920 | } | ||
921 | |||
922 | ret = stmpe_devices_init(stmpe); | ||
923 | if (ret) { | ||
924 | dev_err(stmpe->dev, "failed to add children\n"); | ||
925 | goto out_removedevs; | ||
926 | } | ||
927 | |||
928 | return 0; | ||
929 | |||
930 | out_removedevs: | ||
931 | mfd_remove_devices(stmpe->dev); | ||
932 | free_irq(stmpe->i2c->irq, stmpe); | ||
933 | out_removeirq: | ||
934 | stmpe_irq_remove(stmpe); | ||
935 | out_free: | ||
936 | kfree(stmpe); | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int __devexit stmpe_remove(struct i2c_client *client) | ||
941 | { | ||
942 | struct stmpe *stmpe = i2c_get_clientdata(client); | ||
943 | |||
944 | mfd_remove_devices(stmpe->dev); | ||
945 | |||
946 | free_irq(stmpe->i2c->irq, stmpe); | ||
947 | stmpe_irq_remove(stmpe); | ||
948 | |||
949 | kfree(stmpe); | ||
950 | |||
951 | return 0; | ||
952 | } | ||
953 | |||
954 | static const struct i2c_device_id stmpe_id[] = { | ||
955 | { "stmpe811", STMPE811 }, | ||
956 | { "stmpe1601", STMPE1601 }, | ||
957 | { "stmpe2401", STMPE2401 }, | ||
958 | { "stmpe2403", STMPE2403 }, | ||
959 | { } | ||
960 | }; | ||
961 | MODULE_DEVICE_TABLE(i2c, stmpe_id); | ||
962 | |||
963 | static struct i2c_driver stmpe_driver = { | ||
964 | .driver.name = "stmpe", | ||
965 | .driver.owner = THIS_MODULE, | ||
966 | .probe = stmpe_probe, | ||
967 | .remove = __devexit_p(stmpe_remove), | ||
968 | .id_table = stmpe_id, | ||
969 | }; | ||
970 | |||
971 | static int __init stmpe_init(void) | ||
972 | { | ||
973 | return i2c_add_driver(&stmpe_driver); | ||
974 | } | ||
975 | subsys_initcall(stmpe_init); | ||
976 | |||
977 | static void __exit stmpe_exit(void) | ||
978 | { | ||
979 | i2c_del_driver(&stmpe_driver); | ||
980 | } | ||
981 | module_exit(stmpe_exit); | ||
982 | |||
983 | MODULE_LICENSE("GPL v2"); | ||
984 | MODULE_DESCRIPTION("STMPE MFD core driver"); | ||
985 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h new file mode 100644 index 000000000000..0dbdc4e8cd77 --- /dev/null +++ b/drivers/mfd/stmpe.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #ifndef __STMPE_H | ||
9 | #define __STMPE_H | ||
10 | |||
11 | #ifdef STMPE_DUMP_BYTES | ||
12 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
13 | size_t len) | ||
14 | { | ||
15 | print_hex_dump_bytes(str, DUMP_PREFIX_OFFSET, buf, len); | ||
16 | } | ||
17 | #else | ||
18 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
19 | size_t len) | ||
20 | { | ||
21 | } | ||
22 | #endif | ||
23 | |||
24 | /** | ||
25 | * struct stmpe_variant_block - information about block | ||
26 | * @cell: base mfd cell | ||
27 | * @irq: interrupt number to be added to each IORESOURCE_IRQ | ||
28 | * in the cell | ||
29 | * @block: block id; used for identification with platform data and for | ||
30 | * enable and altfunc callbacks | ||
31 | */ | ||
32 | struct stmpe_variant_block { | ||
33 | struct mfd_cell *cell; | ||
34 | int irq; | ||
35 | enum stmpe_block block; | ||
36 | }; | ||
37 | |||
38 | /** | ||
39 | * struct stmpe_variant_info - variant-specific information | ||
40 | * @name: part name | ||
41 | * @id_val: content of CHIPID register | ||
42 | * @id_mask: bits valid in CHIPID register for comparison with id_val | ||
43 | * @num_gpios: number of GPIOS | ||
44 | * @af_bits: number of bits used to specify the alternate function | ||
45 | * @blocks: list of blocks present on this device | ||
46 | * @num_blocks: number of blocks present on this device | ||
47 | * @num_irqs: number of internal IRQs available on this device | ||
48 | * @enable: callback to enable the specified blocks. | ||
49 | * Called with the I/O lock held. | ||
50 | * @get_altfunc: callback to get the alternate function number for the | ||
51 | * specific block | ||
52 | * @enable_autosleep: callback to configure autosleep with specified timeout | ||
53 | */ | ||
54 | struct stmpe_variant_info { | ||
55 | const char *name; | ||
56 | u16 id_val; | ||
57 | u16 id_mask; | ||
58 | int num_gpios; | ||
59 | int af_bits; | ||
60 | const u8 *regs; | ||
61 | struct stmpe_variant_block *blocks; | ||
62 | int num_blocks; | ||
63 | int num_irqs; | ||
64 | int (*enable)(struct stmpe *stmpe, unsigned int blocks, bool enable); | ||
65 | int (*get_altfunc)(struct stmpe *stmpe, enum stmpe_block block); | ||
66 | int (*enable_autosleep)(struct stmpe *stmpe, int autosleep_timeout); | ||
67 | }; | ||
68 | |||
69 | #define STMPE_ICR_LSB_HIGH (1 << 2) | ||
70 | #define STMPE_ICR_LSB_EDGE (1 << 1) | ||
71 | #define STMPE_ICR_LSB_GIM (1 << 0) | ||
72 | |||
73 | /* | ||
74 | * STMPE811 | ||
75 | */ | ||
76 | |||
77 | #define STMPE811_IRQ_TOUCH_DET 0 | ||
78 | #define STMPE811_IRQ_FIFO_TH 1 | ||
79 | #define STMPE811_IRQ_FIFO_OFLOW 2 | ||
80 | #define STMPE811_IRQ_FIFO_FULL 3 | ||
81 | #define STMPE811_IRQ_FIFO_EMPTY 4 | ||
82 | #define STMPE811_IRQ_TEMP_SENS 5 | ||
83 | #define STMPE811_IRQ_ADC 6 | ||
84 | #define STMPE811_IRQ_GPIOC 7 | ||
85 | #define STMPE811_NR_INTERNAL_IRQS 8 | ||
86 | |||
87 | #define STMPE811_REG_CHIP_ID 0x00 | ||
88 | #define STMPE811_REG_SYS_CTRL2 0x04 | ||
89 | #define STMPE811_REG_INT_CTRL 0x09 | ||
90 | #define STMPE811_REG_INT_EN 0x0A | ||
91 | #define STMPE811_REG_INT_STA 0x0B | ||
92 | #define STMPE811_REG_GPIO_INT_EN 0x0C | ||
93 | #define STMPE811_REG_GPIO_INT_STA 0x0D | ||
94 | #define STMPE811_REG_GPIO_SET_PIN 0x10 | ||
95 | #define STMPE811_REG_GPIO_CLR_PIN 0x11 | ||
96 | #define STMPE811_REG_GPIO_MP_STA 0x12 | ||
97 | #define STMPE811_REG_GPIO_DIR 0x13 | ||
98 | #define STMPE811_REG_GPIO_ED 0x14 | ||
99 | #define STMPE811_REG_GPIO_RE 0x15 | ||
100 | #define STMPE811_REG_GPIO_FE 0x16 | ||
101 | #define STMPE811_REG_GPIO_AF 0x17 | ||
102 | |||
103 | #define STMPE811_SYS_CTRL2_ADC_OFF (1 << 0) | ||
104 | #define STMPE811_SYS_CTRL2_TSC_OFF (1 << 1) | ||
105 | #define STMPE811_SYS_CTRL2_GPIO_OFF (1 << 2) | ||
106 | #define STMPE811_SYS_CTRL2_TS_OFF (1 << 3) | ||
107 | |||
108 | /* | ||
109 | * STMPE1601 | ||
110 | */ | ||
111 | |||
112 | #define STMPE1601_IRQ_GPIOC 8 | ||
113 | #define STMPE1601_IRQ_PWM3 7 | ||
114 | #define STMPE1601_IRQ_PWM2 6 | ||
115 | #define STMPE1601_IRQ_PWM1 5 | ||
116 | #define STMPE1601_IRQ_PWM0 4 | ||
117 | #define STMPE1601_IRQ_KEYPAD_OVER 2 | ||
118 | #define STMPE1601_IRQ_KEYPAD 1 | ||
119 | #define STMPE1601_IRQ_WAKEUP 0 | ||
120 | #define STMPE1601_NR_INTERNAL_IRQS 9 | ||
121 | |||
122 | #define STMPE1601_REG_SYS_CTRL 0x02 | ||
123 | #define STMPE1601_REG_SYS_CTRL2 0x03 | ||
124 | #define STMPE1601_REG_ICR_LSB 0x11 | ||
125 | #define STMPE1601_REG_IER_LSB 0x13 | ||
126 | #define STMPE1601_REG_ISR_MSB 0x14 | ||
127 | #define STMPE1601_REG_CHIP_ID 0x80 | ||
128 | #define STMPE1601_REG_INT_EN_GPIO_MASK_LSB 0x17 | ||
129 | #define STMPE1601_REG_INT_STA_GPIO_MSB 0x18 | ||
130 | #define STMPE1601_REG_GPIO_MP_LSB 0x87 | ||
131 | #define STMPE1601_REG_GPIO_SET_LSB 0x83 | ||
132 | #define STMPE1601_REG_GPIO_CLR_LSB 0x85 | ||
133 | #define STMPE1601_REG_GPIO_SET_DIR_LSB 0x89 | ||
134 | #define STMPE1601_REG_GPIO_ED_MSB 0x8A | ||
135 | #define STMPE1601_REG_GPIO_RE_LSB 0x8D | ||
136 | #define STMPE1601_REG_GPIO_FE_LSB 0x8F | ||
137 | #define STMPE1601_REG_GPIO_AF_U_MSB 0x92 | ||
138 | |||
139 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
140 | #define STMPE1601_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
141 | #define STMPE1601_SYSCON_ENABLE_SPWM (1 << 0) | ||
142 | |||
143 | /* The 1601/2403 share the same masks */ | ||
144 | #define STMPE1601_AUTOSLEEP_TIMEOUT_MASK (0x7) | ||
145 | #define STPME1601_AUTOSLEEP_ENABLE (1 << 3) | ||
146 | |||
147 | /* | ||
148 | * STMPE24xx | ||
149 | */ | ||
150 | |||
151 | #define STMPE24XX_IRQ_GPIOC 8 | ||
152 | #define STMPE24XX_IRQ_PWM2 7 | ||
153 | #define STMPE24XX_IRQ_PWM1 6 | ||
154 | #define STMPE24XX_IRQ_PWM0 5 | ||
155 | #define STMPE24XX_IRQ_ROT_OVER 4 | ||
156 | #define STMPE24XX_IRQ_ROT 3 | ||
157 | #define STMPE24XX_IRQ_KEYPAD_OVER 2 | ||
158 | #define STMPE24XX_IRQ_KEYPAD 1 | ||
159 | #define STMPE24XX_IRQ_WAKEUP 0 | ||
160 | #define STMPE24XX_NR_INTERNAL_IRQS 9 | ||
161 | |||
162 | #define STMPE24XX_REG_SYS_CTRL 0x02 | ||
163 | #define STMPE24XX_REG_ICR_LSB 0x11 | ||
164 | #define STMPE24XX_REG_IER_LSB 0x13 | ||
165 | #define STMPE24XX_REG_ISR_MSB 0x14 | ||
166 | #define STMPE24XX_REG_CHIP_ID 0x80 | ||
167 | #define STMPE24XX_REG_IEGPIOR_LSB 0x18 | ||
168 | #define STMPE24XX_REG_ISGPIOR_MSB 0x19 | ||
169 | #define STMPE24XX_REG_GPMR_LSB 0xA5 | ||
170 | #define STMPE24XX_REG_GPSR_LSB 0x85 | ||
171 | #define STMPE24XX_REG_GPCR_LSB 0x88 | ||
172 | #define STMPE24XX_REG_GPDR_LSB 0x8B | ||
173 | #define STMPE24XX_REG_GPEDR_MSB 0x8C | ||
174 | #define STMPE24XX_REG_GPRER_LSB 0x91 | ||
175 | #define STMPE24XX_REG_GPFER_LSB 0x94 | ||
176 | #define STMPE24XX_REG_GPAFR_U_MSB 0x9B | ||
177 | |||
178 | #define STMPE24XX_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
179 | #define STMPE24XX_SYSCON_ENABLE_PWM (1 << 2) | ||
180 | #define STMPE24XX_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
181 | #define STMPE24XX_SYSCON_ENABLE_ROT (1 << 0) | ||
182 | |||
183 | #endif | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 5041d33adf0b..006c121f3f0d 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -350,7 +350,6 @@ static int t7l66xb_probe(struct platform_device *dev) | |||
350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); | 350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); |
351 | if (IS_ERR(t7l66xb->clk48m)) { | 351 | if (IS_ERR(t7l66xb->clk48m)) { |
352 | ret = PTR_ERR(t7l66xb->clk48m); | 352 | ret = PTR_ERR(t7l66xb->clk48m); |
353 | clk_put(t7l66xb->clk32k); | ||
354 | goto err_clk48m_get; | 353 | goto err_clk48m_get; |
355 | } | 354 | } |
356 | 355 | ||
@@ -425,6 +424,8 @@ static int t7l66xb_remove(struct platform_device *dev) | |||
425 | ret = pdata->disable(dev); | 424 | ret = pdata->disable(dev); |
426 | clk_disable(t7l66xb->clk48m); | 425 | clk_disable(t7l66xb->clk48m); |
427 | clk_put(t7l66xb->clk48m); | 426 | clk_put(t7l66xb->clk48m); |
427 | clk_disable(t7l66xb->clk32k); | ||
428 | clk_put(t7l66xb->clk32k); | ||
428 | t7l66xb_detach_irq(dev); | 429 | t7l66xb_detach_irq(dev); |
429 | iounmap(t7l66xb->scr); | 430 | iounmap(t7l66xb->scr); |
430 | release_resource(&t7l66xb->rscr); | 431 | release_resource(&t7l66xb->rscr); |
diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index 715f095dd7a6..e619e2a55997 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c | |||
@@ -296,7 +296,6 @@ out_freeirq: | |||
296 | out_removeirq: | 296 | out_removeirq: |
297 | tc35892_irq_remove(tc35892); | 297 | tc35892_irq_remove(tc35892); |
298 | out_free: | 298 | out_free: |
299 | i2c_set_clientdata(i2c, NULL); | ||
300 | kfree(tc35892); | 299 | kfree(tc35892); |
301 | return ret; | 300 | return ret; |
302 | } | 301 | } |
@@ -310,7 +309,6 @@ static int __devexit tc35892_remove(struct i2c_client *client) | |||
310 | free_irq(tc35892->i2c->irq, tc35892); | 309 | free_irq(tc35892->i2c->irq, tc35892); |
311 | tc35892_irq_remove(tc35892); | 310 | tc35892_irq_remove(tc35892); |
312 | 311 | ||
313 | i2c_set_clientdata(client, NULL); | ||
314 | kfree(tc35892); | 312 | kfree(tc35892); |
315 | 313 | ||
316 | return 0; | 314 | return 0; |
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 517f9bcdeaac..6315f63f017d 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
@@ -137,7 +137,7 @@ static struct mfd_cell tc6387xb_cells[] = { | |||
137 | }, | 137 | }, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static int tc6387xb_probe(struct platform_device *dev) | 140 | static int __devinit tc6387xb_probe(struct platform_device *dev) |
141 | { | 141 | { |
142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; | 142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; |
143 | struct resource *iomem, *rscr; | 143 | struct resource *iomem, *rscr; |
@@ -201,6 +201,7 @@ static int tc6387xb_probe(struct platform_device *dev) | |||
201 | if (!ret) | 201 | if (!ret) |
202 | return 0; | 202 | return 0; |
203 | 203 | ||
204 | iounmap(tc6387xb->scr); | ||
204 | err_ioremap: | 205 | err_ioremap: |
205 | release_resource(&tc6387xb->rscr); | 206 | release_resource(&tc6387xb->rscr); |
206 | err_resource: | 207 | err_resource: |
@@ -211,14 +212,17 @@ err_no_irq: | |||
211 | return ret; | 212 | return ret; |
212 | } | 213 | } |
213 | 214 | ||
214 | static int tc6387xb_remove(struct platform_device *dev) | 215 | static int __devexit tc6387xb_remove(struct platform_device *dev) |
215 | { | 216 | { |
216 | struct clk *clk32k = platform_get_drvdata(dev); | 217 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); |
217 | 218 | ||
218 | mfd_remove_devices(&dev->dev); | 219 | mfd_remove_devices(&dev->dev); |
219 | clk_disable(clk32k); | 220 | iounmap(tc6387xb->scr); |
220 | clk_put(clk32k); | 221 | release_resource(&tc6387xb->rscr); |
222 | clk_disable(tc6387xb->clk32k); | ||
223 | clk_put(tc6387xb->clk32k); | ||
221 | platform_set_drvdata(dev, NULL); | 224 | platform_set_drvdata(dev, NULL); |
225 | kfree(tc6387xb); | ||
222 | 226 | ||
223 | return 0; | 227 | return 0; |
224 | } | 228 | } |
@@ -229,7 +233,7 @@ static struct platform_driver tc6387xb_platform_driver = { | |||
229 | .name = "tc6387xb", | 233 | .name = "tc6387xb", |
230 | }, | 234 | }, |
231 | .probe = tc6387xb_probe, | 235 | .probe = tc6387xb_probe, |
232 | .remove = tc6387xb_remove, | 236 | .remove = __devexit_p(tc6387xb_remove), |
233 | .suspend = tc6387xb_suspend, | 237 | .suspend = tc6387xb_suspend, |
234 | .resume = tc6387xb_resume, | 238 | .resume = tc6387xb_resume, |
235 | }; | 239 | }; |
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index fcf9068810fb..ef6c42c8917a 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -732,9 +732,9 @@ err_gpio_add: | |||
732 | if (tc6393xb->gpio.base != -1) | 732 | if (tc6393xb->gpio.base != -1) |
733 | temp = gpiochip_remove(&tc6393xb->gpio); | 733 | temp = gpiochip_remove(&tc6393xb->gpio); |
734 | tcpd->disable(dev); | 734 | tcpd->disable(dev); |
735 | err_clk_enable: | ||
736 | clk_disable(tc6393xb->clk); | ||
737 | err_enable: | 735 | err_enable: |
736 | clk_disable(tc6393xb->clk); | ||
737 | err_clk_enable: | ||
738 | iounmap(tc6393xb->scr); | 738 | iounmap(tc6393xb->scr); |
739 | err_ioremap: | 739 | err_ioremap: |
740 | release_resource(&tc6393xb->rscr); | 740 | release_resource(&tc6393xb->rscr); |
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 9b22a77f70f5..d0016b67d125 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c | |||
@@ -530,7 +530,6 @@ static int __exit tps65010_remove(struct i2c_client *client) | |||
530 | cancel_delayed_work(&tps->work); | 530 | cancel_delayed_work(&tps->work); |
531 | flush_scheduled_work(); | 531 | flush_scheduled_work(); |
532 | debugfs_remove(tps->file); | 532 | debugfs_remove(tps->file); |
533 | i2c_set_clientdata(client, NULL); | ||
534 | kfree(tps); | 533 | kfree(tps); |
535 | the_tps = NULL; | 534 | the_tps = NULL; |
536 | return 0; | 535 | return 0; |
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index d859dffed39f..fc0197649281 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c | |||
@@ -89,10 +89,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, | |||
89 | int ret = 0; | 89 | int ret = 0; |
90 | 90 | ||
91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); | 91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); |
92 | if (tps6507x == NULL) { | 92 | if (tps6507x == NULL) |
93 | kfree(i2c); | ||
94 | return -ENOMEM; | 93 | return -ENOMEM; |
95 | } | ||
96 | 94 | ||
97 | i2c_set_clientdata(i2c, tps6507x); | 95 | i2c_set_clientdata(i2c, tps6507x); |
98 | tps6507x->dev = &i2c->dev; | 96 | tps6507x->dev = &i2c->dev; |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c new file mode 100644 index 000000000000..4cde31e6a252 --- /dev/null +++ b/drivers/mfd/tps6586x.c | |||
@@ -0,0 +1,375 @@ | |||
1 | /* | ||
2 | * Core driver for TI TPS6586x PMIC family | ||
3 | * | ||
4 | * Copyright (c) 2010 CompuLab Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on da903x.c. | ||
8 | * Copyright (C) 2008 Compulab, Ltd. | ||
9 | * Mike Rapoport <mike@compulab.co.il> | ||
10 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
11 | * Eric Miao <eric.miao@marvell.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/i2c.h> | ||
24 | |||
25 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/tps6586x.h> | ||
27 | |||
28 | /* GPIO control registers */ | ||
29 | #define TPS6586X_GPIOSET1 0x5d | ||
30 | #define TPS6586X_GPIOSET2 0x5e | ||
31 | |||
32 | /* device id */ | ||
33 | #define TPS6586X_VERSIONCRC 0xcd | ||
34 | #define TPS658621A_VERSIONCRC 0x15 | ||
35 | |||
36 | struct tps6586x { | ||
37 | struct mutex lock; | ||
38 | struct device *dev; | ||
39 | struct i2c_client *client; | ||
40 | |||
41 | struct gpio_chip gpio; | ||
42 | }; | ||
43 | |||
44 | static inline int __tps6586x_read(struct i2c_client *client, | ||
45 | int reg, uint8_t *val) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | ret = i2c_smbus_read_byte_data(client, reg); | ||
50 | if (ret < 0) { | ||
51 | dev_err(&client->dev, "failed reading at 0x%02x\n", reg); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | *val = (uint8_t)ret; | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static inline int __tps6586x_reads(struct i2c_client *client, int reg, | ||
61 | int len, uint8_t *val) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); | ||
66 | if (ret < 0) { | ||
67 | dev_err(&client->dev, "failed reading from 0x%02x\n", reg); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static inline int __tps6586x_write(struct i2c_client *client, | ||
75 | int reg, uint8_t val) | ||
76 | { | ||
77 | int ret; | ||
78 | |||
79 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
80 | if (ret < 0) { | ||
81 | dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", | ||
82 | val, reg); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static inline int __tps6586x_writes(struct i2c_client *client, int reg, | ||
90 | int len, uint8_t *val) | ||
91 | { | ||
92 | int ret; | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(client, reg, len, val); | ||
95 | if (ret < 0) { | ||
96 | dev_err(&client->dev, "failed writings to 0x%02x\n", reg); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int tps6586x_write(struct device *dev, int reg, uint8_t val) | ||
104 | { | ||
105 | return __tps6586x_write(to_i2c_client(dev), reg, val); | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(tps6586x_write); | ||
108 | |||
109 | int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) | ||
110 | { | ||
111 | return __tps6586x_writes(to_i2c_client(dev), reg, len, val); | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(tps6586x_writes); | ||
114 | |||
115 | int tps6586x_read(struct device *dev, int reg, uint8_t *val) | ||
116 | { | ||
117 | return __tps6586x_read(to_i2c_client(dev), reg, val); | ||
118 | } | ||
119 | EXPORT_SYMBOL_GPL(tps6586x_read); | ||
120 | |||
121 | int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) | ||
122 | { | ||
123 | return __tps6586x_reads(to_i2c_client(dev), reg, len, val); | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(tps6586x_reads); | ||
126 | |||
127 | int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
128 | { | ||
129 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
130 | uint8_t reg_val; | ||
131 | int ret = 0; | ||
132 | |||
133 | mutex_lock(&tps6586x->lock); | ||
134 | |||
135 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
136 | if (ret) | ||
137 | goto out; | ||
138 | |||
139 | if ((reg_val & bit_mask) == 0) { | ||
140 | reg_val |= bit_mask; | ||
141 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
142 | } | ||
143 | out: | ||
144 | mutex_unlock(&tps6586x->lock); | ||
145 | return ret; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(tps6586x_set_bits); | ||
148 | |||
149 | int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
150 | { | ||
151 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
152 | uint8_t reg_val; | ||
153 | int ret = 0; | ||
154 | |||
155 | mutex_lock(&tps6586x->lock); | ||
156 | |||
157 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
158 | if (ret) | ||
159 | goto out; | ||
160 | |||
161 | if (reg_val & bit_mask) { | ||
162 | reg_val &= ~bit_mask; | ||
163 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
164 | } | ||
165 | out: | ||
166 | mutex_unlock(&tps6586x->lock); | ||
167 | return ret; | ||
168 | } | ||
169 | EXPORT_SYMBOL_GPL(tps6586x_clr_bits); | ||
170 | |||
171 | int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) | ||
172 | { | ||
173 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
174 | uint8_t reg_val; | ||
175 | int ret = 0; | ||
176 | |||
177 | mutex_lock(&tps6586x->lock); | ||
178 | |||
179 | ret = __tps6586x_read(tps6586x->client, reg, ®_val); | ||
180 | if (ret) | ||
181 | goto out; | ||
182 | |||
183 | if ((reg_val & mask) != val) { | ||
184 | reg_val = (reg_val & ~mask) | val; | ||
185 | ret = __tps6586x_write(tps6586x->client, reg, reg_val); | ||
186 | } | ||
187 | out: | ||
188 | mutex_unlock(&tps6586x->lock); | ||
189 | return ret; | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(tps6586x_update); | ||
192 | |||
193 | static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
194 | { | ||
195 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
196 | uint8_t val; | ||
197 | int ret; | ||
198 | |||
199 | ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
203 | return !!(val & (1 << offset)); | ||
204 | } | ||
205 | |||
206 | |||
207 | static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, | ||
208 | int value) | ||
209 | { | ||
210 | struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); | ||
211 | |||
212 | __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, | ||
213 | value << offset); | ||
214 | } | ||
215 | |||
216 | static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, | ||
217 | int value) | ||
218 | { | ||
219 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
220 | uint8_t val, mask; | ||
221 | |||
222 | tps6586x_gpio_set(gc, offset, value); | ||
223 | |||
224 | val = 0x1 << (offset * 2); | ||
225 | mask = 0x3 << (offset * 2); | ||
226 | |||
227 | return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); | ||
228 | } | ||
229 | |||
230 | static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | if (!gpio_base) | ||
235 | return; | ||
236 | |||
237 | tps6586x->gpio.owner = THIS_MODULE; | ||
238 | tps6586x->gpio.label = tps6586x->client->name; | ||
239 | tps6586x->gpio.dev = tps6586x->dev; | ||
240 | tps6586x->gpio.base = gpio_base; | ||
241 | tps6586x->gpio.ngpio = 4; | ||
242 | tps6586x->gpio.can_sleep = 1; | ||
243 | |||
244 | /* FIXME: add handling of GPIOs as dedicated inputs */ | ||
245 | tps6586x->gpio.direction_output = tps6586x_gpio_output; | ||
246 | tps6586x->gpio.set = tps6586x_gpio_set; | ||
247 | tps6586x->gpio.get = tps6586x_gpio_get; | ||
248 | |||
249 | ret = gpiochip_add(&tps6586x->gpio); | ||
250 | if (ret) | ||
251 | dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret); | ||
252 | } | ||
253 | |||
254 | static int __remove_subdev(struct device *dev, void *unused) | ||
255 | { | ||
256 | platform_device_unregister(to_platform_device(dev)); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) | ||
261 | { | ||
262 | return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); | ||
263 | } | ||
264 | |||
265 | static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, | ||
266 | struct tps6586x_platform_data *pdata) | ||
267 | { | ||
268 | struct tps6586x_subdev_info *subdev; | ||
269 | struct platform_device *pdev; | ||
270 | int i, ret = 0; | ||
271 | |||
272 | for (i = 0; i < pdata->num_subdevs; i++) { | ||
273 | subdev = &pdata->subdevs[i]; | ||
274 | |||
275 | pdev = platform_device_alloc(subdev->name, subdev->id); | ||
276 | |||
277 | pdev->dev.parent = tps6586x->dev; | ||
278 | pdev->dev.platform_data = subdev->platform_data; | ||
279 | |||
280 | ret = platform_device_add(pdev); | ||
281 | if (ret) | ||
282 | goto failed; | ||
283 | } | ||
284 | return 0; | ||
285 | |||
286 | failed: | ||
287 | tps6586x_remove_subdevs(tps6586x); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | ||
292 | const struct i2c_device_id *id) | ||
293 | { | ||
294 | struct tps6586x_platform_data *pdata = client->dev.platform_data; | ||
295 | struct tps6586x *tps6586x; | ||
296 | int ret; | ||
297 | |||
298 | if (!pdata) { | ||
299 | dev_err(&client->dev, "tps6586x requires platform data\n"); | ||
300 | return -ENOTSUPP; | ||
301 | } | ||
302 | |||
303 | ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); | ||
304 | if (ret < 0) { | ||
305 | dev_err(&client->dev, "Chip ID read failed: %d\n", ret); | ||
306 | return -EIO; | ||
307 | } | ||
308 | |||
309 | if (ret != TPS658621A_VERSIONCRC) { | ||
310 | dev_err(&client->dev, "Unsupported chip ID: %x\n", ret); | ||
311 | return -ENODEV; | ||
312 | } | ||
313 | |||
314 | tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); | ||
315 | if (tps6586x == NULL) | ||
316 | return -ENOMEM; | ||
317 | |||
318 | tps6586x->client = client; | ||
319 | tps6586x->dev = &client->dev; | ||
320 | i2c_set_clientdata(client, tps6586x); | ||
321 | |||
322 | mutex_init(&tps6586x->lock); | ||
323 | |||
324 | ret = tps6586x_add_subdevs(tps6586x, pdata); | ||
325 | if (ret) { | ||
326 | dev_err(&client->dev, "add devices failed: %d\n", ret); | ||
327 | goto err_add_devs; | ||
328 | } | ||
329 | |||
330 | tps6586x_gpio_init(tps6586x, pdata->gpio_base); | ||
331 | |||
332 | return 0; | ||
333 | |||
334 | err_add_devs: | ||
335 | kfree(tps6586x); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int __devexit tps6586x_i2c_remove(struct i2c_client *client) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static const struct i2c_device_id tps6586x_id_table[] = { | ||
345 | { "tps6586x", 0 }, | ||
346 | { }, | ||
347 | }; | ||
348 | MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); | ||
349 | |||
350 | static struct i2c_driver tps6586x_driver = { | ||
351 | .driver = { | ||
352 | .name = "tps6586x", | ||
353 | .owner = THIS_MODULE, | ||
354 | }, | ||
355 | .probe = tps6586x_i2c_probe, | ||
356 | .remove = __devexit_p(tps6586x_i2c_remove), | ||
357 | .id_table = tps6586x_id_table, | ||
358 | }; | ||
359 | |||
360 | static int __init tps6586x_init(void) | ||
361 | { | ||
362 | return i2c_add_driver(&tps6586x_driver); | ||
363 | } | ||
364 | subsys_initcall(tps6586x_init); | ||
365 | |||
366 | static void __exit tps6586x_exit(void) | ||
367 | { | ||
368 | i2c_del_driver(&tps6586x_driver); | ||
369 | } | ||
370 | module_exit(tps6586x_exit); | ||
371 | |||
372 | MODULE_DESCRIPTION("TPS6586X core driver"); | ||
373 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
374 | MODULE_LICENSE("GPL"); | ||
375 | |||
diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c new file mode 100644 index 000000000000..5d25bdc78424 --- /dev/null +++ b/drivers/mfd/twl6030-pwm.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * twl6030_pwm.c | ||
3 | * Driver for PHOENIX (TWL6030) Pulse Width Modulator | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments | ||
6 | * Author: Hemanth V <hemanthv@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/i2c/twl.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #define LED_PWM_CTRL1 0xF4 | ||
27 | #define LED_PWM_CTRL2 0xF5 | ||
28 | |||
29 | /* Max value for CTRL1 register */ | ||
30 | #define PWM_CTRL1_MAX 255 | ||
31 | |||
32 | /* Pull down disable */ | ||
33 | #define PWM_CTRL2_DIS_PD (1 << 6) | ||
34 | |||
35 | /* Current control 2.5 milli Amps */ | ||
36 | #define PWM_CTRL2_CURR_02 (2 << 4) | ||
37 | |||
38 | /* LED supply source */ | ||
39 | #define PWM_CTRL2_SRC_VAC (1 << 2) | ||
40 | |||
41 | /* LED modes */ | ||
42 | #define PWM_CTRL2_MODE_HW (0 << 0) | ||
43 | #define PWM_CTRL2_MODE_SW (1 << 0) | ||
44 | #define PWM_CTRL2_MODE_DIS (2 << 0) | ||
45 | |||
46 | #define PWM_CTRL2_MODE_MASK 0x3 | ||
47 | |||
48 | struct pwm_device { | ||
49 | const char *label; | ||
50 | unsigned int pwm_id; | ||
51 | }; | ||
52 | |||
53 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | ||
54 | { | ||
55 | u8 duty_cycle; | ||
56 | int ret; | ||
57 | |||
58 | if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) | ||
59 | return -EINVAL; | ||
60 | |||
61 | duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns; | ||
62 | |||
63 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1); | ||
64 | |||
65 | if (ret < 0) { | ||
66 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
67 | pwm->label, ret); | ||
68 | return ret; | ||
69 | } | ||
70 | return 0; | ||
71 | } | ||
72 | EXPORT_SYMBOL(pwm_config); | ||
73 | |||
74 | int pwm_enable(struct pwm_device *pwm) | ||
75 | { | ||
76 | u8 val; | ||
77 | int ret; | ||
78 | |||
79 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
80 | if (ret < 0) { | ||
81 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | /* Change mode to software control */ | ||
86 | val &= ~PWM_CTRL2_MODE_MASK; | ||
87 | val |= PWM_CTRL2_MODE_SW; | ||
88 | |||
89 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
90 | if (ret < 0) { | ||
91 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
96 | return 0; | ||
97 | } | ||
98 | EXPORT_SYMBOL(pwm_enable); | ||
99 | |||
100 | void pwm_disable(struct pwm_device *pwm) | ||
101 | { | ||
102 | u8 val; | ||
103 | int ret; | ||
104 | |||
105 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
106 | if (ret < 0) { | ||
107 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
108 | pwm->label, ret); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | val &= ~PWM_CTRL2_MODE_MASK; | ||
113 | val |= PWM_CTRL2_MODE_HW; | ||
114 | |||
115 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
116 | if (ret < 0) { | ||
117 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
118 | pwm->label, ret); | ||
119 | return; | ||
120 | } | ||
121 | return; | ||
122 | } | ||
123 | EXPORT_SYMBOL(pwm_disable); | ||
124 | |||
125 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
126 | { | ||
127 | u8 val; | ||
128 | int ret; | ||
129 | struct pwm_device *pwm; | ||
130 | |||
131 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | ||
132 | if (pwm == NULL) { | ||
133 | pr_err("%s: failed to allocate memory\n", label); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | pwm->label = label; | ||
138 | pwm->pwm_id = pwm_id; | ||
139 | |||
140 | /* Configure PWM */ | ||
141 | val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC | | ||
142 | PWM_CTRL2_MODE_HW; | ||
143 | |||
144 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
145 | |||
146 | if (ret < 0) { | ||
147 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
148 | pwm->label, ret); | ||
149 | |||
150 | kfree(pwm); | ||
151 | return NULL; | ||
152 | } | ||
153 | |||
154 | return pwm; | ||
155 | } | ||
156 | EXPORT_SYMBOL(pwm_request); | ||
157 | |||
158 | void pwm_free(struct pwm_device *pwm) | ||
159 | { | ||
160 | pwm_disable(pwm); | ||
161 | kfree(pwm); | ||
162 | } | ||
163 | EXPORT_SYMBOL(pwm_free); | ||
diff --git a/drivers/mfd/ucb1400_core.c b/drivers/mfd/ucb1400_core.c index dbe280153f9e..d73f84ba0f08 100644 --- a/drivers/mfd/ucb1400_core.c +++ b/drivers/mfd/ucb1400_core.c | |||
@@ -114,7 +114,7 @@ static int ucb1400_core_probe(struct device *dev) | |||
114 | err3: | 114 | err3: |
115 | platform_device_put(ucb->ucb1400_ts); | 115 | platform_device_put(ucb->ucb1400_ts); |
116 | err2: | 116 | err2: |
117 | platform_device_unregister(ucb->ucb1400_gpio); | 117 | platform_device_del(ucb->ucb1400_gpio); |
118 | err1: | 118 | err1: |
119 | platform_device_put(ucb->ucb1400_gpio); | 119 | platform_device_put(ucb->ucb1400_gpio); |
120 | err0: | 120 | err0: |
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 1a968f34d679..1e7aaaf6cc6f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -95,6 +95,7 @@ enum wm831x_parent { | |||
95 | WM8311 = 0x8311, | 95 | WM8311 = 0x8311, |
96 | WM8312 = 0x8312, | 96 | WM8312 = 0x8312, |
97 | WM8320 = 0x8320, | 97 | WM8320 = 0x8320, |
98 | WM8321 = 0x8321, | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) | 101 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) |
@@ -1533,6 +1534,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1533 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); | 1534 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); |
1534 | break; | 1535 | break; |
1535 | 1536 | ||
1537 | case WM8321: | ||
1538 | parent = WM8321; | ||
1539 | wm831x->num_gpio = 12; | ||
1540 | dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev); | ||
1541 | break; | ||
1542 | |||
1536 | default: | 1543 | default: |
1537 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); | 1544 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); |
1538 | ret = -EINVAL; | 1545 | ret = -EINVAL; |
@@ -1607,6 +1614,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1607 | NULL, 0); | 1614 | NULL, 0); |
1608 | break; | 1615 | break; |
1609 | 1616 | ||
1617 | case WM8321: | ||
1618 | ret = mfd_add_devices(wm831x->dev, -1, | ||
1619 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | ||
1620 | NULL, 0); | ||
1621 | break; | ||
1622 | |||
1610 | default: | 1623 | default: |
1611 | /* If this happens the bus probe function is buggy */ | 1624 | /* If this happens the bus probe function is buggy */ |
1612 | BUG(); | 1625 | BUG(); |
@@ -1744,10 +1757,8 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, | |||
1744 | struct wm831x *wm831x; | 1757 | struct wm831x *wm831x; |
1745 | 1758 | ||
1746 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | 1759 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); |
1747 | if (wm831x == NULL) { | 1760 | if (wm831x == NULL) |
1748 | kfree(i2c); | ||
1749 | return -ENOMEM; | 1761 | return -ENOMEM; |
1750 | } | ||
1751 | 1762 | ||
1752 | i2c_set_clientdata(i2c, wm831x); | 1763 | i2c_set_clientdata(i2c, wm831x); |
1753 | wm831x->dev = &i2c->dev; | 1764 | wm831x->dev = &i2c->dev; |
@@ -1779,6 +1790,7 @@ static const struct i2c_device_id wm831x_i2c_id[] = { | |||
1779 | { "wm8311", WM8311 }, | 1790 | { "wm8311", WM8311 }, |
1780 | { "wm8312", WM8312 }, | 1791 | { "wm8312", WM8312 }, |
1781 | { "wm8320", WM8320 }, | 1792 | { "wm8320", WM8320 }, |
1793 | { "wm8321", WM8321 }, | ||
1782 | { } | 1794 | { } |
1783 | }; | 1795 | }; |
1784 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | 1796 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); |
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index b5807484b4c9..e81cc31e4202 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -536,6 +536,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) | |||
536 | } | 536 | } |
537 | 537 | ||
538 | out: | 538 | out: |
539 | kfree(wm8350->reg_cache); | ||
539 | return ret; | 540 | return ret; |
540 | } | 541 | } |
541 | 542 | ||
@@ -700,7 +701,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
700 | 701 | ||
701 | ret = wm8350_irq_init(wm8350, irq, pdata); | 702 | ret = wm8350_irq_init(wm8350, irq, pdata); |
702 | if (ret < 0) | 703 | if (ret < 0) |
703 | goto err; | 704 | goto err_free; |
704 | 705 | ||
705 | if (wm8350->irq_base) { | 706 | if (wm8350->irq_base) { |
706 | ret = request_threaded_irq(wm8350->irq_base + | 707 | ret = request_threaded_irq(wm8350->irq_base + |
@@ -738,8 +739,9 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
738 | 739 | ||
739 | err_irq: | 740 | err_irq: |
740 | wm8350_irq_exit(wm8350); | 741 | wm8350_irq_exit(wm8350); |
741 | err: | 742 | err_free: |
742 | kfree(wm8350->reg_cache); | 743 | kfree(wm8350->reg_cache); |
744 | err: | ||
743 | return ret; | 745 | return ret; |
744 | } | 746 | } |
745 | EXPORT_SYMBOL_GPL(wm8350_device_init); | 747 | EXPORT_SYMBOL_GPL(wm8350_device_init); |
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index 7795af4b1fe1..5fe5de166adb 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c | |||
@@ -80,7 +80,6 @@ static int wm8350_i2c_probe(struct i2c_client *i2c, | |||
80 | return ret; | 80 | return ret; |
81 | 81 | ||
82 | err: | 82 | err: |
83 | i2c_set_clientdata(i2c, NULL); | ||
84 | kfree(wm8350); | 83 | kfree(wm8350); |
85 | return ret; | 84 | return ret; |
86 | } | 85 | } |
@@ -90,7 +89,6 @@ static int wm8350_i2c_remove(struct i2c_client *i2c) | |||
90 | struct wm8350 *wm8350 = i2c_get_clientdata(i2c); | 89 | struct wm8350 *wm8350 = i2c_get_clientdata(i2c); |
91 | 90 | ||
92 | wm8350_device_exit(wm8350); | 91 | wm8350_device_exit(wm8350); |
93 | i2c_set_clientdata(i2c, NULL); | ||
94 | kfree(wm8350); | 92 | kfree(wm8350); |
95 | 93 | ||
96 | return 0; | 94 | return 0; |
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index e08aafa663dc..1bfef4846b07 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c | |||
@@ -415,7 +415,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c, | |||
415 | return 0; | 415 | return 0; |
416 | 416 | ||
417 | struct_err: | 417 | struct_err: |
418 | i2c_set_clientdata(i2c, NULL); | ||
419 | kfree(wm8400); | 418 | kfree(wm8400); |
420 | err: | 419 | err: |
421 | return ret; | 420 | return ret; |
@@ -426,7 +425,6 @@ static int wm8400_i2c_remove(struct i2c_client *i2c) | |||
426 | struct wm8400 *wm8400 = i2c_get_clientdata(i2c); | 425 | struct wm8400 *wm8400 = i2c_get_clientdata(i2c); |
427 | 426 | ||
428 | wm8400_release(wm8400); | 427 | wm8400_release(wm8400); |
429 | i2c_set_clientdata(i2c, NULL); | ||
430 | kfree(wm8400); | 428 | kfree(wm8400); |
431 | 429 | ||
432 | return 0; | 430 | return 0; |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index ec71c9368906..b3b2aaf89dbe 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -326,8 +326,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * | 326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * |
327 | ARRAY_SIZE(wm8994_main_supplies), | 327 | ARRAY_SIZE(wm8994_main_supplies), |
328 | GFP_KERNEL); | 328 | GFP_KERNEL); |
329 | if (!wm8994->supplies) | 329 | if (!wm8994->supplies) { |
330 | ret = -ENOMEM; | ||
330 | goto err; | 331 | goto err; |
332 | } | ||
331 | 333 | ||
332 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 334 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) |
333 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 335 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
@@ -495,10 +497,8 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
495 | struct wm8994 *wm8994; | 497 | struct wm8994 *wm8994; |
496 | 498 | ||
497 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); | 499 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); |
498 | if (wm8994 == NULL) { | 500 | if (wm8994 == NULL) |
499 | kfree(i2c); | ||
500 | return -ENOMEM; | 501 | return -ENOMEM; |
501 | } | ||
502 | 502 | ||
503 | i2c_set_clientdata(i2c, wm8994); | 503 | i2c_set_clientdata(i2c, wm8994); |
504 | wm8994->dev = &i2c->dev; | 504 | wm8994->dev = &i2c->dev; |