diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-01 11:28:14 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-01 11:28:14 (GMT) |
commit | 06e23d51151fd06c225c80ace26675532bdf406d (patch) | |
tree | 25d869bed6c4bdfd9addb799c72941e08c162ac2 /drivers/mfd | |
parent | dd9671172a06830071c8edb31fb2176f222a2c6e (diff) | |
parent | f37be01e6dc606f2fcc5e95c9933d948ce19bd35 (diff) | |
download | linux-06e23d51151fd06c225c80ace26675532bdf406d.tar.xz |
Merge tag 'mfd-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"Core Framework:
- New API to call bespoke pre/post IRQ handlers; Regmap
New Device Support:
- Add support for RN5T567 to rn5t618
- Add support for COMe-cSL6 and COMe-mAL10 to kempld-core
New Functionality:
- Add support for USB Power Supply to axp20x
- Add support for Power Key to hi655x-pmic
Fix-ups:
- Update MAINTAINERS; Dialog, Altera
- Remove module support; max77843, max77620, max8998, max8997, max8925-i2c
- Add module support; max14577
- Constifying; max77620
- Allow bespoke IRQ masking/unmasking; max77620
- Remove superfluous code; arizona, qcom_rpm, smsc-ece1099
- Power Management fixups; arizona-core
- Error-path improvement; twl-core, dm355evm_msp, smsc-ece1099, hi655x
- Clocking fixups; twl6040
- Trivial (spelling, headers, coding-style, whitespace, (re)naming);
si476x-i2c, omap-usb-tll, ti_am335x_tscadc, tps6507, hi655x-pmic
Bug Fixes:
- Fix offset error for MSM8660; qcom_rpm
- Fix possible spurious IRQs; arizona, hi655x-pmic"
* tag 'mfd-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (42 commits)
mfd: qcom_rpm: Parametrize also ack selector size
mfd: twl6040: Handle mclk used for HPPLL and optional internal clock source
mfd: Add support for COMe-cSL6 and COMe-mAL10 to Kontron PLD driver
mfd: hi655x: Fix return value check in hi655x_pmic_probe()
mfd: smsc-ece1099: Return directly after a function failure in smsc_i2c_probe()
mfd: smsc-ece1099: Delete an unnecessary variable initialisation in smsc_i2c_probe()
mfd: dm355evm_msp: Return directly after a failed platform_device_alloc() in add_child()
mfd: twl-core: Refactoring for add_numbered_child()
mfd: twl-core: Return directly after a failed platform_device_alloc() in add_numbered_child()
mfd: arizona: Add missing disable of PM runtime on probe error path
mfd: stmpe: Move platform data into MFD driver
mfd: max14577: Allow driver to be built as a module
mfd: max14577: Use module_init() instead of subsys_initcall()
mfd: arizona: Remove some duplicate defines
mfd: qcom_rpm: Remove unused define
mfd: hi655x-pmic: Add powerkey device to hi655x PMIC driver
mfd: hi655x-pmic: Rename some interrupt macro names
mfd: hi655x-pmic: Fixup issue with un-acked interrupts
mfd: arizona: Check if AOD interrupts are pending before dispatching
mfd: qcom_rpm: Fix offset error for msm8660
...
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 17 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 2 | ||||
-rw-r--r-- | drivers/mfd/altera-a10sr.c | 169 | ||||
-rw-r--r-- | drivers/mfd/arizona-core.c | 4 | ||||
-rw-r--r-- | drivers/mfd/arizona-irq.c | 16 | ||||
-rw-r--r-- | drivers/mfd/axp20x.c | 17 | ||||
-rw-r--r-- | drivers/mfd/dm355evm_msp.c | 7 | ||||
-rw-r--r-- | drivers/mfd/hi655x-pmic.c | 59 | ||||
-rw-r--r-- | drivers/mfd/kempld-core.c | 16 | ||||
-rw-r--r-- | drivers/mfd/max14577.c | 2 | ||||
-rw-r--r-- | drivers/mfd/max77620.c | 75 | ||||
-rw-r--r-- | drivers/mfd/max77843.c | 24 | ||||
-rw-r--r-- | drivers/mfd/max8925-i2c.c | 14 | ||||
-rw-r--r-- | drivers/mfd/max8997.c | 30 | ||||
-rw-r--r-- | drivers/mfd/max8998.c | 27 | ||||
-rw-r--r-- | drivers/mfd/omap-usb-tll.c | 2 | ||||
-rw-r--r-- | drivers/mfd/qcom_rpm.c | 57 | ||||
-rw-r--r-- | drivers/mfd/si476x-i2c.c | 2 | ||||
-rw-r--r-- | drivers/mfd/smsc-ece1099.c | 11 | ||||
-rw-r--r-- | drivers/mfd/stmpe.c | 40 | ||||
-rw-r--r-- | drivers/mfd/ti_am335x_tscadc.c | 135 | ||||
-rw-r--r-- | drivers/mfd/tps6507x.c | 4 | ||||
-rw-r--r-- | drivers/mfd/twl-core.c | 28 | ||||
-rw-r--r-- | drivers/mfd/twl6040.c | 41 |
24 files changed, 515 insertions, 284 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ff031a7..2d1fb64 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -18,6 +18,17 @@ config MFD_CS5535 This is the core driver for CS5535/CS5536 MFD functions. This is necessary for using the board's GPIO and MFGPT functionality. +config MFD_ALTERA_A10SR + bool "Altera Arria10 DevKit System Resource chip" + depends on ARCH_SOCFPGA && SPI_MASTER=y && OF + select REGMAP_SPI + select MFD_CORE + help + Support for the Altera Arria10 DevKit MAX5 System Resource chip + using the SPI interface. This driver provides common support for + accessing the external gpio extender (LEDs & buttons) and + power supply alarms (hwmon). + config MFD_ACT8945A tristate "Active-semi ACT8945A" select MFD_CORE @@ -480,6 +491,8 @@ config MFD_KEMPLD * COMe-cDC2 (microETXexpress-DC) * COMe-cHL6 * COMe-cPC2 (microETXexpress-PC) + * COMe-cSL6 + * COMe-mAL10 * COMe-mBT10 * COMe-mCT10 * COMe-mTT10 (nanoETXexpress-TT) @@ -524,8 +537,8 @@ config MFD_88PM860X battery-charger under the corresponding menus. config MFD_MAX14577 - bool "Maxim Semiconductor MAX14577/77836 MUIC + Charger Support" - depends on I2C=y + tristate "Maxim Semiconductor MAX14577/77836 MUIC + Charger Support" + depends on I2C select MFD_CORE select REGMAP_I2C select REGMAP_IRQ diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 42a66e1..2ba3ba3 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -205,3 +205,5 @@ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o + +obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o diff --git a/drivers/mfd/altera-a10sr.c b/drivers/mfd/altera-a10sr.c new file mode 100644 index 0000000..c05aa4f --- /dev/null +++ b/drivers/mfd/altera-a10sr.c @@ -0,0 +1,169 @@ +/* + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPI access for Altera Arria10 MAX5 System Resource Chip + * + * Adapted from DA9052 + */ + +#include <linux/mfd/altera-a10sr.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/spi/spi.h> + +static const struct mfd_cell altr_a10sr_subdev_info[] = { + { + .name = "altr_a10sr_gpio", + .of_compatible = "altr,a10sr-gpio", + }, +}; + +static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_VERSION_READ: + case ALTR_A10SR_LED_REG: + case ALTR_A10SR_PBDSW_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_PWR_GOOD1_REG: + case ALTR_A10SR_PWR_GOOD2_REG: + case ALTR_A10SR_PWR_GOOD3_REG: + case ALTR_A10SR_FMCAB_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_USB_QSPI_REG: + case ALTR_A10SR_SFPA_REG: + case ALTR_A10SR_SFPB_REG: + case ALTR_A10SR_I2C_M_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +static bool altr_a10sr_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_LED_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_FMCAB_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_USB_QSPI_REG: + case ALTR_A10SR_SFPA_REG: + case ALTR_A10SR_SFPB_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_PBDSW_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_PWR_GOOD1_REG: + case ALTR_A10SR_PWR_GOOD2_REG: + case ALTR_A10SR_PWR_GOOD3_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_I2C_M_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +const struct regmap_config altr_a10sr_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .cache_type = REGCACHE_NONE, + + .use_single_rw = true, + .read_flag_mask = 1, + .write_flag_mask = 0, + + .max_register = ALTR_A10SR_WR_KEY_REG, + .readable_reg = altr_a10sr_reg_readable, + .writeable_reg = altr_a10sr_reg_writeable, + .volatile_reg = altr_a10sr_reg_volatile, + +}; + +static int altr_a10sr_spi_probe(struct spi_device *spi) +{ + int ret; + struct altr_a10sr *a10sr; + + a10sr = devm_kzalloc(&spi->dev, sizeof(*a10sr), + GFP_KERNEL); + if (!a10sr) + return -ENOMEM; + + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + + a10sr->dev = &spi->dev; + + spi_set_drvdata(spi, a10sr); + + a10sr->regmap = devm_regmap_init_spi(spi, &altr_a10sr_regmap_config); + if (IS_ERR(a10sr->regmap)) { + ret = PTR_ERR(a10sr->regmap); + dev_err(&spi->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = devm_mfd_add_devices(a10sr->dev, PLATFORM_DEVID_AUTO, + altr_a10sr_subdev_info, + ARRAY_SIZE(altr_a10sr_subdev_info), + NULL, 0, NULL); + if (ret) + dev_err(a10sr->dev, "Failed to register sub-devices: %d\n", + ret); + + return ret; +} + +static const struct of_device_id altr_a10sr_spi_of_match[] = { + { .compatible = "altr,a10sr" }, + { }, +}; +MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match); + +static struct spi_driver altr_a10sr_spi_driver = { + .probe = altr_a10sr_spi_probe, + .driver = { + .name = "altr_a10sr", + .of_match_table = of_match_ptr(altr_a10sr_spi_of_match), + }, +}; + +module_spi_driver(altr_a10sr_spi_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>"); +MODULE_DESCRIPTION("Altera Arria10 DevKit System Resource MFD Driver"); diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index bf27179..e4f97b3 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1462,7 +1462,7 @@ int arizona_dev_init(struct arizona *arizona) /* Set up for interrupts */ ret = arizona_irq_init(arizona); if (ret != 0) - goto err_reset; + goto err_pm; pm_runtime_set_autosuspend_delay(arizona->dev, 100); pm_runtime_use_autosuspend(arizona->dev); @@ -1486,6 +1486,8 @@ int arizona_dev_init(struct arizona *arizona) err_irq: arizona_irq_exit(arizona); +err_pm: + pm_runtime_disable(arizona->dev); err_reset: arizona_enable_reset(arizona); regulator_disable(arizona->dcvdd); diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index edeb495..5e18d3c 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -109,8 +109,20 @@ static irqreturn_t arizona_irq_thread(int irq, void *data) do { poll = false; - if (arizona->aod_irq_chip) - handle_nested_irq(irq_find_mapping(arizona->virq, 0)); + if (arizona->aod_irq_chip) { + /* + * Check the AOD status register to determine whether + * the nested IRQ handler should be called. + */ + ret = regmap_read(arizona->regmap, + ARIZONA_AOD_IRQ1, &val); + if (ret) + dev_warn(arizona->dev, + "Failed to read AOD IRQ1 %d\n", ret); + else if (val) + handle_nested_irq( + irq_find_mapping(arizona->virq, 0)); + } /* * Check if one of the main interrupts is asserted and only diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index e4e3297..fd80b09 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -17,6 +17,7 @@ */ #include <linux/err.h> +#include <linux/delay.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> @@ -93,7 +94,10 @@ static const struct regmap_range axp22x_writeable_ranges[] = { }; static const struct regmap_range axp22x_volatile_ranges[] = { + regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE), regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE), + regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE), + regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES), }; static const struct regmap_access_table axp22x_writeable_table = { @@ -157,6 +161,11 @@ static struct resource axp20x_usb_power_supply_resources[] = { DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), }; +static struct resource axp22x_usb_power_supply_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), +}; + static struct resource axp22x_pek_resources[] = { { .name = "PEK_DBR", @@ -524,6 +533,11 @@ static struct mfd_cell axp22x_cells[] = { .resources = axp22x_pek_resources, }, { .name = "axp20x-regulator", + }, { + .name = "axp20x-usb-power-supply", + .of_compatible = "x-powers,axp221-usb-power-supply", + .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources), + .resources = axp22x_usb_power_supply_resources, }, }; @@ -664,6 +678,9 @@ static void axp20x_power_off(void) regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, AXP20X_OFF); + + /* Give capacitors etc. time to drain to avoid kernel panic msg. */ + msleep(500); } int axp20x_match_device(struct axp20x_dev *axp20x) diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 14661ec..270e19c 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -199,11 +199,8 @@ static struct device *add_child(struct i2c_client *client, const char *name, int status; pdev = platform_device_alloc(name, -1); - if (!pdev) { - dev_dbg(&client->dev, "can't alloc dev\n"); - status = -ENOMEM; - goto err; - } + if (!pdev) + return ERR_PTR(-ENOMEM); device_init_wakeup(&pdev->dev, can_wakeup); pdev->dev.parent = &client->dev; diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index 05ddc78..0fc6299 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -24,19 +24,15 @@ #include <linux/platform_device.h> #include <linux/regmap.h> -static const struct mfd_cell hi655x_pmic_devs[] = { - { .name = "hi655x-regulator", }, -}; - static const struct regmap_irq hi655x_irqs[] = { - { .reg_offset = 0, .mask = OTMP_D1R_INT }, - { .reg_offset = 0, .mask = VSYS_2P5_R_INT }, - { .reg_offset = 0, .mask = VSYS_UV_D3R_INT }, - { .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT }, - { .reg_offset = 0, .mask = PWRON_D4SR_INT }, - { .reg_offset = 0, .mask = PWRON_D20F_INT }, - { .reg_offset = 0, .mask = PWRON_D20R_INT }, - { .reg_offset = 0, .mask = RESERVE_INT }, + { .reg_offset = 0, .mask = OTMP_D1R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_2P5_R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_UV_D3R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D4SR_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D20F_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D20R_INT_MASK }, + { .reg_offset = 0, .mask = RESERVE_INT_MASK }, }; static const struct regmap_irq_chip hi655x_irq_chip = { @@ -45,6 +41,7 @@ static const struct regmap_irq_chip hi655x_irq_chip = { .num_regs = 1, .num_irqs = ARRAY_SIZE(hi655x_irqs), .status_base = HI655X_IRQ_STAT_BASE, + .ack_base = HI655X_IRQ_STAT_BASE, .mask_base = HI655X_IRQ_MASK_BASE, }; @@ -55,6 +52,34 @@ static struct regmap_config hi655x_regmap_config = { .max_register = HI655X_BUS_ADDR(0xFFF), }; +static struct resource pwrkey_resources[] = { + { + .name = "down", + .start = PWRON_D20R_INT, + .end = PWRON_D20R_INT, + .flags = IORESOURCE_IRQ, + }, { + .name = "up", + .start = PWRON_D20F_INT, + .end = PWRON_D20F_INT, + .flags = IORESOURCE_IRQ, + }, { + .name = "hold 4s", + .start = PWRON_D4SR_INT, + .end = PWRON_D4SR_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static const struct mfd_cell hi655x_pmic_devs[] = { + { + .name = "hi65xx-powerkey", + .num_resources = ARRAY_SIZE(pwrkey_resources), + .resources = &pwrkey_resources[0], + }, + { .name = "hi655x-regulator", }, +}; + static void hi655x_local_irq_clear(struct regmap *map) { int i; @@ -80,12 +105,9 @@ static int hi655x_pmic_probe(struct platform_device *pdev) 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; + if (IS_ERR(base)) + return PTR_ERR(base); pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base, &hi655x_regmap_config); @@ -123,7 +145,8 @@ static int hi655x_pmic_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmic); ret = mfd_add_devices(dev, PLATFORM_DEVID_AUTO, hi655x_pmic_devs, - ARRAY_SIZE(hi655x_pmic_devs), NULL, 0, NULL); + ARRAY_SIZE(hi655x_pmic_devs), NULL, 0, + regmap_irq_get_domain(pmic->irq_data)); if (ret) { dev_err(dev, "Failed to register device %d\n", ret); regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data); diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c index 05b9245..da5722d 100644 --- a/drivers/mfd/kempld-core.c +++ b/drivers/mfd/kempld-core.c @@ -624,6 +624,14 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = { .driver_data = (void *)&kempld_platform_data_generic, .callback = kempld_create_platform_device, }, { + .ident = "CSL6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-cSL6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { .ident = "CVV6", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), @@ -647,6 +655,14 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = { .driver_data = (void *)&kempld_platform_data_generic, .callback = kempld_create_platform_device, }, { + .ident = "MAL1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-mAL10"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { .ident = "MBR1", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 2280b3f..6c24512 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -561,7 +561,7 @@ static int __init max14577_i2c_init(void) return i2c_add_driver(&max14577_i2c_driver); } -subsys_initcall(max14577_i2c_init); +module_init(max14577_i2c_init); static void __exit max14577_i2c_exit(void) { diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index f32fbb8..258757e 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -31,25 +31,25 @@ #include <linux/interrupt.h> #include <linux/mfd/core.h> #include <linux/mfd/max77620.h> -#include <linux/module.h> +#include <linux/init.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/regmap.h> #include <linux/slab.h> -static struct resource gpio_resources[] = { +static const struct resource gpio_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO), }; -static struct resource power_resources[] = { +static const struct resource power_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_LBT_MBATLOW), }; -static struct resource rtc_resources[] = { +static const struct resource rtc_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_TOP_RTC), }; -static struct resource thermal_resources[] = { +static const struct resource thermal_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM1), DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM2), }; @@ -111,15 +111,6 @@ static const struct mfd_cell max20024_children[] = { }, }; -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), }; @@ -180,6 +171,51 @@ static const struct regmap_config max20024_regmap_config = { .volatile_table = &max77620_volatile_table, }; +/* + * MAX77620 and MAX20024 has the following steps of the interrupt handling + * for TOP interrupts: + * 1. When interrupt occurs from PMIC, mask the PMIC interrupt by setting GLBLM. + * 2. Read IRQTOP and service the interrupt. + * 3. Once all interrupts has been checked and serviced, the interrupt service + * routine un-masks the hardware interrupt line by clearing GLBLM. + */ +static int max77620_irq_global_mask(void *irq_drv_data) +{ + struct max77620_chip *chip = irq_drv_data; + int ret; + + ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT, + MAX77620_GLBLM_MASK, MAX77620_GLBLM_MASK); + if (ret < 0) + dev_err(chip->dev, "Failed to set GLBLM: %d\n", ret); + + return ret; +} + +static int max77620_irq_global_unmask(void *irq_drv_data) +{ + struct max77620_chip *chip = irq_drv_data; + int ret; + + ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT, + MAX77620_GLBLM_MASK, 0); + if (ret < 0) + dev_err(chip->dev, "Failed to reset GLBLM: %d\n", ret); + + return ret; +} + +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, + .handle_pre_irq = max77620_irq_global_mask, + .handle_post_irq = max77620_irq_global_unmask, +}; + /* 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 @@ -433,6 +469,7 @@ static int max77620_probe(struct i2c_client *client, if (ret < 0) return ret; + max77620_top_irq_chip.irq_drv_data = chip; ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, IRQF_ONESHOT | IRQF_SHARED, chip->irq_base, &max77620_top_irq_chip, @@ -568,7 +605,6 @@ static const struct i2c_device_id max77620_id[] = { {"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) @@ -582,11 +618,4 @@ static struct i2c_driver max77620_driver = { .probe = max77620_probe, .id_table = max77620_id, }; - -module_i2c_driver(max77620_driver); - -MODULE_DESCRIPTION("MAX77620/MAX20024 Multi Function Device Core Driver"); -MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); -MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>"); -MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>"); -MODULE_LICENSE("GPL v2"); +builtin_i2c_driver(max77620_driver); diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c index 7cfc95b..dc5caea 100644 --- a/drivers/mfd/max77843.c +++ b/drivers/mfd/max77843.c @@ -15,7 +15,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/module.h> +#include <linux/init.h> #include <linux/mfd/core.h> #include <linux/mfd/max77693-common.h> #include <linux/mfd/max77843-private.h> @@ -171,19 +171,6 @@ err_pmic_id: return ret; } -static int max77843_remove(struct i2c_client *i2c) -{ - struct max77693_dev *max77843 = i2c_get_clientdata(i2c); - - mfd_remove_devices(max77843->dev); - - regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys); - - i2c_unregister_device(max77843->i2c_chg); - - return 0; -} - static const struct of_device_id max77843_dt_match[] = { { .compatible = "maxim,max77843", }, { }, @@ -193,7 +180,6 @@ static const struct i2c_device_id max77843_id[] = { { "max77843", TYPE_MAX77843, }, { }, }; -MODULE_DEVICE_TABLE(i2c, max77843_id); static int __maybe_unused max77843_suspend(struct device *dev) { @@ -226,9 +212,9 @@ static struct i2c_driver max77843_i2c_driver = { .name = "max77843", .pm = &max77843_pm, .of_match_table = max77843_dt_match, + .suppress_bind_attrs = true, }, .probe = max77843_probe, - .remove = max77843_remove, .id_table = max77843_id, }; @@ -237,9 +223,3 @@ static int __init max77843_i2c_init(void) return i2c_add_driver(&max77843_i2c_driver); } subsys_initcall(max77843_i2c_init); - -static void __exit max77843_i2c_exit(void) -{ - i2c_del_driver(&max77843_i2c_driver); -} -module_exit(max77843_i2c_exit); diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index 70443b1..5c80aea 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -9,7 +9,7 @@ * published by the Free Software Foundation. */ #include <linux/kernel.h> -#include <linux/module.h> +#include <linux/init.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/mfd/max8925.h> @@ -133,7 +133,6 @@ static const struct i2c_device_id max8925_id_table[] = { { "max8925", 0 }, { }, }; -MODULE_DEVICE_TABLE(i2c, max8925_id_table); static int max8925_dt_init(struct device_node *np, struct device *dev, struct max8925_platform_data *pdata) @@ -240,7 +239,6 @@ static const struct of_device_id max8925_dt_ids[] = { { .compatible = "maxim,max8925", }, {}, }; -MODULE_DEVICE_TABLE(of, max8925_dt_ids); static struct i2c_driver max8925_driver = { .driver = { @@ -264,13 +262,3 @@ static int __init max8925_i2c_init(void) return ret; } subsys_initcall(max8925_i2c_init); - -static void __exit max8925_i2c_exit(void) -{ - i2c_del_driver(&max8925_driver); -} -module_exit(max8925_i2c_exit); - -MODULE_DESCRIPTION("I2C Driver for Maxim 8925"); -MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index f316348..2d6e2c3 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -2,7 +2,7 @@ * max8997.c - mfd core driver for the Maxim 8966 and 8997 * * Copyright (C) 2011 Samsung Electronics - * MyungJoo Ham <myungjoo.ham@smasung.com> + * MyungJoo Ham <myungjoo.ham@samsung.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ #include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/pm_runtime.h> -#include <linux/module.h> +#include <linux/init.h> #include <linux/mutex.h> #include <linux/mfd/core.h> #include <linux/mfd/max8997.h> @@ -55,7 +55,6 @@ static const struct of_device_id max8997_pmic_dt_match[] = { { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 }, {}, }; -MODULE_DEVICE_TABLE(of, max8997_pmic_dt_match); #endif int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) @@ -263,24 +262,11 @@ err_i2c_haptic: return ret; } -static int max8997_i2c_remove(struct i2c_client *i2c) -{ - struct max8997_dev *max8997 = i2c_get_clientdata(i2c); - - mfd_remove_devices(max8997->dev); - i2c_unregister_device(max8997->muic); - i2c_unregister_device(max8997->haptic); - i2c_unregister_device(max8997->rtc); - - return 0; -} - static const struct i2c_device_id max8997_i2c_id[] = { { "max8997", TYPE_MAX8997 }, { "max8966", TYPE_MAX8966 }, { } }; -MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); static u8 max8997_dumpaddr_pmic[] = { MAX8997_REG_INT1MSK, @@ -510,10 +496,10 @@ static struct i2c_driver max8997_i2c_driver = { .driver = { .name = "max8997", .pm = &max8997_pm, + .suppress_bind_attrs = true, .of_match_table = of_match_ptr(max8997_pmic_dt_match), }, .probe = max8997_i2c_probe, - .remove = max8997_i2c_remove, .id_table = max8997_i2c_id, }; @@ -523,13 +509,3 @@ static int __init max8997_i2c_init(void) } /* init early so consumer devices can complete system boot */ subsys_initcall(max8997_i2c_init); - -static void __exit max8997_i2c_exit(void) -{ - i2c_del_driver(&max8997_i2c_driver); -} -module_exit(max8997_i2c_exit); - -MODULE_DESCRIPTION("MAXIM 8997 multi-function core driver"); -MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index ab28b29..4c33b80 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -21,8 +21,6 @@ */ #include <linux/err.h> -#include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/i2c.h> @@ -138,7 +136,6 @@ static const struct of_device_id max8998_dt_match[] = { { .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 }, {}, }; -MODULE_DEVICE_TABLE(of, max8998_dt_match); #endif /* @@ -254,23 +251,11 @@ err: return ret; } -static int max8998_i2c_remove(struct i2c_client *i2c) -{ - struct max8998_dev *max8998 = i2c_get_clientdata(i2c); - - mfd_remove_devices(max8998->dev); - max8998_irq_exit(max8998); - i2c_unregister_device(max8998->rtc); - - return 0; -} - static const struct i2c_device_id max8998_i2c_id[] = { { "max8998", TYPE_MAX8998 }, { "lp3974", TYPE_LP3974}, { } }; -MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); static int max8998_suspend(struct device *dev) { @@ -378,10 +363,10 @@ static struct i2c_driver max8998_i2c_driver = { .driver = { .name = "max8998", .pm = &max8998_pm, + .suppress_bind_attrs = true, .of_match_table = of_match_ptr(max8998_dt_match), }, .probe = max8998_i2c_probe, - .remove = max8998_i2c_remove, .id_table = max8998_i2c_id, }; @@ -391,13 +376,3 @@ static int __init max8998_i2c_init(void) } /* init early so consumer devices can complete system boot */ subsys_initcall(max8998_i2c_init); - -static void __exit max8998_i2c_exit(void) -{ - i2c_del_driver(&max8998_i2c_driver); -} -module_exit(max8998_i2c_exit); - -MODULE_DESCRIPTION("MAXIM 8998 multi-function core driver"); -MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index c30290f..1aa74c4 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -30,6 +30,8 @@ #include <linux/platform_data/usb-omap.h> #include <linux/of.h> +#include "omap-usb.h" + #define USBTLL_DRIVER_NAME "usbhs_tll" /* TLL Register Set */ diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 1be47ad..2e44323 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c @@ -34,7 +34,13 @@ struct qcom_rpm_resource { struct qcom_rpm_data { u32 version; const struct qcom_rpm_resource *resource_table; - unsigned n_resources; + unsigned int n_resources; + unsigned int req_ctx_off; + unsigned int req_sel_off; + unsigned int ack_ctx_off; + unsigned int ack_sel_off; + unsigned int req_sel_size; + unsigned int ack_sel_size; }; struct qcom_rpm { @@ -61,17 +67,11 @@ struct qcom_rpm { #define RPM_REQUEST_TIMEOUT (5 * HZ) -#define RPM_REQUEST_CONTEXT 3 -#define RPM_REQ_SELECT 11 -#define RPM_ACK_CONTEXT 15 -#define RPM_ACK_SELECTOR 23 -#define RPM_SELECT_SIZE 7 +#define RPM_MAX_SEL_SIZE 7 #define RPM_NOTIFICATION BIT(30) #define RPM_REJECTED BIT(31) -#define RPM_SIGNAL BIT(2) - static const struct qcom_rpm_resource apq8064_rpm_resource_table[] = { [QCOM_RPM_CXO_CLK] = { 25, 9, 5, 1 }, [QCOM_RPM_PXO_CLK] = { 26, 10, 6, 1 }, @@ -157,6 +157,12 @@ static const struct qcom_rpm_data apq8064_template = { .version = 3, .resource_table = apq8064_rpm_resource_table, .n_resources = ARRAY_SIZE(apq8064_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 15, + .ack_sel_off = 23, + .req_sel_size = 4, + .ack_sel_size = 7, }; static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = { @@ -240,6 +246,12 @@ static const struct qcom_rpm_data msm8660_template = { .version = 2, .resource_table = msm8660_rpm_resource_table, .n_resources = ARRAY_SIZE(msm8660_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 19, + .ack_sel_off = 27, + .req_sel_size = 7, + .ack_sel_size = 7, }; static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = { @@ -322,6 +334,12 @@ static const struct qcom_rpm_data msm8960_template = { .version = 3, .resource_table = msm8960_rpm_resource_table, .n_resources = ARRAY_SIZE(msm8960_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 15, + .ack_sel_off = 23, + .req_sel_size = 4, + .ack_sel_size = 7, }; static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = { @@ -362,6 +380,12 @@ static const struct qcom_rpm_data ipq806x_template = { .version = 3, .resource_table = ipq806x_rpm_resource_table, .n_resources = ARRAY_SIZE(ipq806x_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 15, + .ack_sel_off = 23, + .req_sel_size = 4, + .ack_sel_size = 7, }; static const struct of_device_id qcom_rpm_of_match[] = { @@ -380,7 +404,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, { const struct qcom_rpm_resource *res; const struct qcom_rpm_data *data = rpm->data; - u32 sel_mask[RPM_SELECT_SIZE] = { 0 }; + u32 sel_mask[RPM_MAX_SEL_SIZE] = { 0 }; int left; int ret = 0; int i; @@ -398,12 +422,12 @@ int qcom_rpm_write(struct qcom_rpm *rpm, writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i)); bitmap_set((unsigned long *)sel_mask, res->select_id, 1); - for (i = 0; i < ARRAY_SIZE(sel_mask); i++) { + for (i = 0; i < rpm->data->req_sel_size; i++) { writel_relaxed(sel_mask[i], - RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i)); + RPM_CTRL_REG(rpm, rpm->data->req_sel_off + i)); } - writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT)); + writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, rpm->data->req_ctx_off)); reinit_completion(&rpm->ack); regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit)); @@ -426,10 +450,11 @@ static irqreturn_t qcom_rpm_ack_interrupt(int irq, void *dev) u32 ack; int i; - ack = readl_relaxed(RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT)); - for (i = 0; i < RPM_SELECT_SIZE; i++) - writel_relaxed(0, RPM_CTRL_REG(rpm, RPM_ACK_SELECTOR + i)); - writel(0, RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT)); + ack = readl_relaxed(RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); + for (i = 0; i < rpm->data->ack_sel_size; i++) + writel_relaxed(0, + RPM_CTRL_REG(rpm, rpm->data->ack_sel_off + i)); + writel(0, RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); if (ack & RPM_NOTIFICATION) { dev_warn(rpm->dev, "ignoring notification!\n"); diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index fb4ce6d0..c180b75 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -600,7 +600,7 @@ static int si476x_core_fwver_to_revision(struct si476x_core *core, unknown_revision: dev_err(&core->client->dev, "Unsupported version of the firmware: %d.%d.%d, " - "reverting to A10 comptible functions\n", + "reverting to A10 compatible functions\n", major, minor1, minor2); return SI476X_REVISION_A10; diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c index 7f89e89..cd18c09 100644 --- a/drivers/mfd/smsc-ece1099.c +++ b/drivers/mfd/smsc-ece1099.c @@ -36,7 +36,7 @@ static int smsc_i2c_probe(struct i2c_client *i2c, { struct smsc *smsc; int devid, rev, venid_l, venid_h; - int ret = 0; + int ret; smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc), GFP_KERNEL); @@ -46,10 +46,8 @@ static int smsc_i2c_probe(struct i2c_client *i2c, } smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config); - if (IS_ERR(smsc->regmap)) { - ret = PTR_ERR(smsc->regmap); - goto err; - } + if (IS_ERR(smsc->regmap)) + return PTR_ERR(smsc->regmap); i2c_set_clientdata(i2c, smsc); smsc->dev = &i2c->dev; @@ -68,7 +66,7 @@ static int smsc_i2c_probe(struct i2c_client *i2c, ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk); if (ret) - goto err; + return ret; #ifdef CONFIG_OF if (i2c->dev.of_node) @@ -76,7 +74,6 @@ static int smsc_i2c_probe(struct i2c_client *i2c, NULL, NULL, &i2c->dev); #endif -err: return ret; } diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index fb8f9e8..94c7cc0 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -23,6 +23,27 @@ #include <linux/regulator/consumer.h> #include "stmpe.h" +/** + * struct stmpe_platform_data - STMPE platform data + * @id: device id to distinguish between multiple STMPEs on the same board + * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) + * @irq_trigger: IRQ trigger to use for the interrupt to the host + * @autosleep: bool to enable/disable stmpe autosleep + * @autosleep_timeout: inactivity timeout in milliseconds for autosleep + * @irq_over_gpio: true if gpio is used to get irq + * @irq_gpio: gpio number over which irq will be requested (significant only if + * irq_over_gpio is true) + */ +struct stmpe_platform_data { + int id; + unsigned int blocks; + unsigned int irq_trigger; + bool autosleep; + bool irq_over_gpio; + int irq_gpio; + int autosleep_timeout; +}; + static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) { return stmpe->variant->enable(stmpe, blocks, true); @@ -1187,24 +1208,19 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata, /* Called from client specific probe routines */ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) { - struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev); + struct stmpe_platform_data *pdata; struct device_node *np = ci->dev->of_node; struct stmpe *stmpe; int ret; - if (!pdata) { - if (!np) - return -EINVAL; - - pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; + pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; - stmpe_of_probe(pdata, np); + stmpe_of_probe(pdata, np); - if (of_find_property(np, "interrupts", NULL) == NULL) - ci->irq = -1; - } + if (of_find_property(np, "interrupts", NULL) == NULL) + ci->irq = -1; stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL); if (!stmpe) diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e4e4b22..c8f027b 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -27,20 +27,6 @@ #include <linux/mfd/ti_am335x_tscadc.h> -static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg) -{ - unsigned int val; - - regmap_read(tsadc->regmap_tscadc, reg, &val); - return val; -} - -static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg, - unsigned int val) -{ - regmap_write(tsadc->regmap_tscadc, reg, val); -} - static const struct regmap_config tscadc_regmap_config = { .name = "ti_tscadc", .reg_bits = 32, @@ -48,89 +34,89 @@ static const struct regmap_config tscadc_regmap_config = { .val_bits = 32, }; -void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) +void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tscadc, u32 val) { unsigned long flags; - spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->reg_se_cache |= val; - if (tsadc->adc_waiting) - wake_up(&tsadc->reg_se_wait); - else if (!tsadc->adc_in_use) - tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); + spin_lock_irqsave(&tscadc->reg_lock, flags); + tscadc->reg_se_cache |= val; + if (tscadc->adc_waiting) + wake_up(&tscadc->reg_se_wait); + else if (!tscadc->adc_in_use) + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); - spin_unlock_irqrestore(&tsadc->reg_lock, flags); + spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache); -static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) +static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tscadc) { DEFINE_WAIT(wait); u32 reg; - reg = tscadc_readl(tsadc, REG_ADCFSM); + regmap_read(tscadc->regmap, REG_ADCFSM, ®); if (reg & SEQ_STATUS) { - tsadc->adc_waiting = true; - prepare_to_wait(&tsadc->reg_se_wait, &wait, + tscadc->adc_waiting = true; + prepare_to_wait(&tscadc->reg_se_wait, &wait, TASK_UNINTERRUPTIBLE); - spin_unlock_irq(&tsadc->reg_lock); + spin_unlock_irq(&tscadc->reg_lock); schedule(); - spin_lock_irq(&tsadc->reg_lock); - finish_wait(&tsadc->reg_se_wait, &wait); + spin_lock_irq(&tscadc->reg_lock); + finish_wait(&tscadc->reg_se_wait, &wait); /* * Sequencer should either be idle or * busy applying the charge step. */ - reg = tscadc_readl(tsadc, REG_ADCFSM); + regmap_read(tscadc->regmap, REG_ADCFSM, ®); WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP)); - tsadc->adc_waiting = false; + tscadc->adc_waiting = false; } - tsadc->adc_in_use = true; + tscadc->adc_in_use = true; } -void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) +void am335x_tsc_se_set_once(struct ti_tscadc_dev *tscadc, u32 val) { - spin_lock_irq(&tsadc->reg_lock); - am335x_tscadc_need_adc(tsadc); + spin_lock_irq(&tscadc->reg_lock); + am335x_tscadc_need_adc(tscadc); - tscadc_writel(tsadc, REG_SE, val); - spin_unlock_irq(&tsadc->reg_lock); + regmap_write(tscadc->regmap, REG_SE, val); + spin_unlock_irq(&tscadc->reg_lock); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); -void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc) +void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tscadc) { unsigned long flags; - spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->adc_in_use = false; - tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); - spin_unlock_irqrestore(&tsadc->reg_lock, flags); + spin_lock_irqsave(&tscadc->reg_lock, flags); + tscadc->adc_in_use = false; + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); + spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); -void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) +void am335x_tsc_se_clr(struct ti_tscadc_dev *tscadc, u32 val) { unsigned long flags; - spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->reg_se_cache &= ~val; - tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); - spin_unlock_irqrestore(&tsadc->reg_lock, flags); + spin_lock_irqsave(&tscadc->reg_lock, flags); + tscadc->reg_se_cache &= ~val; + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); + spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); -static void tscadc_idle_config(struct ti_tscadc_dev *config) +static void tscadc_idle_config(struct ti_tscadc_dev *tscadc) { unsigned int idleconfig; idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; - tscadc_writel(config, REG_IDLECONFIG, idleconfig); + regmap_write(tscadc->regmap, REG_IDLECONFIG, idleconfig); } static int ti_tscadc_probe(struct platform_device *pdev) @@ -182,8 +168,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) } /* Allocate memory for device */ - tscadc = devm_kzalloc(&pdev->dev, - sizeof(struct ti_tscadc_dev), GFP_KERNEL); + tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL); if (!tscadc) { dev_err(&pdev->dev, "failed to allocate memory.\n"); return -ENOMEM; @@ -202,11 +187,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) if (IS_ERR(tscadc->tscadc_base)) return PTR_ERR(tscadc->tscadc_base); - tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev, + tscadc->regmap = devm_regmap_init_mmio(&pdev->dev, tscadc->tscadc_base, &tscadc_regmap_config); - if (IS_ERR(tscadc->regmap_tscadc)) { + if (IS_ERR(tscadc->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); - err = PTR_ERR(tscadc->regmap_tscadc); + err = PTR_ERR(tscadc->regmap); goto ret; } @@ -236,11 +221,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ tscadc->clk_div--; - tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div); + regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); /* Set the control register bits */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - tscadc_writel(tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); /* Set register bits for Idle Config Mode */ if (tsc_wires > 0) { @@ -254,7 +239,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* Enable the TSC module enable bit */ ctrl |= CNTRLREG_TSCSSENB; - tscadc_writel(tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); tscadc->used_cells = 0; tscadc->tsc_cell = -1; @@ -300,7 +285,7 @@ static int ti_tscadc_remove(struct platform_device *pdev) { struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); - tscadc_writel(tscadc, REG_SE, 0x00); + regmap_write(tscadc->regmap, REG_SE, 0x00); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -310,51 +295,43 @@ static int ti_tscadc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int tscadc_suspend(struct device *dev) +static int __maybe_unused tscadc_suspend(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); - tscadc_writel(tscadc_dev, REG_SE, 0x00); + regmap_write(tscadc->regmap, REG_SE, 0x00); pm_runtime_put_sync(dev); return 0; } -static int tscadc_resume(struct device *dev) +static int __maybe_unused tscadc_resume(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); u32 ctrl; pm_runtime_get_sync(dev); /* context restore */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - tscadc_writel(tscadc_dev, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); - if (tscadc_dev->tsc_cell != -1) { - if (tscadc_dev->tsc_wires == 5) + if (tscadc->tsc_cell != -1) { + if (tscadc->tsc_wires == 5) ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; else ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; - tscadc_idle_config(tscadc_dev); + tscadc_idle_config(tscadc); } ctrl |= CNTRLREG_TSCSSENB; - tscadc_writel(tscadc_dev, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); - tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div); + regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); return 0; } -static const struct dev_pm_ops tscadc_pm_ops = { - .suspend = tscadc_suspend, - .resume = tscadc_resume, -}; -#define TSCADC_PM_OPS (&tscadc_pm_ops) -#else -#define TSCADC_PM_OPS NULL -#endif +static SIMPLE_DEV_PM_OPS(tscadc_pm_ops, tscadc_suspend, tscadc_resume); static const struct of_device_id ti_tscadc_dt_ids[] = { { .compatible = "ti,am3359-tscadc", }, @@ -365,7 +342,7 @@ MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids); static struct platform_driver ti_tscadc_driver = { .driver = { .name = "ti_am3359-tscadc", - .pm = TSCADC_PM_OPS, + .pm = &tscadc_pm_ops, .of_match_table = ti_tscadc_dt_ids, }, .probe = ti_tscadc_probe, diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 40beb2f..1f308c4 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -105,8 +105,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, } static const struct i2c_device_id tps6507x_i2c_id[] = { - { "tps6507x", 0 }, - { } + { "tps6507x", 0 }, + { } }; MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id); diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 831696e..a49d3db 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -622,11 +622,8 @@ add_numbered_child(unsigned mod_no, const char *name, int num, twl = &twl_priv->twl_modules[sid]; pdev = platform_device_alloc(name, num); - if (!pdev) { - dev_dbg(&twl->client->dev, "can't alloc dev\n"); - status = -ENOMEM; - goto err; - } + if (!pdev) + return ERR_PTR(-ENOMEM); pdev->dev.parent = &twl->client->dev; @@ -634,7 +631,7 @@ add_numbered_child(unsigned mod_no, const char *name, int num, status = platform_device_add_data(pdev, pdata, pdata_len); if (status < 0) { dev_dbg(&pdev->dev, "can't add platform_data\n"); - goto err; + goto put_device; } } @@ -647,21 +644,22 @@ add_numbered_child(unsigned mod_no, const char *name, int num, status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1); if (status < 0) { dev_dbg(&pdev->dev, "can't add irqs\n"); - goto err; + goto put_device; } } status = platform_device_add(pdev); - if (status == 0) - device_init_wakeup(&pdev->dev, can_wakeup); + if (status) + goto put_device; + + device_init_wakeup(&pdev->dev, can_wakeup); -err: - if (status < 0) { - platform_device_put(pdev); - dev_err(&twl->client->dev, "can't add %s dev\n", name); - return ERR_PTR(status); - } return &pdev->dev; + +put_device: + platform_device_put(pdev); + dev_err(&twl->client->dev, "failed to add device %s\n", name); + return ERR_PTR(status); } static inline struct device *add_child(unsigned mod_no, const char *name, diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 852d587..ab328ec 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -323,8 +323,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; - twl6040->sysclk = 19200000; - twl6040->mclk = 32768; + twl6040->sysclk_rate = 19200000; } else { /* already powered-down */ if (!twl6040->power_count) { @@ -352,8 +351,12 @@ int twl6040_power(struct twl6040 *twl6040, int on) regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); - twl6040->sysclk = 0; - twl6040->mclk = 0; + twl6040->sysclk_rate = 0; + + if (twl6040->pll == TWL6040_SYSCLK_SEL_HPPLL) { + clk_disable_unprepare(twl6040->mclk); + twl6040->mclk_rate = 0; + } clk_disable_unprepare(twl6040->clk32k); } @@ -377,15 +380,15 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, /* Force full reconfiguration when switching between PLL */ if (pll_id != twl6040->pll) { - twl6040->sysclk = 0; - twl6040->mclk = 0; + twl6040->sysclk_rate = 0; + twl6040->mclk_rate = 0; } switch (pll_id) { case TWL6040_SYSCLK_SEL_LPPLL: /* low-power PLL divider */ /* Change the sysclk configuration only if it has been canged */ - if (twl6040->sysclk != freq_out) { + if (twl6040->sysclk_rate != freq_out) { switch (freq_out) { case 17640000: lppllctl |= TWL6040_LPLLFIN; @@ -427,6 +430,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, ret = -EINVAL; goto pll_out; } + + clk_disable_unprepare(twl6040->mclk); break; case TWL6040_SYSCLK_SEL_HPPLL: /* high-performance PLL can provide only 19.2 MHz */ @@ -437,7 +442,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - if (twl6040->mclk != freq_in) { + if (twl6040->mclk_rate != freq_in) { hppllctl &= ~TWL6040_MCLK_MSK; switch (freq_in) { @@ -468,6 +473,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } + /* When switching to HPPLL, enable the mclk first */ + if (pll_id != twl6040->pll) + clk_prepare_enable(twl6040->mclk); /* * enable clock slicer to ensure input waveform is * square @@ -483,6 +491,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, lppllctl &= ~TWL6040_LPLLENA; twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); + + twl6040->mclk_rate = freq_in; } break; default: @@ -491,8 +501,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - twl6040->sysclk = freq_out; - twl6040->mclk = freq_in; + twl6040->sysclk_rate = freq_out; twl6040->pll = pll_id; pll_out: @@ -512,7 +521,7 @@ EXPORT_SYMBOL(twl6040_get_pll); unsigned int twl6040_get_sysclk(struct twl6040 *twl6040) { - return twl6040->sysclk; + return twl6040->sysclk_rate; } EXPORT_SYMBOL(twl6040_get_sysclk); @@ -655,10 +664,18 @@ static int twl6040_probe(struct i2c_client *client, if (IS_ERR(twl6040->clk32k)) { if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER) return -EPROBE_DEFER; - dev_info(&client->dev, "clk32k is not handled\n"); + dev_dbg(&client->dev, "clk32k is not handled\n"); twl6040->clk32k = NULL; } + twl6040->mclk = devm_clk_get(&client->dev, "mclk"); + if (IS_ERR(twl6040->mclk)) { + if (PTR_ERR(twl6040->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(&client->dev, "mclk is not handled\n"); + twl6040->mclk = NULL; + } + twl6040->supplies[0].supply = "vio"; twl6040->supplies[1].supply = "v2v1"; ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, |