From 65433fd561f089f232758efc2c6566b6b6febb47 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 20 Mar 2016 18:53:57 +0000 Subject: mfd: da9063: Remove unused array mask_events_buf mask_events_buf is not used, so remove this redundant array. Signed-off-by: Colin Ian King Signed-off-by: Lee Jones --- drivers/mfd/da9063-irq.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index 2630263..0aa760e 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c @@ -27,8 +27,6 @@ #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; -- cgit v1.1 From 7f0c5ae18d649ed2f4978cbf07c02a0ff732f23e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 19 Feb 2016 10:42:10 +0200 Subject: mfd: intel_quark_i2c_gpio: Remove clock tree on error path There is a potential resource leak in case when ->probe() fails. We have to unregister and remove clock tree which is done here. This is a follow up to previously pushed commit c4726abce63b ("mfd: intel_quark_i2c_gpio: Use clkdev_create()") that prevents double free() when clkdev_drop() followed by kfree() in devm_kcalloc() release stage. I leave Fixes tag here, but the backporting will require to backport the commit c4726abce63b ("mfd: intel_quark_i2c_gpio: Use clkdev_create()") first. Cc: stable@vger.kernel.org Fixes: 60ae5b9f5cdd (mfd: intel_quark_i2c_gpio: Add Intel Quark X1000 I2C-GPIO MFD Driver) Signed-off-by: Andy Shevchenko Acked-by: Stephen Boyd Signed-off-by: Lee Jones --- drivers/mfd/intel_quark_i2c_gpio.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index bdc5e27..7450f5d 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -139,6 +139,7 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) INTEL_QUARK_I2C_CONTROLLER_CLK); if (!quark_mfd->i2c_clk_lookup) { + clk_unregister(quark_mfd->i2c_clk); dev_err(&pdev->dev, "Fixed clk register failed\n"); return -ENOMEM; } @@ -150,7 +151,7 @@ static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev) { struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->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); @@ -246,25 +247,33 @@ 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; + dev_set_drvdata(&pdev->dev, quark_mfd); ret = intel_quark_register_i2c_clk(quark_mfd); 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; - return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, - ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, - NULL); + 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; + +err_unregister_i2c_clk: + intel_quark_unregister_i2c_clk(pdev); + return ret; } static void intel_quark_mfd_remove(struct pci_dev *pdev) -- cgit v1.1 From 9caac886397bdfd6c1a6b48493db6cd95bce313c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 19 Feb 2016 10:42:11 +0200 Subject: mfd: intel_quark_i2c_gpio: Switch to use struct device * There is no need to pass struct pci_dev * to intel_quark_register_i2c_clk() and intel_quark_unregister_i2c_clk(). Change the parameter to struct device *. As a result store it in the private struct instead of struct pci_dev *. Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel_quark_i2c_gpio.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 7450f5d..24c2d29 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,12 +123,12 @@ 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); if (IS_ERR(i2c_clk)) @@ -140,16 +140,16 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) if (!quark_mfd->i2c_clk_lookup) { clk_unregister(quark_mfd->i2c_clk); - dev_err(&pdev->dev, "Fixed clk register failed\n"); + 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_lookup) return; @@ -248,10 +248,10 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, if (!quark_mfd) return -ENOMEM; - quark_mfd->pdev = pdev; + quark_mfd->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, quark_mfd); - ret = intel_quark_register_i2c_clk(quark_mfd); + ret = intel_quark_register_i2c_clk(&pdev->dev); if (ret) return ret; @@ -272,13 +272,13 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, return 0; err_unregister_i2c_clk: - intel_quark_unregister_i2c_clk(pdev); + 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); } -- cgit v1.1 From ee414de525a9abf29e8a1b0c1b6f79f9e875213a Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 13 Mar 2016 03:02:58 +0200 Subject: mfd: core: Fix ACPI child matching by _HID/_CID If MDF child devices have separate ACPI nodes identified by _HID/_CID, they will not be assigned the intended ACPI companion. acpi_match_device_ids will return 0 if a the child device matches the _HID/_CID, so this patch changes the matching condition to check for 0 on success. Signed-off-by: Irina Tirdea Acked-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 88bd1b1..409da01 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; } -- cgit v1.1 From 22aab38e7b59fd79ce1045006be69a9abab58e5a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 11 Mar 2016 11:11:39 +0300 Subject: mfd: lp8788-irq: Uninitialized variable in irq handler Instead to being true/false, the "handled" is true/uninitialized. Presumably this doesn't cause that many problems in real life because normally we handle the IRQ. Fixes: eea6b7cc53aa ('mfd: Add lp8788 mfd driver') Signed-off-by: Dan Carpenter Acked-by: Milo Kim Signed-off-by: Lee Jones --- drivers/mfd/lp8788-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c index c7a9825..792d51b 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)) -- cgit v1.1 From c796c50b9c20b586cd8c3e3a57cea4f0762a60fc Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Tue, 5 Apr 2016 09:41:47 +0100 Subject: mfd: da9063: Remove unused struct da9063_irq_data and define EVENTS_BUF_LEN The structure da9063_irq_data and define EVENTS_BUF_LEN are not used, so remove the redundant entries. Signed-off-by: Steve Twiss Signed-off-by: Lee Jones --- drivers/mfd/da9063-irq.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index 0aa760e..7e903fc 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c @@ -25,12 +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 - -struct da9063_irq_data { - u16 reg; - u8 mask; -}; static const struct regmap_irq da9063_irqs[] = { /* DA9063 event A register */ -- cgit v1.1 From 073d4aca342029fc62fefa500bb11a556c5f7223 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 4 Apr 2016 16:54:18 +0900 Subject: mfd: max77693: Allow building as a module The consumer of max77693 regulators on Trats2 board (samsung-usb2-phy driver) supports deferred probing so the max77693 main MFD driver can be built now as a module. This gives more flexibility and removes manual ordering of init calls. Suggested-by: Paul Gortmaker Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 4 ++-- drivers/mfd/max77693.c | 14 ++------------ 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index eea61e3..aa1e7c3 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -543,8 +543,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 diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index b83b7a7..78e501f 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -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 "); -- cgit v1.1 From dedf24a28da67f6bf814cb5d05a5d12bb39093dc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 25 Mar 2016 14:27:09 +0000 Subject: mfd: arizona: Fix lockdep recursion warning on set_irq_wake Avoid a false recursive locking warning from lockdep by adding a lock class for the arizona IRQ chip. Signed-off-by: Charles Keepax Acked-by: Thomas Gleixner Signed-off-by: Lee Jones --- drivers/mfd/arizona-irq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 5fef014..edeb495 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); -- cgit v1.1 From 20147f0d4f50f6f0d1fbe1815fe3d4d0a6444a70 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 29 Mar 2016 17:22:26 +0800 Subject: mfd: axp20x: Add support for AXP809 PMIC The X-Powers AXP809 is a new PMIC that is paired with Allwinner's A80 SoC, along with a slave AXP806 PMIC. This PMIC is quite similar to the earlier AXP223, though the interrupts and regulator have changed a bit. This patch adds support for the interrupts and power button of the PMIC. Signed-off-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/axp20x-rsb.c | 1 + drivers/mfd/axp20x.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c index 28c2024..a407527 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 a57d6e9..1ce9232 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), @@ -211,6 +213,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 +394,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 +479,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", @@ -572,6 +635,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 +704,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; -- cgit v1.1 From a8f447be8056d9ce17bf7757d6de79426700bb8b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:55 +0530 Subject: mfd: Add resource managed APIs for mfd_add_devices Add resource managed API devm_mfd_add_devices() for the mfd_add_devices(). This helps in reducing code in error path as it is not required to call mfd_remove_devices() explicitly to remove all child-devices. In some cases, it also helps not to implement .remove() callback which get called during driver unbind. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 409da01..4b4c1d4 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -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; -- cgit v1.1 From f9932c6e66c17ca3d84a7c6424c844bea8003ffb Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:57 +0530 Subject: mfd: act8945a: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Wenyou Yang CC: Krzysztof Kozlowski Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/act8945a.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/act8945a.c b/drivers/mfd/act8945a.c index 525b546..10c6d2d 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, }; -- cgit v1.1 From 9c9983267deab5c268676d8ac15686923b6e5e19 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:58 +0530 Subject: mfd: as3711: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Guennadi Liakhovetski Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/as3711.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c index 09e1483..67b1241 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, }; -- cgit v1.1 From f32fb9a593704a32ddc395686fa00075d10df173 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:59 +0530 Subject: mfd: atmel-hlcdc: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. Signed-off-by: Laxman Dewangan Acked-by: Boris Brezillon Signed-off-by: Lee Jones --- drivers/mfd/atmel-hlcdc.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index 06c2058..eca7ea6 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, -- cgit v1.1 From 9148f2c01827fe1c8c8d589ac54b0f459759d78b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:00 +0530 Subject: mfd: bcm590xx: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Matt Porter Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/bcm590xx.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c index 320aaef..0d76d69 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); -- cgit v1.1 From 9c384b0268c69a36e6b5d9c6b336fb81a63d457e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:01 +0530 Subject: mfd: hi6421-pmic: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Guodong Xu Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/hi6421-pmic-core.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c index f9ded45..3fd703f 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); -- cgit v1.1 From c5f244549425c83835759f2d338967d0e798fda3 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:02 +0530 Subject: mfd: lp3943: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Milo Kim Signed-off-by: Laxman Dewangan Acked-by: Milo Kim Signed-off-by: Lee Jones --- drivers/mfd/lp3943.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c index eecbb13..65a2a8f1 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), -- cgit v1.1 From 7990ad17a9debc2c91ffc1413d01450c982fcb8d Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:03 +0530 Subject: mfd: menf21bmc: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. Signed-off-by: Laxman Dewangan Reviewed-by: Andreas Werner Signed-off-by: Lee Jones --- drivers/mfd/menf21bmc.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/menf21bmc.c b/drivers/mfd/menf21bmc.c index 1c27434..3ad2def 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); -- cgit v1.1 From 08e380a53a92a445bdfd98e09680237bf0c269aa Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:04 +0530 Subject: mfd: mt6397: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: John Crispin Signed-off-by: Laxman Dewangan Reviewed-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/mt6397-core.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 8e8d932..5a3ffa3 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -276,8 +276,9 @@ static int mt6397_probe(struct platform_device *pdev) 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 = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, + ARRAY_SIZE(mt6323_devs), NULL, + 0, NULL); break; case MT6397_CID_CODE: @@ -286,8 +287,9 @@ 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 = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, + ARRAY_SIZE(mt6397_devs), NULL, + 0, NULL); break; default: @@ -312,13 +314,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 +329,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), -- cgit v1.1 From 7360544c2b91d5689b635b2117f5e85986cf529b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:05 +0530 Subject: mfd: rdc321x: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Florian Fainelli Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/rdc321x-southbridge.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 6575585..2bd8c5b 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); -- cgit v1.1 From d5623161accbc567452700add15d76fc092b07fe Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:06 +0530 Subject: mfd: rk808: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and remove the call of mfd_remove_devices() from .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Chris Zhong Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/rk808.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 4b1e439..49d7f62 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; -- cgit v1.1 From f41206c9fd5c48becdb0f2f65328c5438f6ea34d Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:07 +0530 Subject: mfd: rn5t618: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and remove the call of mfd_remove_devices() from .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Beniamino Galvani Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/rn5t618.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index 6668571..0ad51d7 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; } -- cgit v1.1 From 6b719eba9f01cd65ede04e64f20f648f8dbe6359 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:08 +0530 Subject: mfd: rt5033: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Ingi Kim Signed-off-by: Laxman Dewangan Reviewed-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/rt5033.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index 2b95485..9bd089c 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); -- cgit v1.1 From 69633beaebf345cde6672a9ac7679c88fc0c3245 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:09 +0530 Subject: mfd: sky81452: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Gyungoh Yoo Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/sky81452.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c index b0c9b04..30a2a67 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, }; -- cgit v1.1 From e253fb0472e7a892176c7a65cef61a6aa75f8d2e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:10 +0530 Subject: mfd: stw481x: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. Signed-off-by: Laxman Dewangan Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/stw481x.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c index ca613df..ab949ea 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, }; -- cgit v1.1 From 5635d994fe870a0de2614e83bbf2d70f506651eb Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:11 +0530 Subject: mfd: tps6507x: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Todd Fischer Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/tps6507x.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 1ab3dd6..40beb2f 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, }; -- cgit v1.1 From b89b6b6bcd570a0beb1fc6fb8d0ecc20316413ab Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:12 +0530 Subject: mfd: tps65217: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Tony Lindgren Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/tps65217.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index d32b5442..049a6fc 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) -- cgit v1.1 From f3466e7764783ed4fae91ebe1653b0a08cca22bf Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:13 +0530 Subject: mfd: tps65910: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and remove the call of mfd_remove_devices() from .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Tony Lindgren Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/tps65910.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index f7ab115..8086e5d 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -510,10 +510,10 @@ 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); @@ -528,7 +528,6 @@ 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; } -- cgit v1.1 From 7825dc05601b38f99808830098fd4f512c876b4e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:14 +0530 Subject: mfd: wm8400: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Mark Brown Signed-off-by: Laxman Dewangan Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm8400-core.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 3bd44a4..9fd8230 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -70,7 +70,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 +111,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 +119,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 = { @@ -176,15 +167,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 +178,6 @@ static struct i2c_driver wm8400_i2c_driver = { .name = "WM8400", }, .probe = wm8400_i2c_probe, - .remove = wm8400_i2c_remove, .id_table = wm8400_i2c_id, }; #endif -- cgit v1.1 From 082cc468385dbc7bbdc234bf6f2577e64fc00bbb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:01 +0200 Subject: mfd: asic3: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Paul Parsons Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/asic3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 4dca6bc..0413c81 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) -- cgit v1.1 From 4363765c851313d460db86f2d41d2eebca0d9c17 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:02 +0200 Subject: mfd: dm355evm_msp: Switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/dm355evm_msp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index ec4438e..d7d59f8 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -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; -- cgit v1.1 From 8d5f095fc5f7e36f40a80e87317828be249ee454 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:03 +0200 Subject: mfd: htc-egpio: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Acked-by: Philipp Zabel Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/htc-egpio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index c636b5f..513cfc5 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 */ -- cgit v1.1 From ed1c9b3c18e33a69da0a911eadf4948ea7e5b5b9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:04 +0200 Subject: mfd: htc-i2cpld: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/htc-i2cpld.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index bd6b96d..3f9eee5 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); -- cgit v1.1 From 3a504105f0e4cf32464d596f3b30d23dbfd76520 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:05 +0200 Subject: mfd: sm501: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Ben Dooks Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/sm501.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index c646784..65cd0d2 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) -- cgit v1.1 From 4e125f62b73dffde17f4c53155654623ab2a9855 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:06 +0200 Subject: mfd: tc6393xb: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Dmitry Baryshkov Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/tc6393xb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 1ecbfa4..d42d322 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #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); } /*--------------------------------------------------------------------------*/ -- cgit v1.1 From 22e5e747e71f19ac3af60ce648f4c02c63ed3cc1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:07 +0200 Subject: mfd: tps65010: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/tps65010.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 495e451..d829a61 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -34,7 +34,7 @@ #include -#include +#include /*-------------------------------------------------------------------------*/ @@ -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); -- cgit v1.1 From 7d94352eba4f943734c19d172a834d0b2affec09 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:08 +0200 Subject: mfd: ucb1x00: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ucb1x00-core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index bcafe1e..9ab9ec4 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include 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 -- cgit v1.1 From 7ad073695dff7b1fc2a6ef2e8112d96a76fc8dc4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:09 +0200 Subject: mfd: vexpress-sysreg: Switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/vexpress-sysreg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 855c020..201a3ea2 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, -- cgit v1.1 From 630fd98c0a7fcba67d4b33440793b0c9bd1fb440 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 Apr 2016 11:04:51 +0900 Subject: mfd: max77686/max77693: Fix misspelled Samsung address Correct smasung.com into samsung.com. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/max77686.c | 2 +- drivers/mfd/max77693.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index c1aff46..0aa33d4 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 + * Chiwoong Byun * Jonghwa Lee * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 78e501f..662ae0d 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 + * SangYoung Son * * This program is not provided / owned by Maxim Integrated Products. * -- cgit v1.1 From 8a0aee4a7c8500278495012d8f4b653033df83a3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 4 Apr 2016 18:46:02 -0400 Subject: mfd: max77686: Use module_i2c_driver() instead of subsys initcall The driver's init and exit function don't do anything besides adding and deleting the I2C driver so the module_i2c_driver() macro could be used. Currently is not being used because the driver is initialized at subsys initcall level, claiming that this is done to allow consumers devices to use the resources provided by this driver. But dependencies are in DT so manual ordering of init calls is not necessary any more. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Lee Jones --- drivers/mfd/max77686.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 0aa33d4..7a0457e 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -321,18 +321,7 @@ static struct i2c_driver max77686_i2c_driver = { .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 "); -- cgit v1.1 From ba5776ab6f09800dd9ba8442185139661e065529 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 11 Apr 2016 10:27:32 -0700 Subject: mfd: cros_ec: Allow building for ARM64 There are platforms using the ChromeOS embeded controller on ARM64 now, so let's allow using this driver (without having to use COMPILE_TEST). Signed-off-by: Brian Norris Reviewed-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index aa1e7c3..cf7cbba 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. -- cgit v1.1 From 1387ff53568ba409eef072087fa02359b3a3551b Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Fri, 15 Apr 2016 16:30:29 +0800 Subject: mfd: mt6397: IRQ domain should initialize before mfd_add_devices() Some sub driver like RTC module need irq domain from parent to create irq mapping when driver initialize. so move mt6397_irq_init() before mfd_add_devices(). Acked-by: John Crispin Signed-off-by: Henry Chen Signed-off-by: Lee Jones --- drivers/mfd/mt6397-core.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 5a3ffa3..e14d8b0 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -267,15 +267,23 @@ 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 = 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); @@ -287,6 +295,10 @@ 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 = 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); @@ -298,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); -- cgit v1.1 From f83c218c1705a0d38fb9791bdee268c4092a37cb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 15 Apr 2016 13:18:47 +0100 Subject: mfd: arizona: Update device ordering to allow clean driver removal Since this commit: commit b9a8a271c38f ("mfd: make mfd_remove_devices() iterate in reverse order") The order in which the MFD children remove has been reversed, as our driver contains some dependencies between the devices we need to make some changes to ensure the driver unloads cleanly. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 5319f25..bf27179 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) -- cgit v1.1 From 0e10d549f6eebd0a26bf075309b6fb947f4c1cb2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 15 Apr 2016 17:44:18 +0300 Subject: mfd: wm8400-core: Delete wm8400_reg_read() There was a static checker warning in wm8400_reg_read() because we were returning u16 and that can't hold the negative error codes. The function isn't used, so let's just delete it. Signed-off-by: Dan Carpenter Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm8400-core.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 9fd8230..8166776 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); -- cgit v1.1 From 41a3da2b8e1639d983192e3650670df4ecc94cf7 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 18 Apr 2016 15:14:56 +0300 Subject: mfd: intel-lpss: Save register context on suspend All configurations are lost and the registers will have default values when the hardware is suspended and resumed, so saving the private register space context on suspend, and restoring it on resume. Fixes: 4b45efe85263 (mfd: Add support for Intel Sunrisepoint LPSS devices) Cc: stable@vger.kernel.org # v4.3+ Signed-off-by: Heikki Krogerus Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 1bbbe87..807a3e3 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; @@ -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; } -- cgit v1.1 From 0f7e70e7da0a09d9d0a814f17272ea7da7855f64 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:20:49 -0700 Subject: mfd: intel-lpss: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Acked-by: Mika Westerberg Signed-off-by: Stephen Boyd Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 807a3e3..98e5980 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -338,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); -- cgit v1.1 From 36a0c08848285bb12ed8b83f5eec4a92a5efadf9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:19:20 -0700 Subject: mfd: intel_quark_i2c_gpio: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Acked-by: Andy Shevchenko Signed-off-by: Stephen Boyd Signed-off-by: Lee Jones --- drivers/mfd/intel_quark_i2c_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 24c2d29..ce17ae8 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -130,7 +130,7 @@ static int intel_quark_register_i2c_clk(struct device *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); -- cgit v1.1 From 38fc2eec95a750f2a69d82307ab721265e34939f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 20 Apr 2016 17:40:55 +0100 Subject: mfd: tps6105x: Remove linux/regulator/driver.h include This driver makes no use of linux/regulator/driver.h which should only be used by drivers implementing a regulator. Since it's unlikely to ever need anything from there remove the include. Signed-off-by: Mark Brown Signed-off-by: Lee Jones --- drivers/mfd/tps6105x.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index 51c5495..baa12ea 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include -- cgit v1.1 From 32852bcab29d8d43c5d4ddeed9937817e8e8c990 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 20 Apr 2016 11:16:38 -0400 Subject: mfd: twl6040: Check clk_prepare_enable() return value in twl6040_power() The clk_prepare_enable() function can fail so check the return value and propagate the error in case of a failure. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/twl6040.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 08a693c..85cc32a 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); -- cgit v1.1 From d6441dc5ce2bc8b296a65952d840d2f16e37f974 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 20 Apr 2016 11:16:37 -0400 Subject: mfd: twl6040: Disable and unprepare clk32k in twl6040_power() error path The clk32k clock is prepared and enabled in twl6040_power() but the clock is left enabled in case of an error while it should be disable/unprepared. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/twl6040.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 85cc32a..852d587 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -304,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; } @@ -311,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; } -- cgit v1.1 From 5eb519f3f6df367d43ec0c6e063fd62943fe4dcf Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 20 Apr 2016 13:45:46 -0400 Subject: mfd: Use IS_ENABLED(CONFIG_FOO) instead of checking FOO || FOO_MODULE The IS_ENABLED() macro checks if a Kconfig symbol has been enabled either built-in or as a module, use that macro instead of open coding the same. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/dm355evm_msp.c | 8 ++++---- drivers/mfd/wm8400-core.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index d7d59f8..14661ec 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 diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 8166776..8a98a2f 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -126,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) { @@ -165,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); @@ -177,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 } -- cgit v1.1 From 030ab2beb4cb045891395bb5e849cf583193b5fb Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 21 Apr 2016 17:45:39 +0530 Subject: mfd: smsc-ece1099: Remove unnecessarily remove callback SMSC MFD driver does not add any MFD child devices via mfd_add_devices() and hence it is not required to call mfd_remove_devices() to remove MFD child devices. Remove the call of the API mfd_remove_devices() which will result as remove of .remove callback for driver. Signed-off-by: Laxman Dewangan Signed-off-by: Sourav Poddar Signed-off-by: Lee Jones --- drivers/mfd/smsc-ece1099.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c index a4c0df7..7f89e89 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, }; -- cgit v1.1 From ae9810e275d5847ded7e1cbcf231c3fcf95b6e52 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 25 Apr 2016 13:06:32 -0400 Subject: mfd: twl4030-power: Remove driver path in file comment The driver's file path in the comment is wrong, so just remove it since these tends to get out of date and they serve very little purpose. Suggested-by: Lee Jones Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/twl4030-power.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 04b5398..1beb722 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 * -- cgit v1.1 From 0bbfb87c567d982fd698b41e9fb68478727460f9 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 21 Apr 2016 17:55:52 +0530 Subject: mfd: as3722: Use devm_mfd_add_devices and devm_regmap_add_irq_chip Use devm_mfd_add_devices() for adding MFD child devices and devm_regmap_add_irq_chip() for IRQ chip registration. This reduces the error code path and .remove callback for removing MFD child devices and deleting IRQ chip data. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/as3722.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c index e1f597f..f87342c 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, }; -- cgit v1.1 From 1a5422c9e56a20898a73da5726d935d5d8072f78 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 21 Apr 2016 17:55:54 +0530 Subject: mfd: max77686: Use devm_mfd_add_devices and devm_regmap_add_irq_chip Use devm_mfd_add_devices() for adding MFD child devices and devm_regmap_add_irq_chip() for IRQ chip registration. This reduces the error code path and .remove callback for removing MFD child devices and deleting IRQ chip data. Signed-off-by: Laxman Dewangan Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/max77686.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 7a0457e..7b68ed7 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -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,7 +303,6 @@ 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, }; -- cgit v1.1 From b36c82724fa10da7cc73693c6c2c3ab9a6c8034b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 21 Apr 2016 17:55:55 +0530 Subject: mfd: rc5t583: Use devm_mfd_add_devices and devm_request_threaded_irq Use devm_mfd_add_devices() for adding MFD child devices and devm_request_threaded_irq() for IRQ registration. This reduces the need of remove callback for removing MFD child devices and unregistering IRQ. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/rc5t583-irq.c | 11 ++--------- drivers/mfd/rc5t583.c | 24 +++--------------------- 2 files changed, 5 insertions(+), 30 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c index 3f8812d..f8dde59 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 fc2b2d9..d12243d 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, }; -- cgit v1.1 From 3dc6f4aaafbe9e745fd1183b7a7a91aeeae99fcd Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 21 Apr 2016 17:55:56 +0530 Subject: mfd: sec: Use devm_mfd_add_devices and devm_regmap_add_irq_chip Use devm_mfd_add_devices() for adding MFD child devices and devm_regmap_add_irq_chip() for IRQ chip registration. This reduces the error code path and .remove callback for removing MFD child devices and deleting IRQ chip data. Signed-off-by: Laxman Dewangan Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 20 +++----------------- drivers/mfd/sec-irq.c | 14 +++++--------- 2 files changed, 8 insertions(+), 26 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 400e1d7..ca6b80d 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 d77de43..5eb59c233d5 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); -} -- cgit v1.1 From 6167c5bcef722819ff536dc63ec89825001161ed Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 21 Apr 2016 17:55:57 +0530 Subject: mfd: tps65910: Use devm_mfd_add_devices and devm_regmap_add_irq_chip Use devm_mfd_add_devices() for adding MFD child devices and devm_regmap_add_irq_chip() for IRQ chip registration. This reduces the error code path and .remove callback for removing MFD child devices and deleting IRQ chip data. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/tps65910.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 8086e5d..11cab15 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); @@ -516,22 +510,12 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, 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); - - return 0; -} - static const struct i2c_device_id tps65910_i2c_id[] = { { "tps65910", TPS65910 }, { "tps65911", TPS65911 }, @@ -546,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, }; -- cgit v1.1 From 14856f75825f77b13564a8cc71deb21409671ab1 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 21 Apr 2016 17:55:58 +0530 Subject: mfd: wl1273-core: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/wl1273-core.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index f7c52d9..7080465 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) -- cgit v1.1 From 36e6d081cfb2cb64e6d8e5121cffb1e62f894d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Apr 2016 22:38:55 +0300 Subject: mfd: intel_soc_pmic_core: Terminate panel control GPIO lookup table correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPIO lookup tables are supposed to be zero terminated. Let's do that and avoid accidentally walking off the end. Cc: stable@vger.kernel.org Fixes: 61dd2ca2d44e ("mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal") Signed-off-by: Ville Syrjälä Acked-by: Linus Walleij Acked-by: Daniel Vetter Signed-off-by: Lee Jones --- drivers/mfd/intel_soc_pmic_core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index d9e15cf..12d6ebb4 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), + { }, }, }; -- cgit v1.1 From cd7cf27b8f49505e7419b48e8b51962663819922 Mon Sep 17 00:00:00 2001 From: Michael Haas Date: Fri, 6 May 2016 07:19:49 +0200 Subject: mfd: axp20x: Add a cell for the ac power_supply part of the axp20x PMICs As a counterpart to the usb power_supply cell, this commit adds an AC power_supply cell to the axp20x driver. Still missing are the RTC backup battery and the main battery charger cells. Signed-off-by: Michael Haas Acked-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 1ce9232..e4e3297 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -130,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", @@ -499,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), -- cgit v1.1 From 409b6246cd1c564ea377d5cbe8c6fd184e96119e Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 26 Apr 2016 17:06:19 +0100 Subject: mfd: wm5110: ARIZONA_CLOCK_CONTROL should be volatile Some of the bits in this register can be changed by the codec so we must mark it volatile. Signed-off-by: Richard Fitzgerald Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 8e74e71..1ee68bd 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: -- cgit v1.1 From b49b927f16acee626c56a1af4ab4cb062f75b5df Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 9 May 2016 11:28:37 +0300 Subject: mfd: omap-usb-tll: Fix scheduling while atomic BUG We shouldn't be calling clk_prepare_enable()/clk_prepare_disable() in an atomic context. Fixes the following issue: [ 5.830970] ehci-omap: OMAP-EHCI Host Controller driver [ 5.830974] driver_register 'ehci-omap' [ 5.895849] driver_register 'wl1271_sdio' [ 5.896870] BUG: scheduling while atomic: udevd/994/0x00000002 [ 5.896876] 4 locks held by udevd/994: [ 5.896904] #0: (&dev->mutex){......}, at: [] __driver_attach+0x60/0xac [ 5.896923] #1: (&dev->mutex){......}, at: [] __driver_attach+0x70/0xac [ 5.896946] #2: (tll_lock){+.+...}, at: [] omap_tll_enable+0x2c/0xd0 [ 5.896966] #3: (prepare_lock){+.+...}, at: [] clk_prepare_lock+0x48/0xe0 [ 5.897042] Modules linked in: wlcore_sdio(+) ehci_omap(+) dwc3_omap snd_soc_ts3a225e leds_is31fl319x bq27xxx_battery_i2c tsc2007 bq27xxx_battery bq2429x_charger ina2xx tca8418_keypad as5013 leds_tca6507 twl6040_vibra gpio_twl6040 bmp085_i2c(+) palmas_gpadc usb3503 palmas_pwrbutton bmg160_i2c(+) bmp085 bma150(+) bmg160_core bmp280 input_polldev snd_soc_omap_mcbsp snd_soc_omap_mcpdm snd_soc_omap snd_pcm_dmaengine [ 5.897048] Preemption disabled at:[< (null)>] (null) [ 5.897051] [ 5.897059] CPU: 0 PID: 994 Comm: udevd Not tainted 4.6.0-rc5-letux+ #233 [ 5.897062] Hardware name: Generic OMAP5 (Flattened Device Tree) [ 5.897076] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [ 5.897087] [] (show_stack) from [] (dump_stack+0x88/0xc0) [ 5.897099] [] (dump_stack) from [] (__schedule_bug+0xac/0xd0) [ 5.897111] [] (__schedule_bug) from [] (__schedule+0x88/0x7e4) [ 5.897120] [] (__schedule) from [] (schedule+0x9c/0xc0) [ 5.897129] [] (schedule) from [] (schedule_preempt_disabled+0x14/0x20) [ 5.897140] [] (schedule_preempt_disabled) from [] (mutex_lock_nested+0x258/0x43c) [ 5.897150] [] (mutex_lock_nested) from [] (clk_prepare_lock+0x48/0xe0) [ 5.897160] [] (clk_prepare_lock) from [] (clk_prepare+0x10/0x28) [ 5.897169] [] (clk_prepare) from [] (omap_tll_enable+0x64/0xd0) [ 5.897180] [] (omap_tll_enable) from [] (usbhs_runtime_resume+0x18/0x17c) [ 5.897192] [] (usbhs_runtime_resume) from [] (pm_generic_runtime_resume+0x2c/0x40) [ 5.897202] [] (pm_generic_runtime_resume) from [] (__rpm_callback+0x38/0x68) [ 5.897210] [] (__rpm_callback) from [] (rpm_callback+0x70/0x88) [ 5.897218] [] (rpm_callback) from [] (rpm_resume+0x4ec/0x7ec) [ 5.897227] [] (rpm_resume) from [] (__pm_runtime_resume+0x4c/0x64) [ 5.897236] [] (__pm_runtime_resume) from [] (driver_probe_device+0x30/0x70) [ 5.897246] [] (driver_probe_device) from [] (__driver_attach+0x88/0xac) [ 5.897256] [] (__driver_attach) from [] (bus_for_each_dev+0x50/0x84) [ 5.897267] [] (bus_for_each_dev) from [] (bus_add_driver+0xcc/0x1e4) [ 5.897276] [] (bus_add_driver) from [] (driver_register+0xac/0xf4) [ 5.897286] [] (driver_register) from [] (do_one_initcall+0x100/0x1b8) [ 5.897296] [] (do_one_initcall) from [] (do_init_module+0x58/0x1c0) [ 5.897304] [] (do_init_module) from [] (SyS_finit_module+0x88/0x90) [ 5.897313] [] (SyS_finit_module) from [] (ret_fast_syscall+0x0/0x1c) [ 5.912697] ------------[ cut here ]------------ [ 5.912711] WARNING: CPU: 0 PID: 994 at kernel/sched/core.c:2996 _raw_spin_unlock+0x28/0x58 [ 5.912717] DEBUG_LOCKS_WARN_ON(val > preempt_count()) Cc: Reported-by: H. Nikolaus Schaller Tested-by: H. Nikolaus Schaller Signed-off-by: Roger Quadros Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-tll.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index b7b3e8e..c30290f 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]); } } -- cgit v1.1 From 327156c593600e0f08575621c2a56f311d482e7a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 28 Apr 2016 15:28:56 +0530 Subject: mfd: max77620: Add core driver for MAX77620/MAX20024 MAX77620/MAX20024 are Power Management IC from the MAXIM. It supports RTC, multiple GPIOs, multiple DCDC and LDOs, watchdog, clock etc. Add MFD drier to provides common support for accessing the device; additional drivers is developed on respected subsystem in order to use the functionality of the device. Signed-off-by: Laxman Dewangan Signed-off-by: Mallikarjun Kasoju Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 15 ++ drivers/mfd/Makefile | 1 + drivers/mfd/max77620.c | 590 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 606 insertions(+) create mode 100644 drivers/mfd/max77620.c (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index cf7cbba..16d0bef 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -527,6 +527,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 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 5eaa6465d..921a08d 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 diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c new file mode 100644 index 0000000..199d261 --- /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 + * Chaitanya Bandi + * Mallikarjun Kasoju + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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 "); +MODULE_AUTHOR("Chaitanya Bandi "); +MODULE_AUTHOR("Mallikarjun Kasoju "); +MODULE_LICENSE("GPL v2"); -- cgit v1.1 From fcdad4210fc001b2d46f4bf97a2860792f4265f8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 27 Apr 2016 19:49:22 +0200 Subject: mfd: vexpress: Add !ARCH_USES_GETTIMEOFFSET dependency The MFD_VEXPRESS_SYSREG driver selects CLKSRC_MMIO, which in turn conflicts with ARCH_USES_GETTIMEOFFSET, causing a harmless Kconfig warning when it is set: warning: (ARCH_MVEBU && ARCH_DIGICOLOR && ARCH_GEMINI && ARCH_KEYSTONE && ARCH_MOXART && ARCH_MXS && PLAT_SPEAR && ARCH_SUNXI && ARCH_TEGRA && ARCH_U300 && PLAT_ORION && ARCH_CLPS711X && ARCH_EP93XX && ARCH_NETX && ARCH_IXP4XX && ARCH_KS8695 && ARCH_W90X900 && ARCH_PXA && ARCH_SA1100 && ARCH_OMAP1 && ARCH_BCM_IPROC && ARCH_INTEGRATOR_AP && ARCH_OMAP2PLUS && MFD_VEXPRESS_SYSREG) selects CLKSRC_MMIO which has unmet direct dependencies (!ARCH_USES_GETTIMEOFFSET) This was apparently hidden by the fact that no ARM platform that still sets ARCH_USES_GETTIMEOFFSET has gpiolib support, and we already have a dependency on GPIOLIB that I added a while ago. However, after 296ad4acb8ef ("gpio: remove deps on ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB"), any platform can enable CONFIG_GPIOLIB, and that lets us enable MFD_VEXPRESS_SYSREG as well. This adds an explicit dependency on !ARCH_USES_GETTIMEOFFSET to guarantee that we can enable the CLKSRC_MMIO driver without getting warnings. Signed-off-by: Arnd Bergmann Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 16d0bef..a49565c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1583,7 +1583,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 -- cgit v1.1 From 68b21094ef9ba3ef0dd8b1e24b03e00cd3b34e26 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 25 Apr 2016 22:42:25 +0100 Subject: mfd: ab8500-debugfs: Trivial fix of spelling mistake on "between" fix spelling mistake, beetween -> between Signed-off-by: Colin Ian King Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab8500-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 69d9fff..0aecd7b 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -2563,7 +2563,7 @@ static ssize_t ab8500_gpadc_trig_timer_write(struct file *file, if (user_trig_timer & ~0xFF) { dev_err(dev, - "debugfs error input: should be beetween 0 to 255\n"); + "debugfs error input: should be between 0 to 255\n"); return -EINVAL; } -- cgit v1.1 From b52207ef4ea56f8c22288ec3387399aac72c26cf Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Sun, 14 Feb 2016 14:29:21 +0800 Subject: mfd: hi655x: Add MFD driver for hi655x Add PMIC MFD driver to support hisilicon hi665x. Signed-off-by: Chen Feng Signed-off-by: Fei Wang Signed-off-by: Xinwei Kong Reviewed-by: Haojian Zhuang Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 10 +++ drivers/mfd/Makefile | 1 + drivers/mfd/hi655x-pmic.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 drivers/mfd/hi655x-pmic.c (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a49565c..1bcf601 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -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 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 921a08d..42a66e1 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -196,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/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c new file mode 100644 index 0000000..05ddc78 --- /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 + * Fei Wang + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 "); +MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.1