diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 11:10:24 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 11:10:24 -0700 |
commit | 6eb59af580dcffc6f6982ac8ef6d27a1a5f26b27 (patch) | |
tree | af14aa39719eb15b1251ed612ce9fcf108e15c1d /drivers/mfd | |
parent | 4d230d4d030e34e6eb8911fb669d1b42298eca9e (diff) | |
parent | b52207ef4ea56f8c22288ec3387399aac72c26cf (diff) |
Merge tag 'mfd-for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"New Drivers:
- Add new driver for MAXIM MAX77620/MAX20024 PMIC
- Add new driver for Hisilicon HI665X PMIC
New Device Support:
- Add support for AXP809 in axp20x-rsb
- Add support for Power Supply in axp20x
New core features:
- devm_mfd_* managed resources
Fix-ups:
- Remove unused code (da9063-irq, wm8400-core, tps6105x,
smsc-ece1099, twl4030-power)
- Improve clean-up in error path (intel_quark_i2c_gpio)
- Explicitly include headers (syscon.h)
- Allow building as modules (max77693)
- Use IS_ENABLED() instead of rolling your own (dm355evm_msp,
wm8400-core)
- DT adaptions (axp20x, hi655x, arizona, max77620)
- Remove CLK_IS_ROOT flag (intel-lpss, intel_quark)
- Move to gpiochip API (asic3, dm355evm_msp, htc-egpio, htc-i2cpld,
sm501, tc6393xb, tps65010, ucb1x00, vexpress)
- Make use of devm_mfd_* calls (act8945a, as3711, atmel-hlcdc,
bcm590xx, hi6421-pmic-core, lp3943, menf21bmc, mt6397, rdc321x,
rk808, rn5t618, rt5033, sky81452, stw481x, tps6507x, tps65217,
wm8400)
Bug Fixes"
- Fix ACPI child matching (mfd-core)
- Fix start-up ordering issues (mt6397-core, arizona-core)
- Fix forgotten register state on resume (intel-lpss)
- Fix Clock related issues (twl6040)
- Fix scheduling whilst atomic (omap-usb-tll)
- Kconfig changes (vexpress)"
* tag 'mfd-for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (73 commits)
mfd: hi655x: Add MFD driver for hi655x
mfd: ab8500-debugfs: Trivial fix of spelling mistake on "between"
mfd: vexpress: Add !ARCH_USES_GETTIMEOFFSET dependency
mfd: Add device-tree binding doc for PMIC MAX77620/MAX20024
mfd: max77620: Add core driver for MAX77620/MAX20024
mfd: arizona: Add defines for GPSW values that can be used from DT
mfd: omap-usb-tll: Fix scheduling while atomic BUG
mfd: wm5110: ARIZONA_CLOCK_CONTROL should be volatile
mfd: axp20x: Add a cell for the ac power_supply part of the axp20x PMICs
mfd: intel_soc_pmic_core: Terminate panel control GPIO lookup table correctly
mfd: wl1273-core: Use devm_mfd_add_devices() for mfd_device registration
mfd: tps65910: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
mfd: sec: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
mfd: rc5t583: Use devm_mfd_add_devices and devm_request_threaded_irq
mfd: max77686: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
mfd: as3722: Use devm_mfd_add_devices and devm_regmap_add_irq_chip
mfd: twl4030-power: Remove driver path in file comment
MAINTAINERS: Add entry for X-Powers AXP family PMIC drivers
mfd: smsc-ece1099: Remove unnecessarily remove callback
mfd: Use IS_ENABLED(CONFIG_FOO) instead of checking FOO || FOO_MODULE
...
Diffstat (limited to 'drivers/mfd')
55 files changed, 1139 insertions, 482 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index eea61e349e26..1bcf601de5bc 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -134,7 +134,7 @@ config MFD_CROS_EC select MFD_CORE select CHROME_PLATFORMS select CROS_EC_PROTO - depends on X86 || ARM || COMPILE_TEST + depends on X86 || ARM || ARM64 || COMPILE_TEST help If you say Y here you get support for the ChromeOS Embedded Controller (EC) providing keyboard, battery and power services. @@ -319,6 +319,16 @@ config MFD_HI6421_PMIC menus in order to enable them. We communicate with the Hi6421 via memory-mapped I/O. +config MFD_HI655X_PMIC + tristate "HiSilicon Hi655X series PMU/Codec IC" + depends on ARCH_HISI || COMPILE_TEST + depends on OF + select MFD_CORE + select REGMAP_MMIO + select REGMAP_IRQ + help + Select this option to enable Hisilicon hi655x series pmic driver. + config HTC_EGPIO bool "HTC EGPIO support" depends on GPIOLIB && ARM @@ -527,6 +537,21 @@ config MFD_MAX14577 additional drivers must be enabled in order to use the functionality of the device. +config MFD_MAX77620 + bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support" + depends on I2C=y + depends on OF + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + select IRQ_DOMAIN + help + Say yes here to add support for Maxim Semiconductor MAX77620 and + MAX20024 which are Power Management IC with General purpose pins, + RTC, regulators, clock generator, watchdog etc. This driver + provides common support for accessing the device; additional drivers + must be enabled in order to use the functionality of the device. + config MFD_MAX77686 tristate "Maxim Semiconductor MAX77686/802 PMIC Support" depends on I2C @@ -543,8 +568,8 @@ config MFD_MAX77686 of the device. config MFD_MAX77693 - bool "Maxim Semiconductor MAX77693 PMIC Support" - depends on I2C=y + tristate "Maxim Semiconductor MAX77693 PMIC Support" + depends on I2C select MFD_CORE select REGMAP_I2C select REGMAP_IRQ @@ -1568,7 +1593,7 @@ endmenu config MFD_VEXPRESS_SYSREG bool "Versatile Express System Registers" - depends on VEXPRESS_CONFIG && GPIOLIB + depends on VEXPRESS_CONFIG && GPIOLIB && !ARCH_USES_GETTIMEOFFSET default y select CLKSRC_MMIO select GPIO_GENERIC_PLATFORM diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 5eaa6465d0a6..42a66e19e191 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -128,6 +128,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o obj-$(CONFIG_MFD_DA9150) += da9150-core.o obj-$(CONFIG_MFD_MAX14577) += max14577.o +obj-$(CONFIG_MFD_MAX77620) += max77620.o obj-$(CONFIG_MFD_MAX77686) += max77686.o obj-$(CONFIG_MFD_MAX77693) += max77693.o obj-$(CONFIG_MFD_MAX77843) += max77843.o @@ -195,6 +196,7 @@ obj-$(CONFIG_MFD_STW481X) += stw481x.o obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o +obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o obj-$(CONFIG_MFD_DLN2) += dln2.o obj-$(CONFIG_MFD_RT5033) += rt5033.o obj-$(CONFIG_MFD_SKY81452) += sky81452.o diff --git a/drivers/mfd/act8945a.c b/drivers/mfd/act8945a.c index 525b546ba42f..10c6d2da8822 100644 --- a/drivers/mfd/act8945a.c +++ b/drivers/mfd/act8945a.c @@ -46,8 +46,9 @@ static int act8945a_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, regmap); - ret = mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, act8945a_devs, - ARRAY_SIZE(act8945a_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, + act8945a_devs, ARRAY_SIZE(act8945a_devs), + NULL, 0, NULL); if (ret) { dev_err(&i2c->dev, "Failed to add sub devices\n"); return ret; @@ -56,13 +57,6 @@ static int act8945a_i2c_probe(struct i2c_client *i2c, return 0; } -static int act8945a_i2c_remove(struct i2c_client *i2c) -{ - mfd_remove_devices(&i2c->dev); - - return 0; -} - static const struct i2c_device_id act8945a_i2c_id[] = { { "act8945a", 0 }, {} @@ -81,7 +75,6 @@ static struct i2c_driver act8945a_i2c_driver = { .of_match_table = of_match_ptr(act8945a_of_match), }, .probe = act8945a_i2c_probe, - .remove = act8945a_i2c_remove, .id_table = act8945a_i2c_id, }; diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 5319f252790b..bf2717967597 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -908,12 +908,12 @@ static const char * const wm5102_supplies[] = { static const struct mfd_cell wm5102_devs[] = { { .name = "arizona-micsupp" }, + { .name = "arizona-gpio" }, { .name = "arizona-extcon", .parent_supplies = wm5102_supplies, .num_parent_supplies = 1, /* We only need MICVDD */ }, - { .name = "arizona-gpio" }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { @@ -925,12 +925,12 @@ static const struct mfd_cell wm5102_devs[] = { static const struct mfd_cell wm5110_devs[] = { { .name = "arizona-micsupp" }, + { .name = "arizona-gpio" }, { .name = "arizona-extcon", .parent_supplies = wm5102_supplies, .num_parent_supplies = 1, /* We only need MICVDD */ }, - { .name = "arizona-gpio" }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { @@ -966,12 +966,12 @@ static const char * const wm8997_supplies[] = { static const struct mfd_cell wm8997_devs[] = { { .name = "arizona-micsupp" }, + { .name = "arizona-gpio" }, { .name = "arizona-extcon", .parent_supplies = wm8997_supplies, .num_parent_supplies = 1, /* We only need MICVDD */ }, - { .name = "arizona-gpio" }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { @@ -982,12 +982,13 @@ static const struct mfd_cell wm8997_devs[] = { }; static const struct mfd_cell wm8998_devs[] = { + { .name = "arizona-micsupp" }, + { .name = "arizona-gpio" }, { .name = "arizona-extcon", .parent_supplies = wm5102_supplies, .num_parent_supplies = 1, /* We only need MICVDD */ }, - { .name = "arizona-gpio" }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { @@ -995,7 +996,6 @@ static const struct mfd_cell wm8998_devs[] = { .parent_supplies = wm5102_supplies, .num_parent_supplies = ARRAY_SIZE(wm5102_supplies), }, - { .name = "arizona-micsupp" }, }; int arizona_dev_init(struct arizona *arizona) diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 5fef014920a3..edeb4951366a 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -168,12 +168,15 @@ static struct irq_chip arizona_irq_chip = { .irq_set_wake = arizona_irq_set_wake, }; +static struct lock_class_key arizona_irq_lock_class; + static int arizona_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { struct arizona *data = h->host_data; irq_set_chip_data(virq, data); + irq_set_lockdep_class(virq, &arizona_irq_lock_class); irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq); irq_set_nested_thread(virq, 1); irq_set_noprobe(virq); diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c index 09e1483b99bc..67b12417585d 100644 --- a/drivers/mfd/as3711.c +++ b/drivers/mfd/as3711.c @@ -189,22 +189,14 @@ static int as3711_i2c_probe(struct i2c_client *client, as3711_subdevs[AS3711_BACKLIGHT].pdata_size = 0; } - ret = mfd_add_devices(as3711->dev, -1, as3711_subdevs, - ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL); + ret = devm_mfd_add_devices(as3711->dev, -1, as3711_subdevs, + ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL); if (ret < 0) dev_err(&client->dev, "add mfd devices failed: %d\n", ret); return ret; } -static int as3711_i2c_remove(struct i2c_client *client) -{ - struct as3711 *as3711 = i2c_get_clientdata(client); - - mfd_remove_devices(as3711->dev); - return 0; -} - static const struct i2c_device_id as3711_i2c_id[] = { {.name = "as3711", .driver_data = 0}, {} @@ -218,7 +210,6 @@ static struct i2c_driver as3711_i2c_driver = { .of_match_table = of_match_ptr(as3711_of_match), }, .probe = as3711_i2c_probe, - .remove = as3711_i2c_remove, .id_table = as3711_i2c_id, }; diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c index e1f597f97f86..f87342c211bc 100644 --- a/drivers/mfd/as3722.c +++ b/drivers/mfd/as3722.c @@ -385,9 +385,10 @@ static int as3722_i2c_probe(struct i2c_client *i2c, return ret; irq_flags = as3722->irq_flags | IRQF_ONESHOT; - ret = regmap_add_irq_chip(as3722->regmap, as3722->chip_irq, - irq_flags, -1, &as3722_irq_chip, - &as3722->irq_data); + ret = devm_regmap_add_irq_chip(as3722->dev, as3722->regmap, + as3722->chip_irq, + irq_flags, -1, &as3722_irq_chip, + &as3722->irq_data); if (ret < 0) { dev_err(as3722->dev, "Failed to add regmap irq: %d\n", ret); return ret; @@ -395,33 +396,20 @@ static int as3722_i2c_probe(struct i2c_client *i2c, ret = as3722_configure_pullups(as3722); if (ret < 0) - goto scrub; + return ret; - ret = mfd_add_devices(&i2c->dev, -1, as3722_devs, - ARRAY_SIZE(as3722_devs), NULL, 0, - regmap_irq_get_domain(as3722->irq_data)); + ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs, + ARRAY_SIZE(as3722_devs), NULL, 0, + regmap_irq_get_domain(as3722->irq_data)); if (ret) { dev_err(as3722->dev, "Failed to add MFD devices: %d\n", ret); - goto scrub; + return ret; } device_init_wakeup(as3722->dev, true); dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n"); return 0; - -scrub: - regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data); - return ret; -} - -static int as3722_i2c_remove(struct i2c_client *i2c) -{ - struct as3722 *as3722 = i2c_get_clientdata(i2c); - - mfd_remove_devices(as3722->dev); - regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data); - return 0; } static int __maybe_unused as3722_i2c_suspend(struct device *dev) @@ -470,7 +458,6 @@ static struct i2c_driver as3722_i2c_driver = { .pm = &as3722_pm_ops, }, .probe = as3722_i2c_probe, - .remove = as3722_i2c_remove, .id_table = as3722_i2c_id, }; diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 4dca6bc61f5b..0413c8159551 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -446,7 +446,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip, unsigned long flags; struct asic3 *asic; - asic = container_of(chip, struct asic3, gpio); + asic = gpiochip_get_data(chip); gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_BASE) { @@ -492,7 +492,7 @@ static int asic3_gpio_get(struct gpio_chip *chip, u32 mask = ASIC3_GPIO_TO_MASK(offset); struct asic3 *asic; - asic = container_of(chip, struct asic3, gpio); + asic = gpiochip_get_data(chip); gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_BASE) { @@ -513,7 +513,7 @@ static void asic3_gpio_set(struct gpio_chip *chip, unsigned long flags; struct asic3 *asic; - asic = container_of(chip, struct asic3, gpio); + asic = gpiochip_get_data(chip); gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_BASE) { @@ -540,7 +540,7 @@ static void asic3_gpio_set(struct gpio_chip *chip, static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - struct asic3 *asic = container_of(chip, struct asic3, gpio); + struct asic3 *asic = gpiochip_get_data(chip); return asic->irq_base + offset; } @@ -595,7 +595,7 @@ static __init int asic3_gpio_probe(struct platform_device *pdev, alt_reg[i]); } - return gpiochip_add(&asic->gpio); + return gpiochip_add_data(&asic->gpio, asic); } static int asic3_gpio_remove(struct platform_device *pdev) diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index 06c205868573..eca7ea69b81c 100644 --- a/drivers/mfd/atmel-hlcdc.c +++ b/drivers/mfd/atmel-hlcdc.c @@ -128,16 +128,9 @@ static int atmel_hlcdc_probe(struct platform_device *pdev) dev_set_drvdata(dev, hlcdc); - return mfd_add_devices(dev, -1, atmel_hlcdc_cells, - ARRAY_SIZE(atmel_hlcdc_cells), - NULL, 0, NULL); -} - -static int atmel_hlcdc_remove(struct platform_device *pdev) -{ - mfd_remove_devices(&pdev->dev); - - return 0; + return devm_mfd_add_devices(dev, -1, atmel_hlcdc_cells, + ARRAY_SIZE(atmel_hlcdc_cells), + NULL, 0, NULL); } static const struct of_device_id atmel_hlcdc_match[] = { @@ -152,7 +145,6 @@ MODULE_DEVICE_TABLE(of, atmel_hlcdc_match); static struct platform_driver atmel_hlcdc_driver = { .probe = atmel_hlcdc_probe, - .remove = atmel_hlcdc_remove, .driver = { .name = "atmel-hlcdc", .of_match_table = atmel_hlcdc_match, diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c index 28c20247c112..a407527bcd09 100644 --- a/drivers/mfd/axp20x-rsb.c +++ b/drivers/mfd/axp20x-rsb.c @@ -61,6 +61,7 @@ static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev) static const struct of_device_id axp20x_rsb_of_match[] = { { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, + { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID }, { }, }; MODULE_DEVICE_TABLE(of, axp20x_rsb_of_match); diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index a57d6e940610..e4e32978c377 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -37,6 +37,7 @@ static const char * const axp20x_model_names[] = { "AXP221", "AXP223", "AXP288", + "AXP809", }; static const struct regmap_range axp152_writeable_ranges[] = { @@ -85,6 +86,7 @@ static const struct regmap_access_table axp20x_volatile_table = { .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), }; +/* AXP22x ranges are shared with the AXP809, as they cover the same range */ static const struct regmap_range axp22x_writeable_ranges[] = { regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1), @@ -128,6 +130,12 @@ static struct resource axp152_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), }; +static struct resource axp20x_ac_power_supply_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), + DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), + DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"), +}; + static struct resource axp20x_pek_resources[] = { { .name = "PEK_DBR", @@ -211,6 +219,20 @@ static struct resource axp288_fuel_gauge_resources[] = { }, }; +static struct resource axp809_pek_resources[] = { + { + .name = "PEK_DBR", + .start = AXP809_IRQ_PEK_RIS_EDGE, + .end = AXP809_IRQ_PEK_RIS_EDGE, + .flags = IORESOURCE_IRQ, + }, { + .name = "PEK_DBF", + .start = AXP809_IRQ_PEK_FAL_EDGE, + .end = AXP809_IRQ_PEK_FAL_EDGE, + .flags = IORESOURCE_IRQ, + }, +}; + static const struct regmap_config axp152_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -378,6 +400,41 @@ static const struct regmap_irq axp288_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), }; +static const struct regmap_irq axp809_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7), + INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6), + INIT_REGMAP_IRQ(AXP809, ACIN_REMOVAL, 0, 5), + INIT_REGMAP_IRQ(AXP809, VBUS_OVER_V, 0, 4), + INIT_REGMAP_IRQ(AXP809, VBUS_PLUGIN, 0, 3), + INIT_REGMAP_IRQ(AXP809, VBUS_REMOVAL, 0, 2), + INIT_REGMAP_IRQ(AXP809, VBUS_V_LOW, 0, 1), + INIT_REGMAP_IRQ(AXP809, BATT_PLUGIN, 1, 7), + INIT_REGMAP_IRQ(AXP809, BATT_REMOVAL, 1, 6), + INIT_REGMAP_IRQ(AXP809, BATT_ENT_ACT_MODE, 1, 5), + INIT_REGMAP_IRQ(AXP809, BATT_EXIT_ACT_MODE, 1, 4), + INIT_REGMAP_IRQ(AXP809, CHARG, 1, 3), + INIT_REGMAP_IRQ(AXP809, CHARG_DONE, 1, 2), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH, 2, 7), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH_END, 2, 6), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW, 2, 5), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW_END, 2, 4), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH, 2, 3), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH_END, 2, 2), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW, 2, 1), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW_END, 2, 0), + INIT_REGMAP_IRQ(AXP809, DIE_TEMP_HIGH, 3, 7), + INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL1, 3, 1), + INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL2, 3, 0), + INIT_REGMAP_IRQ(AXP809, TIMER, 4, 7), + INIT_REGMAP_IRQ(AXP809, PEK_RIS_EDGE, 4, 6), + INIT_REGMAP_IRQ(AXP809, PEK_FAL_EDGE, 4, 5), + INIT_REGMAP_IRQ(AXP809, PEK_SHORT, 4, 4), + INIT_REGMAP_IRQ(AXP809, PEK_LONG, 4, 3), + INIT_REGMAP_IRQ(AXP809, PEK_OVER_OFF, 4, 2), + INIT_REGMAP_IRQ(AXP809, GPIO1_INPUT, 4, 1), + INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), +}; + static const struct regmap_irq_chip axp152_regmap_irq_chip = { .name = "axp152_irq_chip", .status_base = AXP152_IRQ1_STATE, @@ -428,6 +485,18 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = { }; +static const struct regmap_irq_chip axp809_regmap_irq_chip = { + .name = "axp809", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, + .mask_base = AXP20X_IRQ1_EN, + .mask_invert = true, + .init_ack_masked = true, + .irqs = axp809_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp809_regmap_irqs), + .num_regs = 5, +}; + static struct mfd_cell axp20x_cells[] = { { .name = "axp20x-pek", @@ -436,6 +505,11 @@ static struct mfd_cell axp20x_cells[] = { }, { .name = "axp20x-regulator", }, { + .name = "axp20x-ac-power-supply", + .of_compatible = "x-powers,axp202-ac-power-supply", + .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), + .resources = axp20x_ac_power_supply_resources, + }, { .name = "axp20x-usb-power-supply", .of_compatible = "x-powers,axp202-usb-power-supply", .num_resources = ARRAY_SIZE(axp20x_usb_power_supply_resources), @@ -572,6 +646,16 @@ static struct mfd_cell axp288_cells[] = { }, }; +static struct mfd_cell axp809_cells[] = { + { + .name = "axp20x-pek", + .num_resources = ARRAY_SIZE(axp809_pek_resources), + .resources = axp809_pek_resources, + }, { + .name = "axp20x-regulator", + }, +}; + static struct axp20x_dev *axp20x_pm_power_off; static void axp20x_power_off(void) { @@ -631,6 +715,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->regmap_cfg = &axp288_regmap_config; axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; break; + case AXP809_ID: + axp20x->nr_cells = ARRAY_SIZE(axp809_cells); + axp20x->cells = axp809_cells; + axp20x->regmap_cfg = &axp22x_regmap_config; + axp20x->regmap_irq_chip = &axp809_regmap_irq_chip; + break; default: dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); return -EINVAL; diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c index 320aaefee718..0d76d690176b 100644 --- a/drivers/mfd/bcm590xx.c +++ b/drivers/mfd/bcm590xx.c @@ -82,8 +82,8 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri, goto err; } - ret = mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs, - ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs, + ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL); if (ret < 0) { dev_err(&i2c_pri->dev, "failed to add sub-devices: %d\n", ret); goto err; @@ -96,12 +96,6 @@ err: return ret; } -static int bcm590xx_i2c_remove(struct i2c_client *i2c) -{ - mfd_remove_devices(&i2c->dev); - return 0; -} - static const struct of_device_id bcm590xx_of_match[] = { { .compatible = "brcm,bcm59056" }, { } @@ -120,7 +114,6 @@ static struct i2c_driver bcm590xx_i2c_driver = { .of_match_table = of_match_ptr(bcm590xx_of_match), }, .probe = bcm590xx_i2c_probe, - .remove = bcm590xx_i2c_remove, .id_table = bcm590xx_i2c_id, }; module_i2c_driver(bcm590xx_i2c_driver); diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index 26302634633c..7e903fcb8813 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c @@ -25,14 +25,6 @@ #define DA9063_REG_EVENT_B_OFFSET 1 #define DA9063_REG_EVENT_C_OFFSET 2 #define DA9063_REG_EVENT_D_OFFSET 3 -#define EVENTS_BUF_LEN 4 - -static const u8 mask_events_buf[] = { [0 ... (EVENTS_BUF_LEN - 1)] = ~0 }; - -struct da9063_irq_data { - u16 reg; - u8 mask; -}; static const struct regmap_irq da9063_irqs[] = { /* DA9063 event A register */ diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index ec4438ed2faf..14661ec5ef7f 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -33,25 +33,25 @@ * This driver was tested with firmware revision A4. */ -#if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE) +#if IS_ENABLED(CONFIG_INPUT_DM355EVM) #define msp_has_keyboard() true #else #define msp_has_keyboard() false #endif -#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +#if IS_ENABLED(CONFIG_LEDS_GPIO) #define msp_has_leds() true #else #define msp_has_leds() false #endif -#if defined(CONFIG_RTC_DRV_DM355EVM) || defined(CONFIG_RTC_DRV_DM355EVM_MODULE) +#if IS_ENABLED(CONFIG_RTC_DRV_DM355EVM) #define msp_has_rtc() true #else #define msp_has_rtc() false #endif -#if defined(CONFIG_VIDEO_TVP514X) || defined(CONFIG_VIDEO_TVP514X_MODULE) +#if IS_ENABLED(CONFIG_VIDEO_TVP514X) #define msp_has_tvp() true #else #define msp_has_tvp() false @@ -260,7 +260,7 @@ static int add_children(struct i2c_client *client) /* GPIO-ish stuff */ dm355evm_msp_gpio.parent = &client->dev; - status = gpiochip_add(&dm355evm_msp_gpio); + status = gpiochip_add_data(&dm355evm_msp_gpio, NULL); if (status < 0) return status; diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c index f9ded45a992d..3fd703fe3aba 100644 --- a/drivers/mfd/hi6421-pmic-core.c +++ b/drivers/mfd/hi6421-pmic-core.c @@ -76,8 +76,8 @@ static int hi6421_pmic_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmic); - ret = mfd_add_devices(&pdev->dev, 0, hi6421_devs, - ARRAY_SIZE(hi6421_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&pdev->dev, 0, hi6421_devs, + ARRAY_SIZE(hi6421_devs), NULL, 0, NULL); if (ret) { dev_err(&pdev->dev, "add mfd devices failed: %d\n", ret); return ret; @@ -86,13 +86,6 @@ static int hi6421_pmic_probe(struct platform_device *pdev) return 0; } -static int hi6421_pmic_remove(struct platform_device *pdev) -{ - mfd_remove_devices(&pdev->dev); - - return 0; -} - static const struct of_device_id of_hi6421_pmic_match_tbl[] = { { .compatible = "hisilicon,hi6421-pmic", }, { }, @@ -105,7 +98,6 @@ static struct platform_driver hi6421_pmic_driver = { .of_match_table = of_hi6421_pmic_match_tbl, }, .probe = hi6421_pmic_probe, - .remove = hi6421_pmic_remove, }; module_platform_driver(hi6421_pmic_driver); diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c new file mode 100644 index 000000000000..05ddc7882362 --- /dev/null +++ b/drivers/mfd/hi655x-pmic.c @@ -0,0 +1,162 @@ +/* + * Device driver for MFD hi655x PMIC + * + * Copyright (c) 2016 Hisilicon. + * + * Authors: + * Chen Feng <puck.chen@hisilicon.com> + * Fei Wang <w.f@huawei.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/gpio.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/mfd/core.h> +#include <linux/mfd/hi655x-pmic.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +static const struct mfd_cell hi655x_pmic_devs[] = { + { .name = "hi655x-regulator", }, +}; + +static const struct regmap_irq hi655x_irqs[] = { + { .reg_offset = 0, .mask = OTMP_D1R_INT }, + { .reg_offset = 0, .mask = VSYS_2P5_R_INT }, + { .reg_offset = 0, .mask = VSYS_UV_D3R_INT }, + { .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT }, + { .reg_offset = 0, .mask = PWRON_D4SR_INT }, + { .reg_offset = 0, .mask = PWRON_D20F_INT }, + { .reg_offset = 0, .mask = PWRON_D20R_INT }, + { .reg_offset = 0, .mask = RESERVE_INT }, +}; + +static const struct regmap_irq_chip hi655x_irq_chip = { + .name = "hi655x-pmic", + .irqs = hi655x_irqs, + .num_regs = 1, + .num_irqs = ARRAY_SIZE(hi655x_irqs), + .status_base = HI655X_IRQ_STAT_BASE, + .mask_base = HI655X_IRQ_MASK_BASE, +}; + +static struct regmap_config hi655x_regmap_config = { + .reg_bits = 32, + .reg_stride = HI655X_STRIDE, + .val_bits = 8, + .max_register = HI655X_BUS_ADDR(0xFFF), +}; + +static void hi655x_local_irq_clear(struct regmap *map) +{ + int i; + + regmap_write(map, HI655X_ANA_IRQM_BASE, HI655X_IRQ_CLR); + for (i = 0; i < HI655X_IRQ_ARRAY; i++) { + regmap_write(map, HI655X_IRQ_STAT_BASE + i * HI655X_STRIDE, + HI655X_IRQ_CLR); + } +} + +static int hi655x_pmic_probe(struct platform_device *pdev) +{ + int ret; + struct hi655x_pmic *pmic; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + void __iomem *base; + + pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) + return -ENOMEM; + pmic->dev = dev; + + pmic->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!pmic->res) + return -ENOENT; + + base = devm_ioremap_resource(dev, pmic->res); + if (!base) + return -ENOMEM; + + pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base, + &hi655x_regmap_config); + + regmap_read(pmic->regmap, HI655X_BUS_ADDR(HI655X_VER_REG), &pmic->ver); + if ((pmic->ver < PMU_VER_START) || (pmic->ver > PMU_VER_END)) { + dev_warn(dev, "PMU version %d unsupported\n", pmic->ver); + return -EINVAL; + } + + hi655x_local_irq_clear(pmic->regmap); + + pmic->gpio = of_get_named_gpio(np, "pmic-gpios", 0); + if (!gpio_is_valid(pmic->gpio)) { + dev_err(dev, "Failed to get the pmic-gpios\n"); + return -ENODEV; + } + + ret = devm_gpio_request_one(dev, pmic->gpio, GPIOF_IN, + "hi655x_pmic_irq"); + if (ret < 0) { + dev_err(dev, "Failed to request gpio %d ret = %d\n", + pmic->gpio, ret); + return ret; + } + + ret = regmap_add_irq_chip(pmic->regmap, gpio_to_irq(pmic->gpio), + IRQF_TRIGGER_LOW | IRQF_NO_SUSPEND, 0, + &hi655x_irq_chip, &pmic->irq_data); + if (ret) { + dev_err(dev, "Failed to obtain 'hi655x_pmic_irq' %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, pmic); + + ret = mfd_add_devices(dev, PLATFORM_DEVID_AUTO, hi655x_pmic_devs, + ARRAY_SIZE(hi655x_pmic_devs), NULL, 0, NULL); + if (ret) { + dev_err(dev, "Failed to register device %d\n", ret); + regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data); + return ret; + } + + return 0; +} + +static int hi655x_pmic_remove(struct platform_device *pdev) +{ + struct hi655x_pmic *pmic = platform_get_drvdata(pdev); + + regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data); + mfd_remove_devices(&pdev->dev); + return 0; +} + +static const struct of_device_id hi655x_pmic_match[] = { + { .compatible = "hisilicon,hi655x-pmic", }, + {}, +}; + +static struct platform_driver hi655x_pmic_driver = { + .driver = { + .name = "hi655x-pmic", + .of_match_table = of_match_ptr(hi655x_pmic_match), + }, + .probe = hi655x_pmic_probe, + .remove = hi655x_pmic_remove, +}; +module_platform_driver(hi655x_pmic_driver); + +MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>"); +MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index c636b5f83cfb..513cfc5c8fb6 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c @@ -155,7 +155,7 @@ static int egpio_get(struct gpio_chip *chip, unsigned offset) pr_debug("egpio_get_value(%d)\n", chip->base + offset); - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); ei = dev_get_drvdata(egpio->dev); bit = egpio_bit(ei, offset); reg = egpio->reg_start + egpio_pos(ei, offset); @@ -170,7 +170,7 @@ static int egpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct egpio_chip *egpio; - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); return test_bit(offset, &egpio->is_out) ? -EINVAL : 0; } @@ -192,7 +192,7 @@ static void egpio_set(struct gpio_chip *chip, unsigned offset, int value) pr_debug("egpio_set(%s, %d(%d), %d)\n", chip->label, offset, offset+chip->base, value); - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); ei = dev_get_drvdata(egpio->dev); bit = egpio_bit(ei, offset); pos = egpio_pos(ei, offset); @@ -216,7 +216,7 @@ static int egpio_direction_output(struct gpio_chip *chip, { struct egpio_chip *egpio; - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); if (test_bit(offset, &egpio->is_out)) { egpio_set(chip, offset, value); return 0; @@ -330,7 +330,7 @@ static int __init egpio_probe(struct platform_device *pdev) chip->base = pdata->chip[i].gpio_base; chip->ngpio = pdata->chip[i].num_gpios; - gpiochip_add(chip); + gpiochip_add_data(chip, &ei->chip[i]); } /* Set initial pin values */ diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index bd6b96d07ab8..3f9eee5f8fb9 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -227,8 +227,7 @@ static irqreturn_t htcpld_handler(int irq, void *dev) static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val) { struct i2c_client *client; - struct htcpld_chip *chip_data = - container_of(chip, struct htcpld_chip, chip_out); + struct htcpld_chip *chip_data = gpiochip_get_data(chip); unsigned long flags; client = chip_data->client; @@ -257,14 +256,12 @@ static void htcpld_chip_set_ni(struct work_struct *work) static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset) { - struct htcpld_chip *chip_data; + struct htcpld_chip *chip_data = gpiochip_get_data(chip); u8 cache; if (!strncmp(chip->label, "htcpld-out", 10)) { - chip_data = container_of(chip, struct htcpld_chip, chip_out); cache = chip_data->cache_out; } else if (!strncmp(chip->label, "htcpld-in", 9)) { - chip_data = container_of(chip, struct htcpld_chip, chip_in); cache = chip_data->cache_in; } else return -EINVAL; @@ -291,9 +288,7 @@ static int htcpld_direction_input(struct gpio_chip *chip, static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset) { - struct htcpld_chip *chip_data; - - chip_data = container_of(chip, struct htcpld_chip, chip_in); + struct htcpld_chip *chip_data = gpiochip_get_data(chip); if (offset < chip_data->nirqs) return chip_data->irq_start + offset; @@ -451,14 +446,14 @@ static int htcpld_register_chip_gpio( gpio_chip->ngpio = plat_chip_data->num_gpios; /* Add the GPIO chips */ - ret = gpiochip_add(&(chip->chip_out)); + ret = gpiochip_add_data(&(chip->chip_out), chip); if (ret) { dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n", plat_chip_data->addr, ret); return ret; } - ret = gpiochip_add(&(chip->chip_in)); + ret = gpiochip_add_data(&(chip->chip_in), chip); if (ret) { dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n", plat_chip_data->addr, ret); diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 6352aaba96a4..41b113875d64 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -34,6 +34,7 @@ #define LPSS_DEV_SIZE 0x200 #define LPSS_PRIV_OFFSET 0x200 #define LPSS_PRIV_SIZE 0x100 +#define LPSS_PRIV_REG_COUNT (LPSS_PRIV_SIZE / 4) #define LPSS_IDMA64_OFFSET 0x800 #define LPSS_IDMA64_SIZE 0x800 @@ -76,6 +77,7 @@ struct intel_lpss { struct mfd_cell *cell; struct device *dev; void __iomem *priv; + u32 priv_ctx[LPSS_PRIV_REG_COUNT]; int devid; u32 caps; u32 active_ltr; @@ -336,8 +338,8 @@ static int intel_lpss_register_clock(struct intel_lpss *lpss) return 0; /* Root clock */ - clk = clk_register_fixed_rate(NULL, dev_name(lpss->dev), NULL, - CLK_IS_ROOT, lpss->info->clk_rate); + clk = clk_register_fixed_rate(NULL, dev_name(lpss->dev), NULL, 0, + lpss->info->clk_rate); if (IS_ERR(clk)) return PTR_ERR(clk); @@ -493,6 +495,16 @@ EXPORT_SYMBOL_GPL(intel_lpss_prepare); int intel_lpss_suspend(struct device *dev) { + struct intel_lpss *lpss = dev_get_drvdata(dev); + unsigned int i; + + /* Save device context */ + for (i = 0; i < LPSS_PRIV_REG_COUNT; i++) + lpss->priv_ctx[i] = readl(lpss->priv + i * 4); + + /* Put the device into reset state */ + writel(0, lpss->priv + LPSS_PRIV_RESETS); + return 0; } EXPORT_SYMBOL_GPL(intel_lpss_suspend); @@ -500,8 +512,13 @@ EXPORT_SYMBOL_GPL(intel_lpss_suspend); int intel_lpss_resume(struct device *dev) { struct intel_lpss *lpss = dev_get_drvdata(dev); + unsigned int i; - intel_lpss_init_dev(lpss); + intel_lpss_deassert_reset(lpss); + + /* Restore device context */ + for (i = 0; i < LPSS_PRIV_REG_COUNT; i++) + writel(lpss->priv_ctx[i], lpss->priv + i * 4); return 0; } diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index a24b35fc2b5b..7946d6e38b87 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -53,7 +53,7 @@ #define INTEL_QUARK_I2C_CLK_HZ 33000000 struct intel_quark_mfd { - struct pci_dev *pdev; + struct device *dev; struct clk *i2c_clk; struct clk_lookup *i2c_clk_lookup; }; @@ -123,14 +123,14 @@ static const struct pci_device_id intel_quark_mfd_ids[] = { }; MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids); -static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) +static int intel_quark_register_i2c_clk(struct device *dev) { - struct pci_dev *pdev = quark_mfd->pdev; + struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev); struct clk *i2c_clk; - i2c_clk = clk_register_fixed_rate(&pdev->dev, + i2c_clk = clk_register_fixed_rate(dev, INTEL_QUARK_I2C_CONTROLLER_CLK, NULL, - CLK_IS_ROOT, INTEL_QUARK_I2C_CLK_HZ); + 0, INTEL_QUARK_I2C_CLK_HZ); if (IS_ERR(i2c_clk)) return PTR_ERR(i2c_clk); @@ -139,18 +139,19 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) INTEL_QUARK_I2C_CONTROLLER_CLK); if (!quark_mfd->i2c_clk_lookup) { - dev_err(&pdev->dev, "Fixed clk register failed\n"); + clk_unregister(quark_mfd->i2c_clk); + dev_err(dev, "Fixed clk register failed\n"); return -ENOMEM; } return 0; } -static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev) +static void intel_quark_unregister_i2c_clk(struct device *dev) { - struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev); + struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev); - if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup) + if (!quark_mfd->i2c_clk_lookup) return; clkdev_drop(quark_mfd->i2c_clk_lookup); @@ -245,30 +246,38 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL); if (!quark_mfd) return -ENOMEM; - quark_mfd->pdev = pdev; - ret = intel_quark_register_i2c_clk(quark_mfd); + quark_mfd->dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, quark_mfd); + + ret = intel_quark_register_i2c_clk(&pdev->dev); if (ret) return ret; - dev_set_drvdata(&pdev->dev, quark_mfd); - ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]); if (ret) - return ret; + goto err_unregister_i2c_clk; ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]); if (ret) - return ret; + goto err_unregister_i2c_clk; + + ret = mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, + ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, + NULL); + if (ret) + goto err_unregister_i2c_clk; + + return 0; - return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, - ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, - NULL); +err_unregister_i2c_clk: + intel_quark_unregister_i2c_clk(&pdev->dev); + return ret; } static void intel_quark_mfd_remove(struct pci_dev *pdev) { - intel_quark_unregister_i2c_clk(pdev); + intel_quark_unregister_i2c_clk(&pdev->dev); mfd_remove_devices(&pdev->dev); } diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index d9e15cf7c6c8..12d6ebb4ae5d 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -35,6 +35,7 @@ static struct gpiod_lookup_table panel_gpio_table = { .table = { /* Panel EN/DISABLE */ GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH), + { }, }, }; diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c index eecbb13de1bd..65a2a8f14e74 100644 --- a/drivers/mfd/lp3943.c +++ b/drivers/mfd/lp3943.c @@ -123,16 +123,9 @@ static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id) lp3943->mux_cfg = lp3943_mux_cfg; i2c_set_clientdata(cl, lp3943); - return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs), - NULL, 0, NULL); -} - -static int lp3943_remove(struct i2c_client *cl) -{ - struct lp3943 *lp3943 = i2c_get_clientdata(cl); - - mfd_remove_devices(lp3943->dev); - return 0; + return devm_mfd_add_devices(dev, -1, lp3943_devs, + ARRAY_SIZE(lp3943_devs), + NULL, 0, NULL); } static const struct i2c_device_id lp3943_ids[] = { @@ -151,7 +144,6 @@ MODULE_DEVICE_TABLE(of, lp3943_of_match); static struct i2c_driver lp3943_driver = { .probe = lp3943_probe, - .remove = lp3943_remove, .driver = { .name = "lp3943", .of_match_table = of_match_ptr(lp3943_of_match), diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c index c7a9825aa4ce..792d51bae20f 100644 --- a/drivers/mfd/lp8788-irq.c +++ b/drivers/mfd/lp8788-irq.c @@ -112,7 +112,7 @@ static irqreturn_t lp8788_irq_handler(int irq, void *ptr) struct lp8788_irq_data *irqd = ptr; struct lp8788 *lp = irqd->lp; u8 status[NUM_REGS], addr, mask; - bool handled; + bool handled = false; int i; if (lp8788_read_multi_bytes(lp, LP8788_INT_1, status, NUM_REGS)) diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c new file mode 100644 index 000000000000..199d261990be --- /dev/null +++ b/drivers/mfd/max77620.c @@ -0,0 +1,590 @@ +/* + * Maxim MAX77620 MFD Driver + * + * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * + * Author: + * Laxman Dewangan <ldewangan@nvidia.com> + * Chaitanya Bandi <bandik@nvidia.com> + * Mallikarjun Kasoju <mkasoju@nvidia.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/****************** Teminology used in driver ******************** + * Here are some terminology used from datasheet for quick reference: + * Flexible Power Sequence (FPS): + * The Flexible Power Sequencer (FPS) allows each regulator to power up under + * hardware or software control. Additionally, each regulator can power on + * independently or among a group of other regulators with an adjustable + * power-up and power-down delays (sequencing). GPIO1, GPIO2, and GPIO3 can + * be programmed to be part of a sequence allowing external regulators to be + * sequenced along with internal regulators. 32KHz clock can be programmed to + * be part of a sequence. + * There is 3 FPS confguration registers and all resources are configured to + * any of these FPS or no FPS. + */ + +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/mfd/core.h> +#include <linux/mfd/max77620.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +static struct resource gpio_resources[] = { + DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO), +}; + +static struct resource power_resources[] = { + DEFINE_RES_IRQ(MAX77620_IRQ_LBT_MBATLOW), +}; + +static struct resource rtc_resources[] = { + DEFINE_RES_IRQ(MAX77620_IRQ_TOP_RTC), +}; + +static struct resource thermal_resources[] = { + DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM1), + DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM2), +}; + +static const struct regmap_irq max77620_top_irqs[] = { + REGMAP_IRQ_REG(MAX77620_IRQ_TOP_GLBL, 0, MAX77620_IRQ_TOP_GLBL_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_TOP_SD, 0, MAX77620_IRQ_TOP_SD_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_TOP_LDO, 0, MAX77620_IRQ_TOP_LDO_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_TOP_GPIO, 0, MAX77620_IRQ_TOP_GPIO_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_TOP_RTC, 0, MAX77620_IRQ_TOP_RTC_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_TOP_32K, 0, MAX77620_IRQ_TOP_32K_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_TOP_ONOFF, 0, MAX77620_IRQ_TOP_ONOFF_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_LBT_MBATLOW, 1, MAX77620_IRQ_LBM_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM1, 1, MAX77620_IRQ_TJALRM1_MASK), + REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM2, 1, MAX77620_IRQ_TJALRM2_MASK), +}; + +static const struct mfd_cell max77620_children[] = { + { .name = "max77620-pinctrl", }, + { .name = "max77620-clock", }, + { .name = "max77620-pmic", }, + { .name = "max77620-watchdog", }, + { + .name = "max77620-gpio", + .resources = gpio_resources, + .num_resources = ARRAY_SIZE(gpio_resources), + }, { + .name = "max77620-rtc", + .resources = rtc_resources, + .num_resources = ARRAY_SIZE(rtc_resources), + }, { + .name = "max77620-power", + .resources = power_resources, + .num_resources = ARRAY_SIZE(power_resources), + }, { + .name = "max77620-thermal", + .resources = thermal_resources, + .num_resources = ARRAY_SIZE(thermal_resources), + }, +}; + +static const struct mfd_cell max20024_children[] = { + { .name = "max20024-pinctrl", }, + { .name = "max77620-clock", }, + { .name = "max20024-pmic", }, + { .name = "max77620-watchdog", }, + { + .name = "max77620-gpio", + .resources = gpio_resources, + .num_resources = ARRAY_SIZE(gpio_resources), + }, { + .name = "max77620-rtc", + .resources = rtc_resources, + .num_resources = ARRAY_SIZE(rtc_resources), + }, { + .name = "max20024-power", + .resources = power_resources, + .num_resources = ARRAY_SIZE(power_resources), + }, +}; + +static struct regmap_irq_chip max77620_top_irq_chip = { + .name = "max77620-top", + .irqs = max77620_top_irqs, + .num_irqs = ARRAY_SIZE(max77620_top_irqs), + .num_regs = 2, + .status_base = MAX77620_REG_IRQTOP, + .mask_base = MAX77620_REG_IRQTOPM, +}; + +static const struct regmap_range max77620_readable_ranges[] = { + regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4), +}; + +static const struct regmap_access_table max77620_readable_table = { + .yes_ranges = max77620_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(max77620_readable_ranges), +}; + +static const struct regmap_range max20024_readable_ranges[] = { + regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4), + regmap_reg_range(MAX20024_REG_MAX_ADD, MAX20024_REG_MAX_ADD), +}; + +static const struct regmap_access_table max20024_readable_table = { + .yes_ranges = max20024_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(max20024_readable_ranges), +}; + +static const struct regmap_range max77620_writable_ranges[] = { + regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4), +}; + +static const struct regmap_access_table max77620_writable_table = { + .yes_ranges = max77620_writable_ranges, + .n_yes_ranges = ARRAY_SIZE(max77620_writable_ranges), +}; + +static const struct regmap_range max77620_cacheable_ranges[] = { + regmap_reg_range(MAX77620_REG_SD0_CFG, MAX77620_REG_LDO_CFG3), + regmap_reg_range(MAX77620_REG_FPS_CFG0, MAX77620_REG_FPS_SD3), +}; + +static const struct regmap_access_table max77620_volatile_table = { + .no_ranges = max77620_cacheable_ranges, + .n_no_ranges = ARRAY_SIZE(max77620_cacheable_ranges), +}; + +static const struct regmap_config max77620_regmap_config = { + .name = "power-slave", + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX77620_REG_DVSSD4 + 1, + .cache_type = REGCACHE_RBTREE, + .rd_table = &max77620_readable_table, + .wr_table = &max77620_writable_table, + .volatile_table = &max77620_volatile_table, +}; + +static const struct regmap_config max20024_regmap_config = { + .name = "power-slave", + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX20024_REG_MAX_ADD + 1, + .cache_type = REGCACHE_RBTREE, + .rd_table = &max20024_readable_table, + .wr_table = &max77620_writable_table, + .volatile_table = &max77620_volatile_table, +}; + +/* max77620_get_fps_period_reg_value: Get FPS bit field value from + * requested periods. + * MAX77620 supports the FPS period of 40, 80, 160, 320, 540, 1280, 2560 + * and 5120 microseconds. MAX20024 supports the FPS period of 20, 40, 80, + * 160, 320, 540, 1280 and 2560 microseconds. + * The FPS register has 3 bits field to set the FPS period as + * bits max77620 max20024 + * 000 40 20 + * 001 80 40 + * ::: +*/ +static int max77620_get_fps_period_reg_value(struct max77620_chip *chip, + int tperiod) +{ + int fps_min_period; + int i; + + switch (chip->chip_id) { + case MAX20024: + fps_min_period = MAX20024_FPS_PERIOD_MIN_US; + break; + case MAX77620: + fps_min_period = MAX77620_FPS_PERIOD_MIN_US; + default: + return -EINVAL; + } + + for (i = 0; i < 7; i++) { + if (fps_min_period >= tperiod) + return i; + fps_min_period *= 2; + } + + return i; +} + +/* max77620_config_fps: Configure FPS configuration registers + * based on platform specific information. + */ +static int max77620_config_fps(struct max77620_chip *chip, + struct device_node *fps_np) +{ + struct device *dev = chip->dev; + unsigned int mask = 0, config = 0; + u32 fps_max_period; + u32 param_val; + int tperiod, fps_id; + int ret; + char fps_name[10]; + + switch (chip->chip_id) { + case MAX20024: + fps_max_period = MAX20024_FPS_PERIOD_MAX_US; + break; + case MAX77620: + fps_max_period = MAX77620_FPS_PERIOD_MAX_US; + default: + return -EINVAL; + } + + for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) { + sprintf(fps_name, "fps%d", fps_id); + if (!strcmp(fps_np->name, fps_name)) + break; + } + + if (fps_id == MAX77620_FPS_COUNT) { + dev_err(dev, "FPS node name %s is not valid\n", fps_np->name); + return -EINVAL; + } + + ret = of_property_read_u32(fps_np, "maxim,shutdown-fps-time-period-us", + ¶m_val); + if (!ret) { + mask |= MAX77620_FPS_TIME_PERIOD_MASK; + chip->shutdown_fps_period[fps_id] = min(param_val, + fps_max_period); + tperiod = max77620_get_fps_period_reg_value(chip, + chip->shutdown_fps_period[fps_id]); + config |= tperiod << MAX77620_FPS_TIME_PERIOD_SHIFT; + } + + ret = of_property_read_u32(fps_np, "maxim,suspend-fps-time-period-us", + ¶m_val); + if (!ret) + chip->suspend_fps_period[fps_id] = min(param_val, + fps_max_period); + + ret = of_property_read_u32(fps_np, "maxim,fps-event-source", + ¶m_val); + if (!ret) { + if (param_val > 2) { + dev_err(dev, "FPS%d event-source invalid\n", fps_id); + return -EINVAL; + } + mask |= MAX77620_FPS_EN_SRC_MASK; + config |= param_val << MAX77620_FPS_EN_SRC_SHIFT; + if (param_val == 2) { + mask |= MAX77620_FPS_ENFPS_SW_MASK; + config |= MAX77620_FPS_ENFPS_SW; + } + } + + if (!chip->sleep_enable && !chip->enable_global_lpm) { + ret = of_property_read_u32(fps_np, + "maxim,device-state-on-disabled-event", + ¶m_val); + if (!ret) { + if (param_val == 0) + chip->sleep_enable = true; + else if (param_val == 1) + chip->enable_global_lpm = true; + } + } + + ret = regmap_update_bits(chip->rmap, MAX77620_REG_FPS_CFG0 + fps_id, + mask, config); + if (ret < 0) { + dev_err(dev, "Failed to update FPS CFG: %d\n", ret); + return ret; + } + + return 0; +} + +static int max77620_initialise_fps(struct max77620_chip *chip) +{ + struct device *dev = chip->dev; + struct device_node *fps_np, *fps_child; + u8 config; + int fps_id; + int ret; + + for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) { + chip->shutdown_fps_period[fps_id] = -1; + chip->suspend_fps_period[fps_id] = -1; + } + + fps_np = of_get_child_by_name(dev->of_node, "fps"); + if (!fps_np) + goto skip_fps; + + for_each_child_of_node(fps_np, fps_child) { + ret = max77620_config_fps(chip, fps_child); + if (ret < 0) + return ret; + } + + config = chip->enable_global_lpm ? MAX77620_ONOFFCNFG2_SLP_LPM_MSK : 0; + ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, + MAX77620_ONOFFCNFG2_SLP_LPM_MSK, config); + if (ret < 0) { + dev_err(dev, "Failed to update SLP_LPM: %d\n", ret); + return ret; + } + +skip_fps: + /* Enable wake on EN0 pin */ + ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, + MAX77620_ONOFFCNFG2_WK_EN0, + MAX77620_ONOFFCNFG2_WK_EN0); + if (ret < 0) { + dev_err(dev, "Failed to update WK_EN0: %d\n", ret); + return ret; + } + + /* For MAX20024, SLPEN will be POR reset if CLRSE is b11 */ + if ((chip->chip_id == MAX20024) && chip->sleep_enable) { + config = MAX77620_ONOFFCNFG1_SLPEN | MAX20024_ONOFFCNFG1_CLRSE; + ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1, + config, config); + if (ret < 0) { + dev_err(dev, "Failed to update SLPEN: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int max77620_read_es_version(struct max77620_chip *chip) +{ + unsigned int val; + u8 cid_val[6]; + int i; + int ret; + + for (i = MAX77620_REG_CID0; i <= MAX77620_REG_CID5; i++) { + ret = regmap_read(chip->rmap, i, &val); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CID: %d\n", ret); + return ret; + } + dev_dbg(chip->dev, "CID%d: 0x%02x\n", + i - MAX77620_REG_CID0, val); + cid_val[i - MAX77620_REG_CID0] = val; + } + + /* CID4 is OTP Version and CID5 is ES version */ + dev_info(chip->dev, "PMIC Version OTP:0x%02X and ES:0x%X\n", + cid_val[4], MAX77620_CID5_DIDM(cid_val[5])); + + return ret; +} + +static int max77620_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct regmap_config *rmap_config; + struct max77620_chip *chip; + const struct mfd_cell *mfd_cells; + int n_mfd_cells; + int ret; + + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + i2c_set_clientdata(client, chip); + chip->dev = &client->dev; + chip->irq_base = -1; + chip->chip_irq = client->irq; + chip->chip_id = (enum max77620_chip_id)id->driver_data; + + switch (chip->chip_id) { + case MAX77620: + mfd_cells = max77620_children; + n_mfd_cells = ARRAY_SIZE(max77620_children); + rmap_config = &max77620_regmap_config; + break; + case MAX20024: + mfd_cells = max20024_children; + n_mfd_cells = ARRAY_SIZE(max20024_children); + rmap_config = &max20024_regmap_config; + break; + default: + dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id); + return -EINVAL; + } + + chip->rmap = devm_regmap_init_i2c(client, rmap_config); + if (IS_ERR(chip->rmap)) { + ret = PTR_ERR(chip->rmap); + dev_err(chip->dev, "Failed to intialise regmap: %d\n", ret); + return ret; + } + + ret = max77620_read_es_version(chip); + if (ret < 0) + return ret; + + ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, + IRQF_ONESHOT | IRQF_SHARED, + chip->irq_base, &max77620_top_irq_chip, + &chip->top_irq_data); + if (ret < 0) { + dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret); + return ret; + } + + ret = max77620_initialise_fps(chip); + if (ret < 0) + return ret; + + ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, + mfd_cells, n_mfd_cells, NULL, 0, + regmap_irq_get_domain(chip->top_irq_data)); + if (ret < 0) { + dev_err(chip->dev, "Failed to add MFD children: %d\n", ret); + return ret; + } + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int max77620_set_fps_period(struct max77620_chip *chip, + int fps_id, int time_period) +{ + int period = max77620_get_fps_period_reg_value(chip, time_period); + int ret; + + ret = regmap_update_bits(chip->rmap, MAX77620_REG_FPS_CFG0 + fps_id, + MAX77620_FPS_TIME_PERIOD_MASK, + period << MAX77620_FPS_TIME_PERIOD_SHIFT); + if (ret < 0) { + dev_err(chip->dev, "Failed to update FPS period: %d\n", ret); + return ret; + } + + return 0; +} + +static int max77620_i2c_suspend(struct device *dev) +{ + struct max77620_chip *chip = dev_get_drvdata(dev); + struct i2c_client *client = to_i2c_client(dev); + unsigned int config; + int fps; + int ret; + + for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) { + if (chip->suspend_fps_period[fps] < 0) + continue; + + ret = max77620_set_fps_period(chip, fps, + chip->suspend_fps_period[fps]); + if (ret < 0) + return ret; + } + + /* + * For MAX20024: No need to configure SLPEN on suspend as + * it will be configured on Init. + */ + if (chip->chip_id == MAX20024) + goto out; + + config = (chip->sleep_enable) ? MAX77620_ONOFFCNFG1_SLPEN : 0; + ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1, + MAX77620_ONOFFCNFG1_SLPEN, + config); + if (ret < 0) { + dev_err(dev, "Failed to configure sleep in suspend: %d\n", ret); + return ret; + } + + /* Disable WK_EN0 */ + ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, + MAX77620_ONOFFCNFG2_WK_EN0, 0); + if (ret < 0) { + dev_err(dev, "Failed to configure WK_EN in suspend: %d\n", ret); + return ret; + } + +out: + disable_irq(client->irq); + + return 0; +} + +static int max77620_i2c_resume(struct device *dev) +{ + struct max77620_chip *chip = dev_get_drvdata(dev); + struct i2c_client *client = to_i2c_client(dev); + int ret; + int fps; + + for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) { + if (chip->shutdown_fps_period[fps] < 0) + continue; + + ret = max77620_set_fps_period(chip, fps, + chip->shutdown_fps_period[fps]); + if (ret < 0) + return ret; + } + + /* + * For MAX20024: No need to configure WKEN0 on resume as + * it is configured on Init. + */ + if (chip->chip_id == MAX20024) + goto out; + + /* Enable WK_EN0 */ + ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, + MAX77620_ONOFFCNFG2_WK_EN0, + MAX77620_ONOFFCNFG2_WK_EN0); + if (ret < 0) { + dev_err(dev, "Failed to configure WK_EN0 n resume: %d\n", ret); + return ret; + } + +out: + enable_irq(client->irq); + + return 0; +} +#endif + +static const struct i2c_device_id max77620_id[] = { + {"max77620", MAX77620}, + {"max20024", MAX20024}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, max77620_id); + +static const struct dev_pm_ops max77620_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(max77620_i2c_suspend, max77620_i2c_resume) +}; + +static struct i2c_driver max77620_driver = { + .driver = { + .name = "max77620", + .pm = &max77620_pm_ops, + }, + .probe = max77620_probe, + .id_table = max77620_id, +}; + +module_i2c_driver(max77620_driver); + +MODULE_DESCRIPTION("MAX77620/MAX20024 Multi Function Device Core Driver"); +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); +MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>"); +MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index c1aff46e89d9..7b68ed72e9cb 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -2,7 +2,7 @@ * max77686.c - mfd core driver for the Maxim 77686/802 * * Copyright (C) 2012 Samsung Electronics - * Chiwoong Byun <woong.byun@smasung.com> + * Chiwoong Byun <woong.byun@samsung.com> * Jonghwa Lee <jonghwa3.lee@samsung.com> * * This program is free software; you can redistribute it and/or modify @@ -230,38 +230,24 @@ static int max77686_i2c_probe(struct i2c_client *i2c, return -ENODEV; } - ret = regmap_add_irq_chip(max77686->regmap, max77686->irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT | - IRQF_SHARED, 0, irq_chip, - &max77686->irq_data); + ret = devm_regmap_add_irq_chip(&i2c->dev, max77686->regmap, + max77686->irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT | + IRQF_SHARED, 0, irq_chip, + &max77686->irq_data); if (ret < 0) { dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret); return ret; } - ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL); + ret = devm_mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, + 0, NULL); if (ret < 0) { dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret); - goto err_del_irqc; + return ret; } return 0; - -err_del_irqc: - regmap_del_irq_chip(max77686->irq, max77686->irq_data); - - return ret; -} - -static int max77686_i2c_remove(struct i2c_client *i2c) -{ - struct max77686_dev *max77686 = i2c_get_clientdata(i2c); - - mfd_remove_devices(max77686->dev); - - regmap_del_irq_chip(max77686->irq, max77686->irq_data); - - return 0; } static const struct i2c_device_id max77686_i2c_id[] = { @@ -317,22 +303,10 @@ static struct i2c_driver max77686_i2c_driver = { .of_match_table = of_match_ptr(max77686_pmic_dt_match), }, .probe = max77686_i2c_probe, - .remove = max77686_i2c_remove, .id_table = max77686_i2c_id, }; -static int __init max77686_i2c_init(void) -{ - return i2c_add_driver(&max77686_i2c_driver); -} -/* init early so consumer devices can complete system boot */ -subsys_initcall(max77686_i2c_init); - -static void __exit max77686_i2c_exit(void) -{ - i2c_del_driver(&max77686_i2c_driver); -} -module_exit(max77686_i2c_exit); +module_i2c_driver(max77686_i2c_driver); MODULE_DESCRIPTION("MAXIM 77686/802 multi-function core driver"); MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>"); diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index b83b7a7da1ae..662ae0d9e334 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -2,7 +2,7 @@ * max77693.c - mfd core driver for the MAX 77693 * * Copyright (C) 2012 Samsung Electronics - * SangYoung Son <hello.son@smasung.com> + * SangYoung Son <hello.son@samsung.com> * * This program is not provided / owned by Maxim Integrated Products. * @@ -368,6 +368,7 @@ static const struct of_device_id max77693_dt_match[] = { { .compatible = "maxim,max77693" }, {}, }; +MODULE_DEVICE_TABLE(of, max77693_dt_match); #endif static struct i2c_driver max77693_i2c_driver = { @@ -381,18 +382,7 @@ static struct i2c_driver max77693_i2c_driver = { .id_table = max77693_i2c_id, }; -static int __init max77693_i2c_init(void) -{ - return i2c_add_driver(&max77693_i2c_driver); -} -/* init early so consumer devices can complete system boot */ -subsys_initcall(max77693_i2c_init); - -static void __exit max77693_i2c_exit(void) -{ - i2c_del_driver(&max77693_i2c_driver); -} -module_exit(max77693_i2c_exit); +module_i2c_driver(max77693_i2c_driver); MODULE_DESCRIPTION("MAXIM 77693 multi-function core driver"); MODULE_AUTHOR("SangYoung, Son <hello.son@samsung.com>"); diff --git a/drivers/mfd/menf21bmc.c b/drivers/mfd/menf21bmc.c index 1c274345820c..3ad2def947d8 100644 --- a/drivers/mfd/menf21bmc.c +++ b/drivers/mfd/menf21bmc.c @@ -96,8 +96,8 @@ menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids) return ret; } - ret = mfd_add_devices(&client->dev, 0, menf21bmc_cell, - ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL); + ret = devm_mfd_add_devices(&client->dev, 0, menf21bmc_cell, + ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL); if (ret < 0) { dev_err(&client->dev, "failed to add BMC sub-devices\n"); return ret; @@ -106,12 +106,6 @@ menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids) return 0; } -static int menf21bmc_remove(struct i2c_client *client) -{ - mfd_remove_devices(&client->dev); - return 0; -} - static const struct i2c_device_id menf21bmc_id_table[] = { { "menf21bmc" }, { } @@ -122,7 +116,6 @@ static struct i2c_driver menf21bmc_driver = { .driver.name = "menf21bmc", .id_table = menf21bmc_id_table, .probe = menf21bmc_probe, - .remove = menf21bmc_remove, }; module_i2c_driver(menf21bmc_driver); diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index fc1c1fc13813..3ac486a597f3 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -107,7 +107,7 @@ static void mfd_acpi_add_device(const struct mfd_cell *cell, strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id)); list_for_each_entry(child, &parent->children, node) { - if (acpi_match_device_ids(child, ids)) { + if (!acpi_match_device_ids(child, ids)) { adev = child; break; } @@ -334,6 +334,44 @@ void mfd_remove_devices(struct device *parent) } EXPORT_SYMBOL(mfd_remove_devices); +static void devm_mfd_dev_release(struct device *dev, void *res) +{ + mfd_remove_devices(dev); +} + +/** + * devm_mfd_add_devices - Resource managed version of mfd_add_devices() + * + * Returns 0 on success or an appropriate negative error number on failure. + * All child-devices of the MFD will automatically be removed when it gets + * unbinded. + */ +int devm_mfd_add_devices(struct device *dev, int id, + const struct mfd_cell *cells, int n_devs, + struct resource *mem_base, + int irq_base, struct irq_domain *domain) +{ + struct device **ptr; + int ret; + + ptr = devres_alloc(devm_mfd_dev_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = mfd_add_devices(dev, id, cells, n_devs, mem_base, + irq_base, domain); + if (ret < 0) { + devres_free(ptr); + return ret; + } + + *ptr = dev; + devres_add(dev, ptr); + + return ret; +} +EXPORT_SYMBOL(devm_mfd_add_devices); + int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) { struct mfd_cell cell_entry; diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 8e8d93249c09..e14d8b058f0c 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -267,17 +267,26 @@ static int mt6397_probe(struct platform_device *pdev) ret = regmap_read(pmic->regmap, MT6397_CID, &id); if (ret) { dev_err(pmic->dev, "Failed to read chip id: %d\n", ret); - goto fail_irq; + return ret; } + pmic->irq = platform_get_irq(pdev, 0); + if (pmic->irq <= 0) + return pmic->irq; + switch (id & 0xff) { case MT6323_CID_CODE: pmic->int_con[0] = MT6323_INT_CON0; pmic->int_con[1] = MT6323_INT_CON1; pmic->int_status[0] = MT6323_INT_STATUS0; pmic->int_status[1] = MT6323_INT_STATUS1; - ret = mfd_add_devices(&pdev->dev, -1, mt6323_devs, - ARRAY_SIZE(mt6323_devs), NULL, 0, NULL); + ret = mt6397_irq_init(pmic); + if (ret) + return ret; + + ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, + ARRAY_SIZE(mt6323_devs), NULL, + 0, NULL); break; case MT6397_CID_CODE: @@ -286,8 +295,13 @@ static int mt6397_probe(struct platform_device *pdev) pmic->int_con[1] = MT6397_INT_CON1; pmic->int_status[0] = MT6397_INT_STATUS0; pmic->int_status[1] = MT6397_INT_STATUS1; - ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs, - ARRAY_SIZE(mt6397_devs), NULL, 0, NULL); + ret = mt6397_irq_init(pmic); + if (ret) + return ret; + + ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, + ARRAY_SIZE(mt6397_devs), NULL, + 0, NULL); break; default: @@ -296,14 +310,6 @@ static int mt6397_probe(struct platform_device *pdev) break; } - pmic->irq = platform_get_irq(pdev, 0); - if (pmic->irq > 0) { - ret = mt6397_irq_init(pmic); - if (ret) - return ret; - } - -fail_irq: if (ret) { irq_domain_remove(pmic->irq_domain); dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); @@ -312,13 +318,6 @@ fail_irq: return ret; } -static int mt6397_remove(struct platform_device *pdev) -{ - mfd_remove_devices(&pdev->dev); - - return 0; -} - static const struct of_device_id mt6397_of_match[] = { { .compatible = "mediatek,mt6397" }, { .compatible = "mediatek,mt6323" }, @@ -334,7 +333,6 @@ MODULE_DEVICE_TABLE(platform, mt6397_id); static struct platform_driver mt6397_driver = { .probe = mt6397_probe, - .remove = mt6397_remove, .driver = { .name = "mt6397", .of_match_table = of_match_ptr(mt6397_of_match), diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index b7b3e8ee64f2..c30290f33430 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -269,6 +269,8 @@ static int usbtll_omap_probe(struct platform_device *pdev) if (IS_ERR(tll->ch_clk[i])) dev_dbg(dev, "can't get clock : %s\n", clkname); + else + clk_prepare(tll->ch_clk[i]); } pm_runtime_put_sync(dev); @@ -301,9 +303,12 @@ static int usbtll_omap_remove(struct platform_device *pdev) tll_dev = NULL; spin_unlock(&tll_lock); - for (i = 0; i < tll->nch; i++) - if (!IS_ERR(tll->ch_clk[i])) + for (i = 0; i < tll->nch; i++) { + if (!IS_ERR(tll->ch_clk[i])) { + clk_unprepare(tll->ch_clk[i]); clk_put(tll->ch_clk[i]); + } + } pm_runtime_disable(&pdev->dev); return 0; @@ -420,7 +425,7 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata) if (IS_ERR(tll->ch_clk[i])) continue; - r = clk_prepare_enable(tll->ch_clk[i]); + r = clk_enable(tll->ch_clk[i]); if (r) { dev_err(tll_dev, "Error enabling ch %d clock: %d\n", i, r); @@ -448,7 +453,7 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata) for (i = 0; i < tll->nch; i++) { if (omap_usb_mode_needs_tll(pdata->port_mode[i])) { if (!IS_ERR(tll->ch_clk[i])) - clk_disable_unprepare(tll->ch_clk[i]); + clk_disable(tll->ch_clk[i]); } } diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c index 3f8812daa304..f8dde59ea6af 100644 --- a/drivers/mfd/rc5t583-irq.c +++ b/drivers/mfd/rc5t583-irq.c @@ -389,17 +389,10 @@ int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base) irq_clear_status_flags(__irq, IRQ_NOREQUEST); } - ret = request_threaded_irq(irq, NULL, rc5t583_irq, IRQF_ONESHOT, - "rc5t583", rc5t583); + ret = devm_request_threaded_irq(rc5t583->dev, irq, NULL, rc5t583_irq, + IRQF_ONESHOT, "rc5t583", rc5t583); if (ret < 0) dev_err(rc5t583->dev, "Error in registering interrupt error: %d\n", ret); return ret; } - -int rc5t583_irq_exit(struct rc5t583 *rc5t583) -{ - if (rc5t583->chip_irq) - free_irq(rc5t583->chip_irq, rc5t583); - return 0; -} diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c index fc2b2d93f354..d12243d5ecb8 100644 --- a/drivers/mfd/rc5t583.c +++ b/drivers/mfd/rc5t583.c @@ -252,7 +252,6 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c, struct rc5t583 *rc5t583; struct rc5t583_platform_data *pdata = dev_get_platdata(&i2c->dev); int ret; - bool irq_init_success = false; if (!pdata) { dev_err(&i2c->dev, "Err: Platform data not found\n"); @@ -284,32 +283,16 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c, /* Still continue with warning, if irq init fails */ if (ret) dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret); - else - irq_init_success = true; } - ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, - ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL); + ret = devm_mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, + ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL); if (ret) { dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret); - goto err_add_devs; + return ret; } return 0; - -err_add_devs: - if (irq_init_success) - rc5t583_irq_exit(rc5t583); - return ret; -} - -static int rc5t583_i2c_remove(struct i2c_client *i2c) -{ - struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c); - - mfd_remove_devices(rc5t583->dev); - rc5t583_irq_exit(rc5t583); - return 0; } static const struct i2c_device_id rc5t583_i2c_id[] = { @@ -324,7 +307,6 @@ static struct i2c_driver rc5t583_i2c_driver = { .name = "rc5t583", }, .probe = rc5t583_i2c_probe, - .remove = rc5t583_i2c_remove, .id_table = rc5t583_i2c_id, }; diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 6575585f1d1f..2bd8c5b6d600 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c @@ -85,14 +85,10 @@ static int rdc321x_sb_probe(struct pci_dev *pdev, rdc321x_gpio_pdata.sb_pdev = pdev; rdc321x_wdt_pdata.sb_pdev = pdev; - return mfd_add_devices(&pdev->dev, -1, - rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), - NULL, 0, NULL); -} - -static void rdc321x_sb_remove(struct pci_dev *pdev) -{ - mfd_remove_devices(&pdev->dev); + return devm_mfd_add_devices(&pdev->dev, -1, + rdc321x_sb_cells, + ARRAY_SIZE(rdc321x_sb_cells), + NULL, 0, NULL); } static const struct pci_device_id rdc321x_sb_table[] = { @@ -105,7 +101,6 @@ static struct pci_driver rdc321x_sb_driver = { .name = "RDC321x Southbridge", .id_table = rdc321x_sb_table, .probe = rdc321x_sb_probe, - .remove = rdc321x_sb_remove, }; module_pci_driver(rdc321x_sb_driver); diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 4b1e4399754b..49d7f624fc94 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -213,9 +213,9 @@ static int rk808_probe(struct i2c_client *client, rk808->i2c = client; i2c_set_clientdata(client, rk808); - ret = mfd_add_devices(&client->dev, -1, - rk808s, ARRAY_SIZE(rk808s), - NULL, 0, regmap_irq_get_domain(rk808->irq_data)); + ret = devm_mfd_add_devices(&client->dev, -1, + rk808s, ARRAY_SIZE(rk808s), NULL, 0, + regmap_irq_get_domain(rk808->irq_data)); if (ret) { dev_err(&client->dev, "failed to add MFD devices %d\n", ret); goto err_irq; @@ -240,7 +240,6 @@ static int rk808_remove(struct i2c_client *client) struct rk808 *rk808 = i2c_get_clientdata(client); regmap_del_irq_chip(client->irq, rk808->irq_data); - mfd_remove_devices(&client->dev); pm_power_off = NULL; return 0; diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index 666857192dbe..0ad51d792feb 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -78,8 +78,8 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c, return ret; } - ret = mfd_add_devices(&i2c->dev, -1, rn5t618_cells, - ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL); + ret = devm_mfd_add_devices(&i2c->dev, -1, rn5t618_cells, + ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL); if (ret) { dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret); return ret; @@ -102,7 +102,6 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c) pm_power_off = NULL; } - mfd_remove_devices(&i2c->dev); return 0; } diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index 2b95485f0057..9bd089c56375 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -97,9 +97,9 @@ static int rt5033_i2c_probe(struct i2c_client *i2c, return ret; } - ret = mfd_add_devices(rt5033->dev, -1, rt5033_devs, - ARRAY_SIZE(rt5033_devs), NULL, 0, - regmap_irq_get_domain(rt5033->irq_data)); + ret = devm_mfd_add_devices(rt5033->dev, -1, rt5033_devs, + ARRAY_SIZE(rt5033_devs), NULL, 0, + regmap_irq_get_domain(rt5033->irq_data)); if (ret < 0) { dev_err(&i2c->dev, "Failed to add RT5033 child devices.\n"); return ret; @@ -110,13 +110,6 @@ static int rt5033_i2c_probe(struct i2c_client *i2c, return 0; } -static int rt5033_i2c_remove(struct i2c_client *i2c) -{ - mfd_remove_devices(&i2c->dev); - - return 0; -} - static const struct i2c_device_id rt5033_i2c_id[] = { { "rt5033", }, { } @@ -135,7 +128,6 @@ static struct i2c_driver rt5033_driver = { .of_match_table = of_match_ptr(rt5033_dt_match), }, .probe = rt5033_i2c_probe, - .remove = rt5033_i2c_remove, .id_table = rt5033_i2c_id, }; module_i2c_driver(rt5033_driver); diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 400e1d7d8d08..ca6b80d08ffc 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -481,29 +481,16 @@ static int sec_pmic_probe(struct i2c_client *i2c, /* If this happens the probe function is problem */ BUG(); } - ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL, - 0, NULL); + ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, + NULL, 0, NULL); if (ret) - goto err_mfd; + return ret; device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); sec_pmic_configure(sec_pmic); sec_pmic_dump_rev(sec_pmic); return ret; - -err_mfd: - sec_irq_exit(sec_pmic); - return ret; -} - -static int sec_pmic_remove(struct i2c_client *i2c) -{ - struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); - - mfd_remove_devices(sec_pmic->dev); - sec_irq_exit(sec_pmic); - return 0; } static void sec_pmic_shutdown(struct i2c_client *i2c) @@ -583,7 +570,6 @@ static struct i2c_driver sec_pmic_driver = { .of_match_table = of_match_ptr(sec_dt_match), }, .probe = sec_pmic_probe, - .remove = sec_pmic_remove, .shutdown = sec_pmic_shutdown, .id_table = sec_pmic_id, }; diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index d77de431cc50..5eb59c233d52 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -483,10 +483,11 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) return -EINVAL; } - ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - sec_pmic->irq_base, sec_irq_chip, - &sec_pmic->irq_data); + ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, + sec_pmic->irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + sec_pmic->irq_base, sec_irq_chip, + &sec_pmic->irq_data); if (ret != 0) { dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); return ret; @@ -500,8 +501,3 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) return 0; } - -void sec_irq_exit(struct sec_pmic_dev *sec_pmic) -{ - regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data); -} diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c index b0c9b0415650..30a2a677100f 100644 --- a/drivers/mfd/sky81452.c +++ b/drivers/mfd/sky81452.c @@ -64,19 +64,14 @@ static int sky81452_probe(struct i2c_client *client, cells[1].platform_data = pdata->regulator_init_data; cells[1].pdata_size = sizeof(*pdata->regulator_init_data); - ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL); + ret = devm_mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), + NULL, 0, NULL); if (ret) dev_err(dev, "failed to add child devices. err=%d\n", ret); return ret; } -static int sky81452_remove(struct i2c_client *client) -{ - mfd_remove_devices(&client->dev); - return 0; -} - static const struct i2c_device_id sky81452_ids[] = { { "sky81452" }, { } @@ -97,7 +92,6 @@ static struct i2c_driver sky81452_driver = { .of_match_table = of_match_ptr(sky81452_of_match), }, .probe = sky81452_probe, - .remove = sky81452_remove, .id_table = sky81452_ids, }; diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index c646784c5a7d..65cd0d2a822a 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -879,11 +879,6 @@ static int sm501_register_display(struct sm501_devdata *sm, #ifdef CONFIG_MFD_SM501_GPIO -static inline struct sm501_gpio_chip *to_sm501_gpio(struct gpio_chip *gc) -{ - return container_of(gc, struct sm501_gpio_chip, gpio); -} - static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio) { return container_of(gpio, struct sm501_devdata, gpio); @@ -892,7 +887,7 @@ static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio) static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip); + struct sm501_gpio_chip *smgpio = gpiochip_get_data(chip); unsigned long result; result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW); @@ -923,7 +918,7 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip, static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; unsigned long bit = 1 << offset; void __iomem *regs = smchip->regbase; @@ -948,7 +943,7 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) { - struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; void __iomem *regs = smchip->regbase; unsigned long bit = 1 << offset; @@ -974,7 +969,7 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) static int sm501_gpio_output(struct gpio_chip *chip, unsigned offset, int value) { - struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; unsigned long bit = 1 << offset; void __iomem *regs = smchip->regbase; @@ -1039,7 +1034,7 @@ static int sm501_gpio_register_chip(struct sm501_devdata *sm, gchip->base = base; chip->ourgpio = gpio; - return gpiochip_add(gchip); + return gpiochip_add_data(gchip, chip); } static int sm501_register_gpio(struct sm501_devdata *sm) diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c index a4c0df71c8b3..7f89e89b8a5e 100644 --- a/drivers/mfd/smsc-ece1099.c +++ b/drivers/mfd/smsc-ece1099.c @@ -80,15 +80,6 @@ err: return ret; } -static int smsc_i2c_remove(struct i2c_client *i2c) -{ - struct smsc *smsc = i2c_get_clientdata(i2c); - - mfd_remove_devices(smsc->dev); - - return 0; -} - static const struct i2c_device_id smsc_i2c_id[] = { { "smscece1099", 0}, {}, @@ -100,7 +91,6 @@ static struct i2c_driver smsc_i2c_driver = { .name = "smsc", }, .probe = smsc_i2c_probe, - .remove = smsc_i2c_remove, .id_table = smsc_i2c_id, }; diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c index ca613df36143..ab949eaca6ad 100644 --- a/drivers/mfd/stw481x.c +++ b/drivers/mfd/stw481x.c @@ -206,8 +206,8 @@ static int stw481x_probe(struct i2c_client *client, stw481x_cells[i].pdata_size = sizeof(*stw481x); } - ret = mfd_add_devices(&client->dev, 0, stw481x_cells, - ARRAY_SIZE(stw481x_cells), NULL, 0, NULL); + ret = devm_mfd_add_devices(&client->dev, 0, stw481x_cells, + ARRAY_SIZE(stw481x_cells), NULL, 0, NULL); if (ret) return ret; @@ -216,12 +216,6 @@ static int stw481x_probe(struct i2c_client *client, return ret; } -static int stw481x_remove(struct i2c_client *client) -{ - mfd_remove_devices(&client->dev); - return 0; -} - /* * This ID table is completely unused, as this is a pure * device-tree probed driver, but it has to be here due to @@ -246,7 +240,6 @@ static struct i2c_driver stw481x_driver = { .of_match_table = stw481x_match, }, .probe = stw481x_probe, - .remove = stw481x_remove, .id_table = stw481x_id, }; diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 1ecbfa40d1b3..d42d322ac7ca 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -24,7 +24,7 @@ #include <linux/mfd/core.h> #include <linux/mfd/tmio.h> #include <linux/mfd/tc6393xb.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <linux/slab.h> #define SCR_REVID 0x08 /* b Revision ID */ @@ -434,7 +434,7 @@ static struct mfd_cell tc6393xb_cells[] = { static int tc6393xb_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); /* XXX: does dsr also represent inputs? */ return !!(tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8)) @@ -444,7 +444,7 @@ static int tc6393xb_gpio_get(struct gpio_chip *chip, static void __tc6393xb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); u8 dsr; dsr = tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8)); @@ -459,7 +459,7 @@ static void __tc6393xb_gpio_set(struct gpio_chip *chip, static void tc6393xb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); unsigned long flags; spin_lock_irqsave(&tc6393xb->lock, flags); @@ -472,7 +472,7 @@ static void tc6393xb_gpio_set(struct gpio_chip *chip, static int tc6393xb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); unsigned long flags; u8 doecr; @@ -490,7 +490,7 @@ static int tc6393xb_gpio_direction_input(struct gpio_chip *chip, static int tc6393xb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); unsigned long flags; u8 doecr; @@ -517,7 +517,7 @@ static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base) tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input; tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output; - return gpiochip_add(&tc6393xb->gpio); + return gpiochip_add_data(&tc6393xb->gpio, tc6393xb); } /*--------------------------------------------------------------------------*/ diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index 51c54951c220..baa12ea666fb 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -21,7 +21,6 @@ #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/err.h> -#include <linux/regulator/driver.h> #include <linux/mfd/core.h> #include <linux/mfd/tps6105x.h> diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 495e4518fc29..d829a6131f09 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -34,7 +34,7 @@ #include <linux/i2c/tps65010.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> /*-------------------------------------------------------------------------*/ @@ -477,7 +477,7 @@ tps65010_output(struct gpio_chip *chip, unsigned offset, int value) if (offset < 4) { struct tps65010 *tps; - tps = container_of(chip, struct tps65010, chip); + tps = gpiochip_get_data(chip); if (!(tps->outmask & (1 << offset))) return -EINVAL; tps65010_set_gpio_out_value(offset + 1, value); @@ -494,7 +494,7 @@ static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset) int value; struct tps65010 *tps; - tps = container_of(chip, struct tps65010, chip); + tps = gpiochip_get_data(chip); if (offset < 4) { value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO); @@ -651,7 +651,7 @@ static int tps65010_probe(struct i2c_client *client, tps->chip.ngpio = 7; tps->chip.can_sleep = 1; - status = gpiochip_add(&tps->chip); + status = gpiochip_add_data(&tps->chip, tps); if (status < 0) dev_err(&client->dev, "can't add gpiochip, err %d\n", status); diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 1ab3dd6c8adf..40beb2f4350c 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -100,16 +100,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, tps6507x->read_dev = tps6507x_i2c_read_device; tps6507x->write_dev = tps6507x_i2c_write_device; - return mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, - ARRAY_SIZE(tps6507x_devs), NULL, 0, NULL); -} - -static int tps6507x_i2c_remove(struct i2c_client *i2c) -{ - struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c); - - mfd_remove_devices(tps6507x->dev); - return 0; + return devm_mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, + ARRAY_SIZE(tps6507x_devs), NULL, 0, NULL); } static const struct i2c_device_id tps6507x_i2c_id[] = { @@ -132,7 +124,6 @@ static struct i2c_driver tps6507x_i2c_driver = { .of_match_table = of_match_ptr(tps6507x_of_match), }, .probe = tps6507x_i2c_probe, - .remove = tps6507x_i2c_remove, .id_table = tps6507x_i2c_id, }; diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index d32b54426b70..049a6fcac651 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -205,8 +205,8 @@ static int tps65217_probe(struct i2c_client *client, return ret; } - ret = mfd_add_devices(tps->dev, -1, tps65217s, - ARRAY_SIZE(tps65217s), NULL, 0, NULL); + ret = devm_mfd_add_devices(tps->dev, -1, tps65217s, + ARRAY_SIZE(tps65217s), NULL, 0, NULL); if (ret < 0) { dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); return ret; @@ -235,15 +235,6 @@ static int tps65217_probe(struct i2c_client *client, return 0; } -static int tps65217_remove(struct i2c_client *client) -{ - struct tps65217 *tps = i2c_get_clientdata(client); - - mfd_remove_devices(tps->dev); - - return 0; -} - static const struct i2c_device_id tps65217_id_table[] = { {"tps65217", TPS65217}, { /* sentinel */ } @@ -257,7 +248,6 @@ static struct i2c_driver tps65217_driver = { }, .id_table = tps65217_id_table, .probe = tps65217_probe, - .remove = tps65217_remove, }; static int __init tps65217_init(void) diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index f7ab115483a9..11cab1582f2f 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -252,9 +252,10 @@ static int tps65910_irq_init(struct tps65910 *tps65910, int irq, } tps65910->chip_irq = irq; - ret = regmap_add_irq_chip(tps65910->regmap, tps65910->chip_irq, - IRQF_ONESHOT, pdata->irq_base, - tps6591x_irqs_chip, &tps65910->irq_data); + ret = devm_regmap_add_irq_chip(tps65910->dev, tps65910->regmap, + tps65910->chip_irq, + IRQF_ONESHOT, pdata->irq_base, + tps6591x_irqs_chip, &tps65910->irq_data); if (ret < 0) { dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret); tps65910->chip_irq = 0; @@ -262,13 +263,6 @@ static int tps65910_irq_init(struct tps65910 *tps65910, int irq, return ret; } -static int tps65910_irq_exit(struct tps65910 *tps65910) -{ - if (tps65910->chip_irq > 0) - regmap_del_irq_chip(tps65910->chip_irq, tps65910->irq_data); - return 0; -} - static bool is_volatile_reg(struct device *dev, unsigned int reg) { struct tps65910 *tps65910 = dev_get_drvdata(dev); @@ -510,29 +504,18 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, pm_power_off = tps65910_power_off; } - ret = mfd_add_devices(tps65910->dev, -1, - tps65910s, ARRAY_SIZE(tps65910s), - NULL, 0, - regmap_irq_get_domain(tps65910->irq_data)); + ret = devm_mfd_add_devices(tps65910->dev, -1, + tps65910s, ARRAY_SIZE(tps65910s), + NULL, 0, + regmap_irq_get_domain(tps65910->irq_data)); if (ret < 0) { dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret); - tps65910_irq_exit(tps65910); return ret; } return ret; } -static int tps65910_i2c_remove(struct i2c_client *i2c) -{ - struct tps65910 *tps65910 = i2c_get_clientdata(i2c); - - tps65910_irq_exit(tps65910); - mfd_remove_devices(tps65910->dev); - - return 0; -} - static const struct i2c_device_id tps65910_i2c_id[] = { { "tps65910", TPS65910 }, { "tps65911", TPS65911 }, @@ -547,7 +530,6 @@ static struct i2c_driver tps65910_i2c_driver = { .of_match_table = of_match_ptr(tps65910_of_match), }, .probe = tps65910_i2c_probe, - .remove = tps65910_i2c_remove, .id_table = tps65910_i2c_id, }; diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 04b539850e72..1beb722f6080 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -1,5 +1,4 @@ /* - * linux/drivers/i2c/chips/twl4030-power.c * * Handle TWL4030 Power initialization * diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 08a693cd38cc..852d5874aabb 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -291,7 +291,11 @@ int twl6040_power(struct twl6040 *twl6040, int on) if (twl6040->power_count++) goto out; - clk_prepare_enable(twl6040->clk32k); + ret = clk_prepare_enable(twl6040->clk32k); + if (ret) { + twl6040->power_count = 0; + goto out; + } /* Allow writes to the chip */ regcache_cache_only(twl6040->regmap, false); @@ -300,6 +304,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* use automatic power-up sequence */ ret = twl6040_power_up_automatic(twl6040); if (ret) { + clk_disable_unprepare(twl6040->clk32k); twl6040->power_count = 0; goto out; } @@ -307,6 +312,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* use manual power-up sequence */ ret = twl6040_power_up_manual(twl6040); if (ret) { + clk_disable_unprepare(twl6040->clk32k); twl6040->power_count = 0; goto out; } diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index bcafe1ecd71c..9ab9ec47ea75 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -28,7 +28,7 @@ #include <linux/mutex.h> #include <linux/mfd/ucb1x00.h> #include <linux/pm.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); @@ -109,7 +109,7 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned long flags; spin_lock_irqsave(&ucb->io_lock, flags); @@ -126,7 +126,7 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned val; ucb1x00_enable(ucb); @@ -138,7 +138,7 @@ static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned long flags; spin_lock_irqsave(&ucb->io_lock, flags); @@ -154,7 +154,7 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset , int value) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned long flags; unsigned old, mask = 1 << offset; @@ -181,7 +181,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO; } @@ -579,7 +579,7 @@ static int ucb1x00_probe(struct mcp *mcp) ucb->gpio.direction_input = ucb1x00_gpio_direction_input; ucb->gpio.direction_output = ucb1x00_gpio_direction_output; ucb->gpio.to_irq = ucb1x00_to_irq; - ret = gpiochip_add(&ucb->gpio); + ret = gpiochip_add_data(&ucb->gpio, ucb); if (ret) goto err_gpio_add; } else diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 855c0204f09a..201a3ea2a9d3 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -202,7 +202,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI, NULL, NULL, NULL, NULL, 0); mmc_gpio_chip->ngpio = 2; - gpiochip_add(mmc_gpio_chip); + gpiochip_add_data(mmc_gpio_chip, NULL); return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, vexpress_sysreg_cells, diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index f7c52d901040..708046592b33 100644 --- a/drivers/mfd/wl1273-core.c +++ b/drivers/mfd/wl1273-core.c @@ -170,15 +170,6 @@ static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) return 0; } -static int wl1273_core_remove(struct i2c_client *client) -{ - dev_dbg(&client->dev, "%s\n", __func__); - - mfd_remove_devices(&client->dev); - - return 0; -} - static int wl1273_core_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -237,8 +228,8 @@ static int wl1273_core_probe(struct i2c_client *client, dev_dbg(&client->dev, "%s: number of children: %d.\n", __func__, children); - r = mfd_add_devices(&client->dev, -1, core->cells, - children, NULL, 0, NULL); + r = devm_mfd_add_devices(&client->dev, -1, core->cells, + children, NULL, 0, NULL); if (r) goto err; @@ -258,7 +249,6 @@ static struct i2c_driver wl1273_core_driver = { }, .probe = wl1273_core_probe, .id_table = wl1273_driver_id_table, - .remove = wl1273_core_remove, }; static int __init wl1273_core_init(void) diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 8e74e71507e7..1ee68bd440fb 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -3066,6 +3066,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_AOD_IRQ_RAW_STATUS: case ARIZONA_FX_CTRL2: case ARIZONA_ASRC_STATUS: + case ARIZONA_CLOCK_CONTROL: case ARIZONA_DSP_STATUS: case ARIZONA_DSP1_STATUS_1: case ARIZONA_DSP1_STATUS_2: diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 3bd44a45c378..8a98a2fc74e1 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -35,27 +35,6 @@ static bool wm8400_volatile(struct device *dev, unsigned int reg) } } -/** - * wm8400_reg_read - Single register read - * - * @wm8400: Pointer to wm8400 control structure - * @reg: Register to read - * - * @return Read value - */ -u16 wm8400_reg_read(struct wm8400 *wm8400, u8 reg) -{ - unsigned int val; - int ret; - - ret = regmap_read(wm8400->regmap, reg, &val); - if (ret < 0) - return ret; - - return val; -} -EXPORT_SYMBOL_GPL(wm8400_reg_read); - int wm8400_block_read(struct wm8400 *wm8400, u8 reg, int count, u16 *data) { return regmap_bulk_read(wm8400->regmap, reg, data, count); @@ -70,7 +49,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) .pdata_size = sizeof(*wm8400), }; - return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); + return devm_mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); } /* @@ -111,7 +90,7 @@ static int wm8400_init(struct wm8400 *wm8400, ret = wm8400_register_codec(wm8400); if (ret != 0) { dev_err(wm8400->dev, "Failed to register codec\n"); - goto err_children; + return ret; } if (pdata && pdata->platform_init) { @@ -119,21 +98,12 @@ static int wm8400_init(struct wm8400 *wm8400, if (ret != 0) { dev_err(wm8400->dev, "Platform init failed: %d\n", ret); - goto err_children; + return ret; } } else dev_warn(wm8400->dev, "No platform initialisation supplied\n"); return 0; - -err_children: - mfd_remove_devices(wm8400->dev); - return ret; -} - -static void wm8400_release(struct wm8400 *wm8400) -{ - mfd_remove_devices(wm8400->dev); } static const struct regmap_config wm8400_regmap_config = { @@ -156,7 +126,7 @@ void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400) } EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) static int wm8400_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -176,15 +146,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c, return wm8400_init(wm8400, dev_get_platdata(&i2c->dev)); } -static int wm8400_i2c_remove(struct i2c_client *i2c) -{ - struct wm8400 *wm8400 = i2c_get_clientdata(i2c); - - wm8400_release(wm8400); - - return 0; -} - static const struct i2c_device_id wm8400_i2c_id[] = { { "wm8400", 0 }, { } @@ -196,7 +157,6 @@ static struct i2c_driver wm8400_i2c_driver = { .name = "WM8400", }, .probe = wm8400_i2c_probe, - .remove = wm8400_i2c_remove, .id_table = wm8400_i2c_id, }; #endif @@ -205,7 +165,7 @@ static int __init wm8400_module_init(void) { int ret = -ENODEV; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8400_i2c_driver); if (ret != 0) pr_err("Failed to register I2C driver: %d\n", ret); @@ -217,7 +177,7 @@ subsys_initcall(wm8400_module_init); static void __exit wm8400_module_exit(void) { -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8400_i2c_driver); #endif } |