diff options
author | Linus Torvalds | 2017-07-07 13:30:05 -0700 |
---|---|---|
committer | Linus Torvalds | 2017-07-07 13:30:05 -0700 |
commit | 6972b007ca771e33dec992ccd104c95a97a186e5 (patch) | |
tree | 0668041e466832b3157bcb02fa7923a29d477ea2 /drivers/mfd | |
parent | c7d28eca1d58d335ff8de6f33559b221bdd029f9 (diff) | |
parent | 1e3496000c11ec1ec56cf664b6a01d66de423507 (diff) |
Merge (most of) tag 'mfd-next-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"New Drivers:
- Intel Cherry Trail Whiskey Cove PMIC
- TI LP87565 PMIC
New Device Support:
- Add support for Cannonlake to intel-lpss-pci
- Add support for Simatic IOT2000 to intel_quark_i2c_gpio
New Functionality:
- Add Regulator support (axp20x)
Fix-ups:
- Rework IRQ handling (intel_soc_pmic_bxtwc, rtsx_pcr, cros_ec)
- Remove unused/unwelcome code (ipaq-micro, wm831x-core, da9062-core)
- Provide deregistration on unbind (rn5t618)
- Rework DT code/documentation (arizona)
- Constify things (fsl-imx25-tsadc)
- MAINTAINERS updates (DA9062/61)
- Kconfig configuration adaptions (INTEL_SOC_PMIC, MFD_AXP20X_I2C)
- Switch to DMI matching (intel_quark_i2c_gpio)
- Provide an appropriate level of error checking (wm831x-{i2c,spi},
twl4030-irq, tc6393xb)
- Make use of devm_* (resource handling) calls (intel_soc_pmic_bxtwc,
stm32-timers, atmel-flexcom, cros_ec, fsl-imx25-tsadc,
exynos-lpass, palmas, qcom-spmi-pmic, smsc-ece1099,
motorola-cpcap)"
[ Skipped the last commit in that series that added eight thousand
lines of pointless repeated register definitions. - Linus ]
* tag 'mfd-next-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (38 commits)
mfd: Add LP87565 PMIC support
mfd: cros_ec: Free IRQ on exit
dt-bindings: vendor-prefixes: Add arctic to vendor prefix
mfd: da9061: Fix to remove BBAT_CONT register from chip model
mfd: da9061: Fix to remove BBAT_CONT register from chip model
mfd: axp20x-i2c: Document that this must be builtin on x86
mfd: Add Cherry Trail Whiskey Cove PMIC driver
mfd: tc6393xb: Handle return value of clk_prepare_enable
mfd: intel_quark_i2c_gpio: Add support for SIMATIC IOT2000 platform
mfd: intel_quark_i2c_gpio: Use dmi_system_id table for retrieving frequency
mfd: motorola-cpcap: Use devm_of_platform_populate()
mfd: smsc-ece: Use devm_of_platform_populate()
mfd: qcom-spmi-pmic: Use devm_of_platform_populate()
mfd: palmas: Use devm_of_platform_populate()
mfd: exynos: Use devm_of_platform_populate()
mfd: fsl-imx25: Use devm_of_platform_populate()
mfd: cros_ec: Use devm_of_platform_populate()
mfd: atmel: Use devm_of_platform_populate()
mfd: stm32-timers: Use devm_of_platform_populate()
mfd: intel_soc_pmic: Select designware i2c-bus driver
...
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 44 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 2 | ||||
-rw-r--r-- | drivers/mfd/atmel-flexcom.c | 2 | ||||
-rw-r--r-- | drivers/mfd/axp20x.c | 3 | ||||
-rw-r--r-- | drivers/mfd/cros_ec.c | 5 | ||||
-rw-r--r-- | drivers/mfd/da9062-core.c | 12 | ||||
-rw-r--r-- | drivers/mfd/exynos-lpass.c | 2 | ||||
-rw-r--r-- | drivers/mfd/fsl-imx25-tsadc.c | 7 | ||||
-rw-r--r-- | drivers/mfd/intel-lpss-pci.c | 24 | ||||
-rw-r--r-- | drivers/mfd/intel_quark_i2c_gpio.c | 49 | ||||
-rw-r--r-- | drivers/mfd/intel_soc_pmic_bxtwc.c | 232 | ||||
-rw-r--r-- | drivers/mfd/intel_soc_pmic_chtwc.c | 230 | ||||
-rw-r--r-- | drivers/mfd/ipaq-micro.c | 5 | ||||
-rw-r--r-- | drivers/mfd/lp87565.c | 100 | ||||
-rw-r--r-- | drivers/mfd/motorola-cpcap.c | 13 | ||||
-rw-r--r-- | drivers/mfd/palmas.c | 2 | ||||
-rw-r--r-- | drivers/mfd/qcom-spmi-pmic.c | 9 | ||||
-rw-r--r-- | drivers/mfd/rn5t618.c | 2 | ||||
-rw-r--r-- | drivers/mfd/rtsx_pcr.c | 17 | ||||
-rw-r--r-- | drivers/mfd/smsc-ece1099.c | 3 | ||||
-rw-r--r-- | drivers/mfd/stm32-timers.c | 10 | ||||
-rw-r--r-- | drivers/mfd/tc6393xb.c | 4 | ||||
-rw-r--r-- | drivers/mfd/twl4030-irq.c | 4 | ||||
-rw-r--r-- | drivers/mfd/wm831x-core.c | 26 | ||||
-rw-r--r-- | drivers/mfd/wm831x-i2c.c | 4 | ||||
-rw-r--r-- | drivers/mfd/wm831x-spi.c | 4 |
26 files changed, 641 insertions, 174 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3eb5c93595f6..94ad2c1c3d90 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -160,6 +160,11 @@ config MFD_AXP20X_I2C components like regulators or the PEK (Power Enable Key) under the corresponding menus. + Note on x86 this provides an ACPI OpRegion, so this must be 'y' + (builtin) and not a module, as the OpRegion must be available as + soon as possible. For the same reason the I2C bus driver options + I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_BAYTRAIL must be 'y' too. + config MFD_AXP20X_RSB tristate "X-Powers AXP series PMICs with RSB" select MFD_AXP20X @@ -448,17 +453,22 @@ config LPC_SCH config INTEL_SOC_PMIC bool "Support for Crystal Cove PMIC" - depends on GPIOLIB - depends on I2C=y + depends on HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK + depends on X86 || COMPILE_TEST select MFD_CORE select REGMAP_I2C select REGMAP_IRQ + select I2C_DESIGNWARE_PLATFORM if ACPI help Select this option to enable support for Crystal Cove PMIC on some Intel SoC systems. The PMIC provides ADC, GPIO, thermal, charger and related power management functions on these systems. + This option is a bool as it provides an ACPI OpRegion which must be + available before any devices using it are probed. This option also + causes the designware-i2c driver to be builtin for the same reason. + config INTEL_SOC_PMIC_BXTWC tristate "Support for Intel Broxton Whiskey Cove PMIC" depends on INTEL_PMC_IPC @@ -470,6 +480,22 @@ config INTEL_SOC_PMIC_BXTWC thermal, charger and related power management functions on these systems. +config INTEL_SOC_PMIC_CHTWC + tristate "Support for Intel Cherry Trail Whiskey Cove PMIC" + depends on ACPI && HAS_IOMEM && I2C=y && COMMON_CLK + depends on X86 || COMPILE_TEST + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + select I2C_DESIGNWARE_PLATFORM + help + Select this option to enable support for the Intel Cherry Trail + Whiskey Cove PMIC found on some Intel Cherry Trail systems. + + This option is a bool as it provides an ACPI OpRegion which must be + available before any devices using it are probed. This option also + causes the designware-i2c driver to be builtin for the same reason. + config MFD_INTEL_LPSS tristate select COMMON_CLK @@ -1325,6 +1351,20 @@ config MFD_TI_LP873X This driver can also be built as a module. If so, the module will be called lp873x. +config MFD_TI_LP87565 + tristate "TI LP87565 Power Management IC" + depends on I2C && OF + select MFD_CORE + select REGMAP_I2C + help + If you say yes here then you get support for the LP87565 series of + Power Management Integrated Circuits (PMIC). + These include voltage regulators, thermal protection, configurable + General Purpose Outputs (GPO) that are used in portable devices. + + This driver can also be built as a module. If so, the module + will be called lp87565. + config MFD_TPS65218 tristate "TI TPS65218 Power Management chips" depends on I2C diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index c16bf1ea0ea9..080793b3fd0e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o obj-$(CONFIG_MFD_TI_LP873X) += lp873x.o +obj-$(CONFIG_MFD_TI_LP87565) += lp87565.o obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o @@ -214,6 +215,7 @@ obj-$(CONFIG_MFD_SKY81452) += sky81452.o intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o +obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c index e8e67be6b493..064bde9cff5a 100644 --- a/drivers/mfd/atmel-flexcom.c +++ b/drivers/mfd/atmel-flexcom.c @@ -80,7 +80,7 @@ static int atmel_flexcom_probe(struct platform_device *pdev) clk_disable_unprepare(clk); - return of_platform_populate(np, NULL, NULL, &pdev->dev); + return devm_of_platform_populate(&pdev->dev); } static const struct of_device_id atmel_flexcom_of_match[] = { diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 1dc6235778eb..917b6ddc4f15 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -848,7 +848,8 @@ static struct mfd_cell axp803_cells[] = { .name = "axp20x-pek", .num_resources = ARRAY_SIZE(axp803_pek_resources), .resources = axp803_pek_resources, - } + }, + { .name = "axp20x-regulator" }, }; static struct mfd_cell axp806_cells[] = { diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index d4a407e466b5..dc6ce9091694 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c @@ -147,7 +147,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) } if (IS_ENABLED(CONFIG_OF) && dev->of_node) { - err = of_platform_populate(dev->of_node, NULL, NULL, dev); + err = devm_of_platform_populate(dev); if (err) { mfd_remove_devices(dev); dev_err(dev, "Failed to register sub-devices\n"); @@ -183,6 +183,9 @@ int cros_ec_remove(struct cros_ec_device *ec_dev) cros_ec_acpi_remove_gpe_handler(); + if (ec_dev->irq) + free_irq(ec_dev->irq, ec_dev); + return 0; } EXPORT_SYMBOL(cros_ec_remove); diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index 7f5e8be0a9ea..fbe0f245ce8e 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -429,9 +429,6 @@ static const struct regmap_range da9061_aa_readable_ranges[] = { .range_min = DA9062AA_VLDO1_B, .range_max = DA9062AA_VLDO4_B, }, { - .range_min = DA9062AA_BBAT_CONT, - .range_max = DA9062AA_BBAT_CONT, - }, { .range_min = DA9062AA_INTERFACE, .range_max = DA9062AA_CONFIG_E, }, { @@ -514,9 +511,6 @@ static const struct regmap_range da9061_aa_writeable_ranges[] = { .range_min = DA9062AA_VLDO1_B, .range_max = DA9062AA_VLDO4_B, }, { - .range_min = DA9062AA_BBAT_CONT, - .range_max = DA9062AA_BBAT_CONT, - }, { .range_min = DA9062AA_GP_ID_0, .range_max = DA9062AA_GP_ID_19, }, @@ -651,9 +645,6 @@ static const struct regmap_range da9062_aa_readable_ranges[] = { .range_min = DA9062AA_VLDO1_B, .range_max = DA9062AA_VLDO4_B, }, { - .range_min = DA9062AA_BBAT_CONT, - .range_max = DA9062AA_BBAT_CONT, - }, { .range_min = DA9062AA_INTERFACE, .range_max = DA9062AA_CONFIG_E, }, { @@ -730,9 +721,6 @@ static const struct regmap_range da9062_aa_writeable_ranges[] = { .range_min = DA9062AA_VLDO1_B, .range_max = DA9062AA_VLDO4_B, }, { - .range_min = DA9062AA_BBAT_CONT, - .range_max = DA9062AA_BBAT_CONT, - }, { .range_min = DA9062AA_GP_ID_0, .range_max = DA9062AA_GP_ID_19, }, diff --git a/drivers/mfd/exynos-lpass.c b/drivers/mfd/exynos-lpass.c index 0bf3aebdac45..ca829f85672f 100644 --- a/drivers/mfd/exynos-lpass.c +++ b/drivers/mfd/exynos-lpass.c @@ -138,7 +138,7 @@ static int exynos_lpass_probe(struct platform_device *pdev) pm_runtime_enable(dev); exynos_lpass_enable(lpass); - return of_platform_populate(dev->of_node, NULL, NULL, dev); + return devm_of_platform_populate(dev); } static int exynos_lpass_remove(struct platform_device *pdev) diff --git a/drivers/mfd/fsl-imx25-tsadc.c b/drivers/mfd/fsl-imx25-tsadc.c index ac430a396a89..b3767c3141e5 100644 --- a/drivers/mfd/fsl-imx25-tsadc.c +++ b/drivers/mfd/fsl-imx25-tsadc.c @@ -59,7 +59,7 @@ static int mx25_tsadc_domain_map(struct irq_domain *d, unsigned int irq, return 0; } -static struct irq_domain_ops mx25_tsadc_domain_ops = { +static const struct irq_domain_ops mx25_tsadc_domain_ops = { .map = mx25_tsadc_domain_map, .xlate = irq_domain_xlate_onecell, }; @@ -129,7 +129,6 @@ static void mx25_tsadc_setup_clk(struct platform_device *pdev, static int mx25_tsadc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; struct mx25_tsadc *tsadc; struct resource *res; int ret; @@ -178,9 +177,7 @@ static int mx25_tsadc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, tsadc); - of_platform_populate(np, NULL, NULL, dev); - - return 0; + return devm_of_platform_populate(dev); } static const struct of_device_id mx25_tsadc_ids[] = { diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 16ffeaeb1385..ad388bb056cd 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -201,6 +201,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x9d64), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0x9d65), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0x9d66), (kernel_ulong_t)&spt_uart_info }, + /* CNL-LP */ + { PCI_VDEVICE(INTEL, 0x9da8), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x9da9), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9dc7), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&spt_i2c_info }, /* SPT-H */ { PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info }, @@ -219,6 +232,17 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0xa2e2), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0xa2e3), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0xa2e6), (kernel_ulong_t)&spt_uart_info }, + /* CNL-H */ + { PCI_VDEVICE(INTEL, 0xa328), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0xa329), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0xa32a), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0xa347), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&spt_i2c_info }, { } }; MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids); diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 7946d6e38b87..90e35dec8648 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -58,19 +58,34 @@ struct intel_quark_mfd { struct clk_lookup *i2c_clk_lookup; }; -struct i2c_mode_info { - const char *name; - unsigned int i2c_scl_freq; -}; - -static const struct i2c_mode_info platform_i2c_mode_info[] = { +static const struct dmi_system_id dmi_platform_info[] = { + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"), + }, + .driver_data = (void *)100000, + }, { - .name = "Galileo", - .i2c_scl_freq = 100000, + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"), + }, + .driver_data = (void *)400000, }, { - .name = "GalileoGen2", - .i2c_scl_freq = 400000, + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), + DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, + "6ES7647-0AA00-0YA2"), + }, + .driver_data = (void *)400000, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), + DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, + "6ES7647-0AA00-1YA2"), + }, + .driver_data = (void *)400000, }, {} }; @@ -160,8 +175,7 @@ static void intel_quark_unregister_i2c_clk(struct device *dev) static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell) { - const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); - const struct i2c_mode_info *info; + const struct dmi_system_id *dmi_id; struct dw_i2c_platform_data *pdata; struct resource *res = (struct resource *)cell->resources; struct device *dev = &pdev->dev; @@ -181,14 +195,9 @@ static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell) /* Normal mode by default */ pdata->i2c_scl_freq = 100000; - if (board_name) { - for (info = platform_i2c_mode_info; info->name; info++) { - if (!strcmp(board_name, info->name)) { - pdata->i2c_scl_freq = info->i2c_scl_freq; - break; - } - } - } + dmi_id = dmi_first_match(dmi_platform_info); + if (dmi_id) + pdata->i2c_scl_freq = (uintptr_t)dmi_id->driver_data; cell->platform_data = pdata; cell->pdata_size = sizeof(*pdata); diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index 8c3cbf63c6ad..15bc052704a6 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -82,20 +82,26 @@ enum bxtwc_irqs { BXTWC_PWRBTN_IRQ, }; -enum bxtwc_irqs_level2 { - /* Level 2 */ - BXTWC_THRM0_IRQ = 0, - BXTWC_THRM1_IRQ, - BXTWC_THRM2_IRQ, - BXTWC_BCU_IRQ, - BXTWC_ADC_IRQ, - BXTWC_USBC_IRQ, +enum bxtwc_irqs_bcu { + BXTWC_BCU_IRQ = 0, +}; + +enum bxtwc_irqs_adc { + BXTWC_ADC_IRQ = 0, +}; + +enum bxtwc_irqs_chgr { + BXTWC_USBC_IRQ = 0, BXTWC_CHGR0_IRQ, BXTWC_CHGR1_IRQ, - BXTWC_GPIO0_IRQ, - BXTWC_GPIO1_IRQ, - BXTWC_CRIT_IRQ, - BXTWC_TMU_IRQ, +}; + +enum bxtwc_irqs_tmu { + BXTWC_TMU_IRQ = 0, +}; + +enum bxtwc_irqs_crit { + BXTWC_CRIT_IRQ = 0, }; static const struct regmap_irq bxtwc_regmap_irqs[] = { @@ -110,24 +116,28 @@ static const struct regmap_irq bxtwc_regmap_irqs[] = { REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 1, 0x03), }; -static const struct regmap_irq bxtwc_regmap_irqs_level2[] = { - REGMAP_IRQ_REG(BXTWC_THRM0_IRQ, 0, 0xff), - REGMAP_IRQ_REG(BXTWC_THRM1_IRQ, 1, 0xbf), - REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff), - REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f), - REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff), - REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 5, BIT(5)), - REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f), - REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f), - REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff), - REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f), - REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03), +static const struct regmap_irq bxtwc_regmap_irqs_bcu[] = { + REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 0, 0x1f), +}; + +static const struct regmap_irq bxtwc_regmap_irqs_adc[] = { + REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 0, 0xff), +}; + +static const struct regmap_irq bxtwc_regmap_irqs_chgr[] = { + REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 0, BIT(5)), + REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 0, 0x1f), + REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 1, 0x1f), }; static const struct regmap_irq bxtwc_regmap_irqs_tmu[] = { REGMAP_IRQ_REG(BXTWC_TMU_IRQ, 0, 0x06), }; +static const struct regmap_irq bxtwc_regmap_irqs_crit[] = { + REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 0, 0x03), +}; + static struct regmap_irq_chip bxtwc_regmap_irq_chip = { .name = "bxtwc_irq_chip", .status_base = BXTWC_IRQLVL1, @@ -137,15 +147,6 @@ static struct regmap_irq_chip bxtwc_regmap_irq_chip = { .num_regs = 2, }; -static struct regmap_irq_chip bxtwc_regmap_irq_chip_level2 = { - .name = "bxtwc_irq_chip_level2", - .status_base = BXTWC_THRM0IRQ, - .mask_base = BXTWC_MTHRM0IRQ, - .irqs = bxtwc_regmap_irqs_level2, - .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_level2), - .num_regs = 10, -}; - static struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = { .name = "bxtwc_irq_chip_tmu", .status_base = BXTWC_TMUIRQ, @@ -155,9 +156,44 @@ static struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = { .num_regs = 1, }; +static struct regmap_irq_chip bxtwc_regmap_irq_chip_bcu = { + .name = "bxtwc_irq_chip_bcu", + .status_base = BXTWC_BCUIRQ, + .mask_base = BXTWC_MBCUIRQ, + .irqs = bxtwc_regmap_irqs_bcu, + .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_bcu), + .num_regs = 1, +}; + +static struct regmap_irq_chip bxtwc_regmap_irq_chip_adc = { + .name = "bxtwc_irq_chip_adc", + .status_base = BXTWC_ADCIRQ, + .mask_base = BXTWC_MADCIRQ, + .irqs = bxtwc_regmap_irqs_adc, + .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_adc), + .num_regs = 1, +}; + +static struct regmap_irq_chip bxtwc_regmap_irq_chip_chgr = { + .name = "bxtwc_irq_chip_chgr", + .status_base = BXTWC_CHGR0IRQ, + .mask_base = BXTWC_MCHGR0IRQ, + .irqs = bxtwc_regmap_irqs_chgr, + .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_chgr), + .num_regs = 2, +}; + +static struct regmap_irq_chip bxtwc_regmap_irq_chip_crit = { + .name = "bxtwc_irq_chip_crit", + .status_base = BXTWC_CRITIRQ, + .mask_base = BXTWC_MCRITIRQ, + .irqs = bxtwc_regmap_irqs_crit, + .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_crit), + .num_regs = 1, +}; + static struct resource gpio_resources[] = { - DEFINE_RES_IRQ_NAMED(BXTWC_GPIO0_IRQ, "GPIO0"), - DEFINE_RES_IRQ_NAMED(BXTWC_GPIO1_IRQ, "GPIO1"), + DEFINE_RES_IRQ_NAMED(BXTWC_GPIO_LVL1_IRQ, "GPIO"), }; static struct resource adc_resources[] = { @@ -174,9 +210,7 @@ static struct resource charger_resources[] = { }; static struct resource thermal_resources[] = { - DEFINE_RES_IRQ(BXTWC_THRM0_IRQ), - DEFINE_RES_IRQ(BXTWC_THRM1_IRQ), - DEFINE_RES_IRQ(BXTWC_THRM2_IRQ), + DEFINE_RES_IRQ(BXTWC_THRM_LVL1_IRQ), }; static struct resource bcu_resources[] = { @@ -367,6 +401,26 @@ static const struct regmap_config bxtwc_regmap_config = { .reg_read = regmap_ipc_byte_reg_read, }; +static int bxtwc_add_chained_irq_chip(struct intel_soc_pmic *pmic, + struct regmap_irq_chip_data *pdata, + int pirq, int irq_flags, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data) +{ + int irq; + + irq = regmap_irq_get_virq(pdata, pirq); + if (irq < 0) { + dev_err(pmic->dev, + "Failed to get parent vIRQ(%d) for chip %s, ret:%d\n", + pirq, chip->name, irq); + return irq; + } + + return devm_regmap_add_irq_chip(pmic->dev, pmic->regmap, irq, irq_flags, + 0, chip, data); +} + static int bxtwc_probe(struct platform_device *pdev) { int ret; @@ -409,45 +463,88 @@ static int bxtwc_probe(struct platform_device *pdev) return ret; } - ret = regmap_add_irq_chip(pmic->regmap, pmic->irq, - IRQF_ONESHOT | IRQF_SHARED, - 0, &bxtwc_regmap_irq_chip, - &pmic->irq_chip_data); + ret = devm_regmap_add_irq_chip(&pdev->dev, pmic->regmap, pmic->irq, + IRQF_ONESHOT | IRQF_SHARED, + 0, &bxtwc_regmap_irq_chip, + &pmic->irq_chip_data); if (ret) { dev_err(&pdev->dev, "Failed to add IRQ chip\n"); return ret; } - ret = regmap_add_irq_chip(pmic->regmap, pmic->irq, - IRQF_ONESHOT | IRQF_SHARED, - 0, &bxtwc_regmap_irq_chip_level2, - &pmic->irq_chip_data_level2); + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_TMU_LVL1_IRQ, + IRQF_ONESHOT, + &bxtwc_regmap_irq_chip_tmu, + &pmic->irq_chip_data_tmu); if (ret) { - dev_err(&pdev->dev, "Failed to add secondary IRQ chip\n"); - goto err_irq_chip_level2; + dev_err(&pdev->dev, "Failed to add TMU IRQ chip\n"); + return ret; } - ret = regmap_add_irq_chip(pmic->regmap, pmic->irq, - IRQF_ONESHOT | IRQF_SHARED, - 0, &bxtwc_regmap_irq_chip_tmu, - &pmic->irq_chip_data_tmu); + /* Add chained IRQ handler for BCU IRQs */ + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_BCU_LVL1_IRQ, + IRQF_ONESHOT, + &bxtwc_regmap_irq_chip_bcu, + &pmic->irq_chip_data_bcu); + + if (ret) { - dev_err(&pdev->dev, "Failed to add TMU IRQ chip\n"); - goto err_irq_chip_tmu; + dev_err(&pdev->dev, "Failed to add BUC IRQ chip\n"); + return ret; + } + + /* Add chained IRQ handler for ADC IRQs */ + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_ADC_LVL1_IRQ, + IRQF_ONESHOT, + &bxtwc_regmap_irq_chip_adc, + &pmic->irq_chip_data_adc); + + + if (ret) { + dev_err(&pdev->dev, "Failed to add ADC IRQ chip\n"); + return ret; + } + + /* Add chained IRQ handler for CHGR IRQs */ + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_CHGR_LVL1_IRQ, + IRQF_ONESHOT, + &bxtwc_regmap_irq_chip_chgr, + &pmic->irq_chip_data_chgr); + + + if (ret) { + dev_err(&pdev->dev, "Failed to add CHGR IRQ chip\n"); + return ret; + } + + /* Add chained IRQ handler for CRIT IRQs */ + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_CRIT_LVL1_IRQ, + IRQF_ONESHOT, + &bxtwc_regmap_irq_chip_crit, + &pmic->irq_chip_data_crit); + + + if (ret) { + dev_err(&pdev->dev, "Failed to add CRIT IRQ chip\n"); + return ret; } - ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev, - ARRAY_SIZE(bxt_wc_dev), NULL, 0, - NULL); + ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev, + ARRAY_SIZE(bxt_wc_dev), NULL, 0, NULL); if (ret) { dev_err(&pdev->dev, "Failed to add devices\n"); - goto err_mfd; + return ret; } ret = sysfs_create_group(&pdev->dev.kobj, &bxtwc_group); if (ret) { dev_err(&pdev->dev, "Failed to create sysfs group %d\n", ret); - goto err_sysfs; + return ret; } /* @@ -461,28 +558,11 @@ static int bxtwc_probe(struct platform_device *pdev) BXTWC_MIRQLVL1_MCHGR, 0); return 0; - -err_sysfs: - mfd_remove_devices(&pdev->dev); -err_mfd: - regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_tmu); -err_irq_chip_tmu: - regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2); -err_irq_chip_level2: - regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); - - return ret; } static int bxtwc_remove(struct platform_device *pdev) { - struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev); - sysfs_remove_group(&pdev->dev.kobj, &bxtwc_group); - mfd_remove_devices(&pdev->dev); - regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); - regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2); - regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_tmu); return 0; } diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c new file mode 100644 index 000000000000..b35da01d5bcf --- /dev/null +++ b/drivers/mfd/intel_soc_pmic_chtwc.c @@ -0,0 +1,230 @@ +/* + * MFD core driver for Intel Cherrytrail Whiskey Cove PMIC + * + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> + * + * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: + * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mfd/core.h> +#include <linux/mfd/intel_soc_pmic.h> +#include <linux/regmap.h> + +/* PMIC device registers */ +#define REG_OFFSET_MASK GENMASK(7, 0) +#define REG_ADDR_MASK GENMASK(15, 8) +#define REG_ADDR_SHIFT 8 + +#define CHT_WC_IRQLVL1 0x6e02 +#define CHT_WC_IRQLVL1_MASK 0x6e0e + +/* Whiskey Cove PMIC share same ACPI ID between different platforms */ +#define CHT_WC_HRV 3 + +/* Level 1 IRQs (level 2 IRQs are handled in the child device drivers) */ +enum { + CHT_WC_PWRSRC_IRQ = 0, + CHT_WC_THRM_IRQ, + CHT_WC_BCU_IRQ, + CHT_WC_ADC_IRQ, + CHT_WC_EXT_CHGR_IRQ, + CHT_WC_GPIO_IRQ, + /* There is no irq 6 */ + CHT_WC_CRIT_IRQ = 7, +}; + +static struct resource cht_wc_pwrsrc_resources[] = { + DEFINE_RES_IRQ(CHT_WC_PWRSRC_IRQ), +}; + +static struct resource cht_wc_ext_charger_resources[] = { + DEFINE_RES_IRQ(CHT_WC_EXT_CHGR_IRQ), +}; + +static struct mfd_cell cht_wc_dev[] = { + { + .name = "cht_wcove_pwrsrc", + .num_resources = ARRAY_SIZE(cht_wc_pwrsrc_resources), + .resources = cht_wc_pwrsrc_resources, + }, { + .name = "cht_wcove_ext_chgr", + .num_resources = ARRAY_SIZE(cht_wc_ext_charger_resources), + .resources = cht_wc_ext_charger_resources, + }, + { .name = "cht_wcove_region", }, +}; + +/* + * The CHT Whiskey Cove covers multiple I2C addresses, with a 1 Byte + * register address space per I2C address, so we use 16 bit register + * addresses where the high 8 bits contain the I2C client address. + */ +static int cht_wc_byte_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct i2c_client *client = context; + int ret, orig_addr = client->addr; + + if (!(reg & REG_ADDR_MASK)) { + dev_err(&client->dev, "Error I2C address not specified\n"); + return -EINVAL; + } + + client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT; + ret = i2c_smbus_read_byte_data(client, reg & REG_OFFSET_MASK); + client->addr = orig_addr; + + if (ret < 0) + return ret; + + *val = ret; + return 0; +} + +static int cht_wc_byte_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct i2c_client *client = context; + int ret, orig_addr = client->addr; + + if (!(reg & REG_ADDR_MASK)) { + dev_err(&client->dev, "Error I2C address not specified\n"); + return -EINVAL; + } + + client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT; + ret = i2c_smbus_write_byte_data(client, reg & REG_OFFSET_MASK, val); + client->addr = orig_addr; + + return ret; +} + +static const struct regmap_config cht_wc_regmap_cfg = { + .reg_bits = 16, + .val_bits = 8, + .reg_write = cht_wc_byte_reg_write, + .reg_read = cht_wc_byte_reg_read, +}; + +static const struct regmap_irq cht_wc_regmap_irqs[] = { + REGMAP_IRQ_REG(CHT_WC_PWRSRC_IRQ, 0, BIT(CHT_WC_PWRSRC_IRQ)), + REGMAP_IRQ_REG(CHT_WC_THRM_IRQ, 0, BIT(CHT_WC_THRM_IRQ)), + REGMAP_IRQ_REG(CHT_WC_BCU_IRQ, 0, BIT(CHT_WC_BCU_IRQ)), + REGMAP_IRQ_REG(CHT_WC_ADC_IRQ, 0, BIT(CHT_WC_ADC_IRQ)), + REGMAP_IRQ_REG(CHT_WC_EXT_CHGR_IRQ, 0, BIT(CHT_WC_EXT_CHGR_IRQ)), + REGMAP_IRQ_REG(CHT_WC_GPIO_IRQ, 0, BIT(CHT_WC_GPIO_IRQ)), + REGMAP_IRQ_REG(CHT_WC_CRIT_IRQ, 0, BIT(CHT_WC_CRIT_IRQ)), +}; + +static const struct regmap_irq_chip cht_wc_regmap_irq_chip = { + .name = "cht_wc_irq_chip", + .status_base = CHT_WC_IRQLVL1, + .mask_base = CHT_WC_IRQLVL1_MASK, + .irqs = cht_wc_regmap_irqs, + .num_irqs = ARRAY_SIZE(cht_wc_regmap_irqs), + .num_regs = 1, +}; + +static int cht_wc_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct intel_soc_pmic *pmic; + acpi_status status; + unsigned long long hrv; + int ret; + + status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_HRV", NULL, &hrv); + if (ACPI_FAILURE(status)) { + dev_err(dev, "Failed to get PMIC hardware revision\n"); + return -ENODEV; + } + if (hrv != CHT_WC_HRV) { + dev_err(dev, "Invalid PMIC hardware revision: %llu\n", hrv); + return -ENODEV; + } + if (client->irq < 0) { + dev_err(dev, "Invalid IRQ\n"); + return -EINVAL; + } + + pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) + return -ENOMEM; + + pmic->irq = client->irq; + pmic->dev = dev; + i2c_set_clientdata(client, pmic); + + pmic->regmap = devm_regmap_init(dev, NULL, client, &cht_wc_regmap_cfg); + if (IS_ERR(pmic->regmap)) + return PTR_ERR(pmic->regmap); + + ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq, + IRQF_ONESHOT | IRQF_SHARED, 0, + &cht_wc_regmap_irq_chip, + &pmic->irq_chip_data); + if (ret) + return ret; + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + cht_wc_dev, ARRAY_SIZE(cht_wc_dev), NULL, 0, + regmap_irq_get_domain(pmic->irq_chip_data)); +} + +static void cht_wc_shutdown(struct i2c_client *client) +{ + struct intel_soc_pmic *pmic = i2c_get_clientdata(client); + + disable_irq(pmic->irq); +} + +static int __maybe_unused cht_wc_suspend(struct device *dev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + + disable_irq(pmic->irq); + + return 0; +} + +static int __maybe_unused cht_wc_resume(struct device *dev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + + enable_irq(pmic->irq); + + return 0; +} +static SIMPLE_DEV_PM_OPS(cht_wc_pm_ops, cht_wc_suspend, cht_wc_resume); + +static const struct i2c_device_id cht_wc_i2c_id[] = { + { } +}; + +static const struct acpi_device_id cht_wc_acpi_ids[] = { + { "INT34D3", }, + { } +}; + +static struct i2c_driver cht_wc_driver = { + .driver = { + .name = "CHT Whiskey Cove PMIC", + .pm = &cht_wc_pm_ops, + .acpi_match_table = cht_wc_acpi_ids, + }, + .probe_new = cht_wc_probe, + .shutdown = cht_wc_shutdown, + .id_table = cht_wc_i2c_id, +}; +builtin_i2c_driver(cht_wc_driver); diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c index 124aad2b1d02..cd762d08f116 100644 --- a/drivers/mfd/ipaq-micro.c +++ b/drivers/mfd/ipaq-micro.c @@ -53,8 +53,6 @@ static void ipaq_micro_trigger_tx(struct ipaq_micro *micro) tx->buf[bp++] = checksum; tx->len = bp; tx->index = 0; - print_hex_dump_debug("data: ", DUMP_PREFIX_OFFSET, 16, 1, - tx->buf, tx->len, true); /* Enable interrupt */ val = readl(micro->base + UTCR3); @@ -281,9 +279,6 @@ static void __init ipaq_micro_eeprom_dump(struct ipaq_micro *micro) dev_info(micro->dev, "RAM size: %u KiB\n", ipaq_micro_to_u16(dump+92)); dev_info(micro->dev, "screen: %u x %u\n", ipaq_micro_to_u16(dump+94), ipaq_micro_to_u16(dump+96)); - print_hex_dump_debug("eeprom: ", DUMP_PREFIX_OFFSET, 16, 1, - dump, 256, true); - } static void micro_tx_chars(struct ipaq_micro *micro) diff --git a/drivers/mfd/lp87565.c b/drivers/mfd/lp87565.c new file mode 100644 index 000000000000..340ad0c63744 --- /dev/null +++ b/drivers/mfd/lp87565.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * + * Author: Keerthy <j-keerthy@ti.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 the Free Software Foundation version 2. + */ + +#include <linux/interrupt.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/regmap.h> + +#include <linux/mfd/lp87565.h> + +static const struct regmap_config lp87565_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = LP87565_REG_MAX, +}; + +static const struct mfd_cell lp87565_cells[] = { + { .name = "lp87565-q1-regulator", }, + { .name = "lp87565-q1-gpio", }, +}; + +static const struct of_device_id of_lp87565_match_table[] = { + { .compatible = "ti,lp87565", }, + { + .compatible = "ti,lp87565-q1", + .data = (void *)LP87565_DEVICE_TYPE_LP87565_Q1, + }, + {} +}; +MODULE_DEVICE_TABLE(of, of_lp87565_match_table); + +static int lp87565_probe(struct i2c_client *client, + const struct i2c_device_id *ids) +{ + struct lp87565 *lp87565; + const struct of_device_id *of_id; + int ret; + unsigned int otpid; + + lp87565 = devm_kzalloc(&client->dev, sizeof(*lp87565), GFP_KERNEL); + if (!lp87565) + return -ENOMEM; + + lp87565->dev = &client->dev; + + lp87565->regmap = devm_regmap_init_i2c(client, &lp87565_regmap_config); + if (IS_ERR(lp87565->regmap)) { + ret = PTR_ERR(lp87565->regmap); + dev_err(lp87565->dev, + "Failed to initialize register map: %d\n", ret); + return ret; + } + + ret = regmap_read(lp87565->regmap, LP87565_REG_OTP_REV, &otpid); + if (ret) { + dev_err(lp87565->dev, "Failed to read OTP ID\n"); + return ret; + } + + lp87565->rev = otpid & LP87565_OTP_REV_OTP_ID; + + of_id = of_match_device(of_lp87565_match_table, &client->dev); + if (of_id) + lp87565->dev_type = (enum lp87565_device_type)of_id->data; + + i2c_set_clientdata(client, lp87565); + + ret = mfd_add_devices(lp87565->dev, PLATFORM_DEVID_AUTO, lp87565_cells, + ARRAY_SIZE(lp87565_cells), NULL, 0, NULL); + + return ret; +} + +static const struct i2c_device_id lp87565_id_table[] = { + { "lp87565-q1", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, lp87565_id_table); + +static struct i2c_driver lp87565_driver = { + .driver = { + .name = "lp87565", + .of_match_table = of_lp87565_match_table, + }, + .probe = lp87565_probe, + .id_table = lp87565_id_table, +}; +module_i2c_driver(lp87565_driver); + +MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>"); +MODULE_DESCRIPTION("lp87565 chip family Multi-Function Device driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index 3cab58ab0b84..d2cc1eabac05 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -260,17 +260,7 @@ static int cpcap_probe(struct spi_device *spi) if (ret) return ret; - return of_platform_populate(spi->dev.of_node, NULL, NULL, - &cpcap->spi->dev); -} - -static int cpcap_remove(struct spi_device *pdev) -{ - struct cpcap_ddata *cpcap = spi_get_drvdata(pdev); - - of_platform_depopulate(&cpcap->spi->dev); - - return 0; + return devm_of_platform_populate(&cpcap->spi->dev); } static struct spi_driver cpcap_driver = { @@ -279,7 +269,6 @@ static struct spi_driver cpcap_driver = { .of_match_table = cpcap_of_match, }, .probe = cpcap_probe, - .remove = cpcap_remove, }; module_spi_driver(cpcap_driver); diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 9103affedcbc..3922a93f9f92 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -676,7 +676,7 @@ no_irq: * otherwise continue and add devices using mfd helpers. */ if (node) { - ret = of_platform_populate(node, NULL, NULL, &i2c->dev); + ret = devm_of_platform_populate(&i2c->dev); if (ret < 0) { goto err_irq; } else if (pdata->pm_off && !pm_power_off) { diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c index 8653e8b9bb4f..2022bdfa7ab4 100644 --- a/drivers/mfd/qcom-spmi-pmic.c +++ b/drivers/mfd/qcom-spmi-pmic.c @@ -120,7 +120,6 @@ static const struct regmap_config spmi_regmap_config = { static int pmic_spmi_probe(struct spmi_device *sdev) { - struct device_node *root = sdev->dev.of_node; struct regmap *regmap; regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config); @@ -131,19 +130,13 @@ static int pmic_spmi_probe(struct spmi_device *sdev) if (sdev->usid % 2 == 0) pmic_spmi_show_revid(regmap, &sdev->dev); - return of_platform_populate(root, NULL, NULL, &sdev->dev); -} - -static void pmic_spmi_remove(struct spmi_device *sdev) -{ - of_platform_depopulate(&sdev->dev); + return devm_of_platform_populate(&sdev->dev); } MODULE_DEVICE_TABLE(of, pmic_spmi_id_table); static struct spmi_driver pmic_spmi_driver = { .probe = pmic_spmi_probe, - .remove = pmic_spmi_remove, .driver = { .name = "pmic-spmi", .of_match_table = pmic_spmi_id_table, diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index 8131d1975745..f4037d42a60f 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -155,6 +155,8 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c) pm_power_off = NULL; } + unregister_restart_handler(&rn5t618_restart_handler); + return 0; } diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 850590aac008..a0ac89dfdf0f 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -30,6 +30,7 @@ #include <linux/platform_device.h> #include <linux/mfd/core.h> #include <linux/mfd/rtsx_pci.h> +#include <linux/mmc/card.h> #include <asm/unaligned.h> #include "rtsx_pcr.h" @@ -452,8 +453,12 @@ int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, } spin_lock_irqsave(&pcr->lock, flags); - if (pcr->trans_result == TRANS_RESULT_FAIL) - err = -EINVAL; + if (pcr->trans_result == TRANS_RESULT_FAIL) { + err = -EILSEQ; + if (pcr->dma_error_count < RTS_MAX_TIMES_FREQ_REDUCTION) + pcr->dma_error_count++; + } + else if (pcr->trans_result == TRANS_NO_DEVICE) err = -ENODEV; spin_unlock_irqrestore(&pcr->lock, flags); @@ -659,6 +664,13 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, if (err < 0) return err; + /* Reduce card clock by 20MHz each time a DMA transfer error occurs */ + if (card_clock == UHS_SDR104_MAX_DTR && + pcr->dma_error_count && + PCI_PID(pcr) == RTS5227_DEVICE_ID) + card_clock = UHS_SDR104_MAX_DTR - + (pcr->dma_error_count * 20000000); + card_clock /= 1000000; pcr_dbg(pcr, "Switch card clock to %dMHz\n", card_clock); @@ -894,6 +906,7 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) pcr->card_removed |= SD_EXIST; pcr->card_inserted &= ~SD_EXIST; } + pcr->dma_error_count = 0; } if (int_reg & MS_INT) { diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c index 1f40baf1234e..93a8297de52a 100644 --- a/drivers/mfd/smsc-ece1099.c +++ b/drivers/mfd/smsc-ece1099.c @@ -69,8 +69,7 @@ static int smsc_i2c_probe(struct i2c_client *i2c, #ifdef CONFIG_OF if (i2c->dev.of_node) - ret = of_platform_populate(i2c->dev.of_node, - NULL, NULL, &i2c->dev); + ret = devm_of_platform_populate(&i2c->dev); #endif return ret; diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c index 2182f00db101..a6675a449409 100644 --- a/drivers/mfd/stm32-timers.c +++ b/drivers/mfd/stm32-timers.c @@ -58,14 +58,7 @@ static int stm32_timers_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ddata); - return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); -} - -static int stm32_timers_remove(struct platform_device *pdev) -{ - of_platform_depopulate(&pdev->dev); - - return 0; + return devm_of_platform_populate(&pdev->dev); } static const struct of_device_id stm32_timers_of_match[] = { @@ -76,7 +69,6 @@ MODULE_DEVICE_TABLE(of, stm32_timers_of_match); static struct platform_driver stm32_timers_driver = { .probe = stm32_timers_probe, - .remove = stm32_timers_remove, .driver = { .name = "stm32-timers", .of_match_table = stm32_timers_of_match, diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index d16e71bd9482..0c9f0390e891 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -797,7 +797,9 @@ static int tc6393xb_resume(struct platform_device *dev) int ret; int i; - clk_prepare_enable(tc6393xb->clk); + ret = clk_prepare_enable(tc6393xb->clk); + if (ret) + return ret; ret = tcpd->resume(dev); if (ret) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index b46c0cfc27d9..378c02d43bf7 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -638,8 +638,10 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base) } } - if (status < 0) + if (status < 0) { + dev_err(dev, "module to setup SIH for not found\n"); return status; + } agent = kzalloc(sizeof(*agent), GFP_KERNEL); if (!agent) diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 13a4c1190dca..e70d35ef5c6d 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1766,7 +1766,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq) } wm831x->locked = 1; - if (pdata && pdata->pre_init) { + if (pdata->pre_init) { ret = pdata->pre_init(wm831x); if (ret != 0) { dev_err(wm831x->dev, "pre_init() failed: %d\n", ret); @@ -1774,19 +1774,17 @@ int wm831x_device_init(struct wm831x *wm831x, int irq) } } - if (pdata) { - for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { - if (!pdata->gpio_defaults[i]) - continue; + for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { + if (!pdata->gpio_defaults[i]) + continue; - wm831x_reg_write(wm831x, - WM831X_GPIO1_CONTROL + i, - pdata->gpio_defaults[i] & 0xffff); - } + wm831x_reg_write(wm831x, + WM831X_GPIO1_CONTROL + i, + pdata->gpio_defaults[i] & 0xffff); } /* Multiply by 10 as we have many subdevices of the same type */ - if (pdata && pdata->wm831x_num) + if (pdata->wm831x_num) wm831x_num = pdata->wm831x_num * 10; else wm831x_num = -1; @@ -1809,7 +1807,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq) ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8311_devs, ARRAY_SIZE(wm8311_devs), NULL, 0, NULL); - if (!pdata || !pdata->disable_touch) + if (!pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), NULL, 0, NULL); @@ -1819,7 +1817,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq) ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8312_devs, ARRAY_SIZE(wm8312_devs), NULL, 0, NULL); - if (!pdata || !pdata->disable_touch) + if (!pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), NULL, 0, NULL); @@ -1865,7 +1863,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq) dev_info(wm831x->dev, "32.768kHz clock disabled, no RTC\n"); } - if (pdata && pdata->backlight) { + if (pdata->backlight) { /* Treat errors as non-critical */ ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, ARRAY_SIZE(backlight_devs), NULL, @@ -1877,7 +1875,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq) wm831x_otp_init(wm831x); - if (pdata && pdata->post_init) { + if (pdata->post_init) { ret = pdata->post_init(wm831x); if (ret != 0) { dev_err(wm831x->dev, "post_init() failed: %d\n", ret); diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c index 781af060f32d..22f7054d1b28 100644 --- a/drivers/mfd/wm831x-i2c.c +++ b/drivers/mfd/wm831x-i2c.c @@ -37,6 +37,10 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, if (i2c->dev.of_node) { of_id = of_match_device(wm831x_of_match, &i2c->dev); + if (!of_id) { + dev_err(&i2c->dev, "Failed to match device\n"); + return -ENODEV; + } type = (enum wm831x_parent)of_id->data; } else { type = (enum wm831x_parent)id->driver_data; diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index c332e2885b26..018ce652ae57 100644 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c @@ -34,6 +34,10 @@ static int wm831x_spi_probe(struct spi_device *spi) if (spi->dev.of_node) { of_id = of_match_device(wm831x_of_match, &spi->dev); + if (!of_id) { + dev_err(&spi->dev, "Failed to match device\n"); + return -ENODEV; + } type = (enum wm831x_parent)of_id->data; } else { type = (enum wm831x_parent)id->driver_data; |