summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-11-02 14:40:51 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2023-11-02 14:40:51 -1000
commit27bc0782ef8ec26ed94b9fa16c75c11fdb3cd78b (patch)
treeffaaa95c5a435ef5f3afc234f32481feb12d0de2 /drivers
parentedd8e84ae9514e93368f56c3715b11af52df6c3b (diff)
parent2b481822446e30943fb7c02744a7b49ebec0e696 (diff)
Merge tag 'mfd-next-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "Core Frameworks: - Allow all MFD Cell properties to be filled in dynamically at runtime - Skip disabled device nodes and continue to look for subsequent devices New Device Support: - Add support for Lunar Lake-M PCI to Intel LPSS PCI - Add support for Denverton to Intel ICH LPC New Functionality: - Add support for Clocks to Texas Instruments TWL* Core - Add support for Interrupts to STMicroelectronics STM32 Timers Fix-ups: - Convert to new devm-* (managed) power-off API - Remove superfluous code - Bunch of Device Tree additions, conversions and adaptions - Simplify obtaining resources (memory, device data) using unified API helpers - Trivial coding-style / spelling type clean-ups - Constify / staticify changes - Expand or edit on existing documentation - Convert some Regmap configurations to use the Maple Tree cache - Apply new __counted_by() annotation to several data structures containing flexible arrays - Replace strncpy() with strscpy() Bug Fixes: - Remove double put creating reference imbalances - Ensure headphone/lineout detection gets set when booting with ACPI" * tag 'mfd-next-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (73 commits) mfd: lpc_ich: Mark *_gpio_offsets data with const spmi: rename spmi device lookup helper spmi: document spmi_device_from_of() refcounting dt-bindings: mfd: armltd: Move Arm board syscon's to separate schema mfd: rk8xx: Add support for RK806 power off mfd: rk8xx: Add support for standard system-power-controller property dt-bindings: mfd: rk806: Allow system-power-controller property dt-bindings: mfd: rk8xx: Deprecate rockchip,system-power-controller dt-bindings: mfd: max8925: Convert to DT schema format mfd: Use i2c_get_match_data() in a selection of drivers mfd: Use device_get_match_data() in a bunch of drivers mfd: mc13xxx-spi/wm831x-spi: Use spi_get_device_match_data() mfd: motorola-cpcap: Drop unnecessary of_match_device() call mfd: arizona-spi: Set pdata.hpdet_channel for ACPI enumerated devs mfd: qcom-spmi-pmic: Switch to EXPORT_SYMBOL_GPL() mfd: qcom-spmi-pmic: Fix revid implementation mfd: qcom-spmi-pmic: Fix reference leaks in revid helper mfd: intel-m10-bmc: Change contact for ABI docs mfd: max8907: Convert to use maple tree register cache mfd: max77686: Convert to use maple tree register cache ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/i2c-core.h2
-rw-r--r--drivers/mfd/arizona-i2c.c11
-rw-r--r--drivers/mfd/arizona-spi.c3
-rw-r--r--drivers/mfd/atmel-hlcdc.c1
-rw-r--r--drivers/mfd/axp20x.c66
-rw-r--r--drivers/mfd/db8500-prcmu.c4
-rw-r--r--drivers/mfd/dln2.c1
-rw-r--r--drivers/mfd/hi6421-pmic-core.c9
-rw-r--r--drivers/mfd/intel-lpss-pci.c13
-rw-r--r--drivers/mfd/iqs62x.c2
-rw-r--r--drivers/mfd/lochnagar-i2c.c9
-rw-r--r--drivers/mfd/lp87565.c9
-rw-r--r--drivers/mfd/lpc_ich.c127
-rw-r--r--drivers/mfd/madera-i2c.c9
-rw-r--r--drivers/mfd/max14577.c14
-rw-r--r--drivers/mfd/max77541.c6
-rw-r--r--drivers/mfd/max77620.c6
-rw-r--r--drivers/mfd/max77686.c2
-rw-r--r--drivers/mfd/max8907.c4
-rw-r--r--drivers/mfd/max8997.c12
-rw-r--r--drivers/mfd/max8998.c12
-rw-r--r--drivers/mfd/mc13xxx-spi.c14
-rw-r--r--drivers/mfd/mfd-core.c17
-rw-r--r--drivers/mfd/motorola-cpcap.c7
-rw-r--r--drivers/mfd/mxs-lradc.c9
-rw-r--r--drivers/mfd/palmas.c60
-rw-r--r--drivers/mfd/qcom-spmi-pmic.c109
-rw-r--r--drivers/mfd/qcom_rpm.c8
-rw-r--r--drivers/mfd/rk8xx-core.c7
-rw-r--r--drivers/mfd/rk8xx-i2c.c6
-rw-r--r--drivers/mfd/rn5t618.c11
-rw-r--r--drivers/mfd/stm32-timers.c46
-rw-r--r--drivers/mfd/tps65086.c2
-rw-r--r--drivers/mfd/tps65090.c2
-rw-r--r--drivers/mfd/tps65218.c2
-rw-r--r--drivers/mfd/tps6586x.c52
-rw-r--r--drivers/mfd/tps65910.c13
-rw-r--r--drivers/mfd/tps65912-core.c2
-rw-r--r--drivers/mfd/twl-core.c18
-rw-r--r--drivers/mfd/twl4030-power.c9
-rw-r--r--drivers/mfd/twl6030-irq.c10
-rw-r--r--drivers/mfd/wcd934x.c2
-rw-r--r--drivers/mfd/wm831x-i2c.c16
-rw-r--r--drivers/mfd/wm831x-spi.c16
-rw-r--r--drivers/mfd/wm8994-core.c11
-rw-r--r--drivers/spmi/spmi.c9
46 files changed, 443 insertions, 337 deletions
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index 1247e6e6e975..05b8b8dfa9bd 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -29,7 +29,7 @@ int i2c_dev_irq_from_resources(const struct resource *resources,
*/
static inline bool i2c_in_atomic_xfer_mode(void)
{
- return system_state > SYSTEM_RUNNING && irqs_disabled();
+ return system_state > SYSTEM_RUNNING && !preemptible();
}
static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index 9b7183ffc928..10e76fc8f12e 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -22,19 +22,12 @@
static int arizona_i2c_probe(struct i2c_client *i2c)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
- const void *match_data;
struct arizona *arizona;
const struct regmap_config *regmap_config = NULL;
- unsigned long type = 0;
+ unsigned long type;
int ret;
- match_data = device_get_match_data(&i2c->dev);
- if (match_data)
- type = (unsigned long)match_data;
- else if (id)
- type = id->driver_data;
-
+ type = (uintptr_t)i2c_get_match_data(i2c);
switch (type) {
case WM5102:
if (IS_ENABLED(CONFIG_MFD_WM5102))
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index 02cf4f3e91d7..de5d894ac04a 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -159,6 +159,9 @@ static int arizona_spi_acpi_probe(struct arizona *arizona)
arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
+ /* Use left headphone speaker for HP vs line-out detection */
+ arizona->pdata.hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
+
return 0;
}
diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c
index 20de7f49a830..4c4e35d404f3 100644
--- a/drivers/mfd/atmel-hlcdc.c
+++ b/drivers/mfd/atmel-hlcdc.c
@@ -139,6 +139,7 @@ static const struct of_device_id atmel_hlcdc_match[] = {
{ .compatible = "atmel,sama5d3-hlcdc" },
{ .compatible = "atmel,sama5d4-hlcdc" },
{ .compatible = "microchip,sam9x60-hlcdc" },
+ { .compatible = "microchip,sam9x75-xlcdc" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, atmel_hlcdc_match);
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 87603eeaa277..deaa969bab4e 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -22,7 +22,8 @@
#include <linux/mfd/axp20x.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/property.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -1131,25 +1132,10 @@ static int axp20x_power_off(struct sys_off_data *data)
int axp20x_match_device(struct axp20x_dev *axp20x)
{
struct device *dev = axp20x->dev;
- const struct acpi_device_id *acpi_id;
- const struct of_device_id *of_id;
-
- if (dev->of_node) {
- of_id = of_match_device(dev->driver->of_match_table, dev);
- if (!of_id) {
- dev_err(dev, "Unable to match OF ID\n");
- return -ENODEV;
- }
- axp20x->variant = (long)of_id->data;
- } else {
- acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!acpi_id || !acpi_id->driver_data) {
- dev_err(dev, "Unable to match ACPI ID and data\n");
- return -ENODEV;
- }
- axp20x->variant = (long)acpi_id->driver_data;
- }
+ const struct mfd_cell *cells_no_irq = NULL;
+ int nr_cells_no_irq = 0;
+ axp20x->variant = (long)device_get_match_data(dev);
switch (axp20x->variant) {
case AXP152_ID:
axp20x->nr_cells = ARRAY_SIZE(axp152_cells);
@@ -1207,14 +1193,15 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
* if there is no interrupt line.
*/
if (of_property_read_bool(axp20x->dev->of_node,
- "x-powers,self-working-mode") &&
- axp20x->irq > 0) {
+ "x-powers,self-working-mode")) {
axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells);
axp20x->cells = axp806_self_working_cells;
} else {
axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
axp20x->cells = axp806_cells;
}
+ nr_cells_no_irq = ARRAY_SIZE(axp806_cells);
+ cells_no_irq = axp806_cells;
axp20x->regmap_cfg = &axp806_regmap_config;
axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
break;
@@ -1238,24 +1225,8 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
break;
case AXP15060_ID:
- /*
- * Don't register the power key part if there is no interrupt
- * line.
- *
- * Since most use cases of AXP PMICs are Allwinner SOCs, board
- * designers follow Allwinner's reference design and connects
- * IRQ line to SOC, there's no need for those variants to deal
- * with cases that IRQ isn't connected. However, AXP15660 is
- * used by some other vendors' SOCs that didn't connect IRQ
- * line, we need to deal with this case.
- */
- if (axp20x->irq > 0) {
- axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
- axp20x->cells = axp15060_cells;
- } else {
- axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
- axp20x->cells = axp_regulator_only_cells;
- }
+ axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
+ axp20x->cells = axp15060_cells;
axp20x->regmap_cfg = &axp15060_regmap_config;
axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
break;
@@ -1263,6 +1234,23 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
return -EINVAL;
}
+
+ /*
+ * Use an alternative cell array when no interrupt line is connected,
+ * since IRQs are required by some drivers.
+ * The default is the safe "regulator-only", as this works fine without
+ * an interrupt specified.
+ */
+ if (axp20x->irq <= 0) {
+ if (cells_no_irq) {
+ axp20x->nr_cells = nr_cells_no_irq;
+ axp20x->cells = cells_no_irq;
+ } else {
+ axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
+ axp20x->cells = axp_regulator_only_cells;
+ }
+ }
+
dev_info(dev, "AXP20x variant %s found\n",
axp20x_model_names[axp20x->variant]);
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 27a881da4d6e..5b3e355e78f6 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2639,9 +2639,9 @@ static void dbx500_fw_version_init(struct device_node *np)
fw_info.version.api_version = (version >> 8) & 0xFF;
fw_info.version.func_version = (version >> 16) & 0xFF;
fw_info.version.errata = (version >> 24) & 0xFF;
- strncpy(fw_info.version.project_name,
+ strscpy(fw_info.version.project_name,
fw_project_name(fw_info.version.project),
- PRCMU_FW_PROJECT_NAME_LEN);
+ sizeof(fw_info.version.project_name));
fw_info.valid = true;
pr_info("PRCMU firmware: %s(%d), version %d.%d.%d\n",
fw_info.version.project_name,
diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
index c7510434380a..fbbe82c6e75b 100644
--- a/drivers/mfd/dln2.c
+++ b/drivers/mfd/dln2.c
@@ -826,7 +826,6 @@ out_stop_rx:
dln2_stop_rx_urbs(dln2);
out_free:
- usb_put_dev(dln2->usb_dev);
dln2_free(dln2);
return ret;
diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c
index a6a890537a1e..5af24a438329 100644
--- a/drivers/mfd/hi6421-pmic-core.c
+++ b/drivers/mfd/hi6421-pmic-core.c
@@ -15,8 +15,9 @@
#include <linux/mfd/core.h>
#include <linux/mfd/hi6421-pmic.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
static const struct mfd_cell hi6421_devs[] = {
@@ -50,16 +51,12 @@ MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match);
static int hi6421_pmic_probe(struct platform_device *pdev)
{
struct hi6421_pmic *pmic;
- const struct of_device_id *id;
const struct mfd_cell *subdevs;
enum hi6421_type type;
void __iomem *base;
int n_subdevs, ret;
- id = of_match_device(of_hi6421_pmic_match, &pdev->dev);
- if (!id)
- return -EINVAL;
- type = (uintptr_t)id->data;
+ type = (uintptr_t)device_get_match_data(&pdev->dev);
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index 699f44ffff0e..ae5759200622 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -561,6 +561,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa3e2), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa3e3), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa3e6), (kernel_ulong_t)&spt_uart_info },
+ /* LNL-M */
+ { PCI_VDEVICE(INTEL, 0xa825), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0xa826), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0xa827), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0xa830), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0xa846), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0xa850), (kernel_ulong_t)&ehl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa851), (kernel_ulong_t)&ehl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa852), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0xa878), (kernel_ulong_t)&ehl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa879), (kernel_ulong_t)&ehl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa87a), (kernel_ulong_t)&ehl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa87b), (kernel_ulong_t)&ehl_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids);
diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c
index e03b4d38fbb0..1b465590567c 100644
--- a/drivers/mfd/iqs62x.c
+++ b/drivers/mfd/iqs62x.c
@@ -96,7 +96,7 @@ struct iqs62x_fw_blk {
u8 addr;
u8 mask;
u8 len;
- u8 data[];
+ u8 data[] __counted_by(len);
};
struct iqs62x_info {
diff --git a/drivers/mfd/lochnagar-i2c.c b/drivers/mfd/lochnagar-i2c.c
index 59092f839d65..0b76fcccd0bd 100644
--- a/drivers/mfd/lochnagar-i2c.c
+++ b/drivers/mfd/lochnagar-i2c.c
@@ -15,8 +15,8 @@
#include <linux/i2c.h>
#include <linux/lockdep.h>
#include <linux/mfd/core.h>
+#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
-#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
@@ -270,7 +270,6 @@ static int lochnagar_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
const struct lochnagar_config *config = NULL;
- const struct of_device_id *of_id;
struct lochnagar *lochnagar;
struct gpio_desc *reset, *present;
unsigned int val;
@@ -282,11 +281,7 @@ static int lochnagar_i2c_probe(struct i2c_client *i2c)
if (!lochnagar)
return -ENOMEM;
- of_id = of_match_device(lochnagar_of_match, dev);
- if (!of_id)
- return -EINVAL;
-
- config = of_id->data;
+ config = i2c_get_match_data(i2c);
lochnagar->dev = dev;
mutex_init(&lochnagar->analogue_config_lock);
diff --git a/drivers/mfd/lp87565.c b/drivers/mfd/lp87565.c
index 1b7f8349911d..08c62ddfb4f5 100644
--- a/drivers/mfd/lp87565.c
+++ b/drivers/mfd/lp87565.c
@@ -6,10 +6,11 @@
*/
#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/mfd/lp87565.h>
@@ -46,7 +47,6 @@ MODULE_DEVICE_TABLE(of, of_lp87565_match_table);
static int lp87565_probe(struct i2c_client *client)
{
struct lp87565 *lp87565;
- const struct of_device_id *of_id;
int ret;
unsigned int otpid;
@@ -89,10 +89,7 @@ static int lp87565_probe(struct i2c_client *client)
}
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 = (uintptr_t)of_id->data;
+ lp87565->dev_type = (uintptr_t)i2c_get_match_data(client);
i2c_set_clientdata(client, lp87565);
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 7b1c597b6879..73a0e7f9bd31 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -85,19 +85,6 @@
#define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i)
#define wdt_res(b, i) (&wdt_ich_res[(b) + (i)])
-struct lpc_ich_priv {
- int chipset;
-
- int abase; /* ACPI base */
- int actrl_pbase; /* ACPI control or PMC base */
- int gbase; /* GPIO base */
- int gctrl; /* GPIO control */
-
- int abase_save; /* Cached ACPI base value */
- int actrl_pbase_save; /* Cached ACPI control or PMC base value */
- int gctrl_save; /* Cached GPIO control value */
-};
-
static struct resource wdt_ich_res[] = {
/* ACPI - TCO */
{
@@ -144,22 +131,33 @@ static struct mfd_cell lpc_ich_gpio_cell = {
.ignore_resource_conflicts = true,
};
+#define INTEL_GPIO_RESOURCE_SIZE 0x1000
+
+struct lpc_ich_gpio_info {
+ const char *hid;
+ const struct mfd_cell *devices;
+ size_t nr_devices;
+ struct resource **resources;
+ size_t nr_resources;
+ const resource_size_t *offsets;
+};
+
#define APL_GPIO_NORTH 0
#define APL_GPIO_NORTHWEST 1
#define APL_GPIO_WEST 2
#define APL_GPIO_SOUTHWEST 3
+
#define APL_GPIO_NR_DEVICES 4
+#define APL_GPIO_NR_RESOURCES 4
/* Offset data for Apollo Lake GPIO controllers */
-static resource_size_t apl_gpio_offsets[APL_GPIO_NR_DEVICES] = {
+static const resource_size_t apl_gpio_offsets[APL_GPIO_NR_RESOURCES] = {
[APL_GPIO_NORTH] = 0xc50000,
[APL_GPIO_NORTHWEST] = 0xc40000,
[APL_GPIO_WEST] = 0xc70000,
[APL_GPIO_SOUTHWEST] = 0xc00000,
};
-#define APL_GPIO_RESOURCE_SIZE 0x1000
-
#define APL_GPIO_IRQ 14
static struct resource apl_gpio_resources[APL_GPIO_NR_DEVICES][2] = {
@@ -181,6 +179,13 @@ static struct resource apl_gpio_resources[APL_GPIO_NR_DEVICES][2] = {
},
};
+static struct resource *apl_gpio_mem_resources[APL_GPIO_NR_RESOURCES] = {
+ [APL_GPIO_NORTH] = &apl_gpio_resources[APL_GPIO_NORTH][0],
+ [APL_GPIO_NORTHWEST] = &apl_gpio_resources[APL_GPIO_NORTHWEST][0],
+ [APL_GPIO_WEST] = &apl_gpio_resources[APL_GPIO_WEST][0],
+ [APL_GPIO_SOUTHWEST] = &apl_gpio_resources[APL_GPIO_SOUTHWEST][0],
+};
+
static const struct mfd_cell apl_gpio_devices[APL_GPIO_NR_DEVICES] = {
[APL_GPIO_NORTH] = {
.name = "apollolake-pinctrl",
@@ -212,6 +217,58 @@ static const struct mfd_cell apl_gpio_devices[APL_GPIO_NR_DEVICES] = {
},
};
+static const struct lpc_ich_gpio_info apl_gpio_info = {
+ .hid = "INT3452",
+ .devices = apl_gpio_devices,
+ .nr_devices = ARRAY_SIZE(apl_gpio_devices),
+ .resources = apl_gpio_mem_resources,
+ .nr_resources = ARRAY_SIZE(apl_gpio_mem_resources),
+ .offsets = apl_gpio_offsets,
+};
+
+#define DNV_GPIO_NORTH 0
+#define DNV_GPIO_SOUTH 1
+
+#define DNV_GPIO_NR_DEVICES 1
+#define DNV_GPIO_NR_RESOURCES 2
+
+/* Offset data for Denverton GPIO controllers */
+static const resource_size_t dnv_gpio_offsets[DNV_GPIO_NR_RESOURCES] = {
+ [DNV_GPIO_NORTH] = 0xc20000,
+ [DNV_GPIO_SOUTH] = 0xc50000,
+};
+
+#define DNV_GPIO_IRQ 14
+
+static struct resource dnv_gpio_resources[DNV_GPIO_NR_RESOURCES + 1] = {
+ [DNV_GPIO_NORTH] = DEFINE_RES_MEM(0, 0),
+ [DNV_GPIO_SOUTH] = DEFINE_RES_MEM(0, 0),
+ DEFINE_RES_IRQ(DNV_GPIO_IRQ),
+};
+
+static struct resource *dnv_gpio_mem_resources[DNV_GPIO_NR_RESOURCES] = {
+ [DNV_GPIO_NORTH] = &dnv_gpio_resources[DNV_GPIO_NORTH],
+ [DNV_GPIO_SOUTH] = &dnv_gpio_resources[DNV_GPIO_SOUTH],
+};
+
+static const struct mfd_cell dnv_gpio_devices[DNV_GPIO_NR_DEVICES] = {
+ {
+ .name = "denverton-pinctrl",
+ .num_resources = ARRAY_SIZE(dnv_gpio_resources),
+ .resources = dnv_gpio_resources,
+ .ignore_resource_conflicts = true,
+ },
+};
+
+static const struct lpc_ich_gpio_info dnv_gpio_info = {
+ .hid = "INTC3000",
+ .devices = dnv_gpio_devices,
+ .nr_devices = ARRAY_SIZE(dnv_gpio_devices),
+ .resources = dnv_gpio_mem_resources,
+ .nr_resources = ARRAY_SIZE(dnv_gpio_mem_resources),
+ .offsets = dnv_gpio_offsets,
+};
+
static struct mfd_cell lpc_ich_spi_cell = {
.name = "intel-spi",
.num_resources = ARRAY_SIZE(intel_spi_res),
@@ -289,10 +346,24 @@ enum lpc_chipsets {
LPC_LEWISBURG, /* Lewisburg */
LPC_9S, /* 9 Series */
LPC_APL, /* Apollo Lake SoC */
+ LPC_DNV, /* Denverton SoC */
LPC_GLK, /* Gemini Lake SoC */
LPC_COUGARMOUNTAIN,/* Cougar Mountain SoC*/
};
+struct lpc_ich_priv {
+ enum lpc_chipsets chipset;
+
+ int abase; /* ACPI base */
+ int actrl_pbase; /* ACPI control or PMC base */
+ int gbase; /* GPIO base */
+ int gctrl; /* GPIO control */
+
+ int abase_save; /* Cached ACPI base value */
+ int actrl_pbase_save; /* Cached ACPI control or PMC base value */
+ int gctrl_save; /* Cached GPIO control value */
+};
+
static struct lpc_ich_info lpc_chipset_info[] = {
[LPC_ICH] = {
.name = "ICH",
@@ -618,8 +689,13 @@ static struct lpc_ich_info lpc_chipset_info[] = {
[LPC_APL] = {
.name = "Apollo Lake SoC",
.iTCO_version = 5,
+ .gpio_info = &apl_gpio_info,
.spi_type = INTEL_SPI_BXT,
},
+ [LPC_DNV] = {
+ .name = "Denverton SoC",
+ .gpio_info = &dnv_gpio_info,
+ },
[LPC_GLK] = {
.name = "Gemini Lake SoC",
.spi_type = INTEL_SPI_BXT,
@@ -638,6 +714,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
*/
static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL},
+ { PCI_VDEVICE(INTEL, 0x19dc), LPC_DNV},
{ PCI_VDEVICE(INTEL, 0x1c41), LPC_CPT},
{ PCI_VDEVICE(INTEL, 0x1c42), LPC_CPTD},
{ PCI_VDEVICE(INTEL, 0x1c43), LPC_CPTM},
@@ -1156,30 +1233,32 @@ wdt_done:
static int lpc_ich_init_pinctrl(struct pci_dev *dev)
{
+ struct lpc_ich_priv *priv = pci_get_drvdata(dev);
+ const struct lpc_ich_gpio_info *info = lpc_chipset_info[priv->chipset].gpio_info;
struct resource base;
unsigned int i;
int ret;
/* Check, if GPIO has been exported as an ACPI device */
- if (acpi_dev_present("INT3452", NULL, -1))
+ if (acpi_dev_present(info->hid, NULL, -1))
return -EEXIST;
ret = p2sb_bar(dev->bus, 0, &base);
if (ret)
return ret;
- for (i = 0; i < ARRAY_SIZE(apl_gpio_devices); i++) {
- struct resource *mem = &apl_gpio_resources[i][0];
- resource_size_t offset = apl_gpio_offsets[i];
+ for (i = 0; i < info->nr_resources; i++) {
+ struct resource *mem = info->resources[i];
+ resource_size_t offset = info->offsets[i];
/* Fill MEM resource */
mem->start = base.start + offset;
- mem->end = base.start + offset + APL_GPIO_RESOURCE_SIZE - 1;
+ mem->end = base.start + offset + INTEL_GPIO_RESOURCE_SIZE - 1;
mem->flags = base.flags;
}
- return mfd_add_devices(&dev->dev, 0, apl_gpio_devices,
- ARRAY_SIZE(apl_gpio_devices), NULL, 0, NULL);
+ return mfd_add_devices(&dev->dev, 0, info->devices, info->nr_devices,
+ NULL, 0, NULL);
}
static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
@@ -1332,7 +1411,7 @@ static int lpc_ich_probe(struct pci_dev *dev,
cell_added = true;
}
- if (priv->chipset == LPC_APL) {
+ if (lpc_chipset_info[priv->chipset].gpio_info) {
ret = lpc_ich_init_pinctrl(dev);
if (!ret)
cell_added = true;
diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c
index a404ea26bc79..0986e4a99f4a 100644
--- a/drivers/mfd/madera-i2c.c
+++ b/drivers/mfd/madera-i2c.c
@@ -18,21 +18,14 @@
static int madera_i2c_probe(struct i2c_client *i2c)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
struct madera *madera;
const struct regmap_config *regmap_16bit_config = NULL;
const struct regmap_config *regmap_32bit_config = NULL;
- const void *of_data;
unsigned long type;
const char *name;
int ret;
- of_data = of_device_get_match_data(&i2c->dev);
- if (of_data)
- type = (unsigned long)of_data;
- else
- type = id->driver_data;
-
+ type = (uintptr_t)i2c_get_match_data(i2c);
switch (type) {
case CS47L15:
if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index 1f4f5002595c..8f7472c76009 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -9,9 +9,10 @@
// This driver is based on max8997.c
#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-#include <linux/of_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max14577.h>
#include <linux/mfd/max14577-private.h>
@@ -357,7 +358,6 @@ static void max77836_remove(struct max14577 *max14577)
static int max14577_i2c_probe(struct i2c_client *i2c)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
struct max14577 *max14577;
struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct device_node *np = i2c->dev.of_node;
@@ -397,15 +397,7 @@ static int max14577_i2c_probe(struct i2c_client *i2c)
return ret;
}
- if (np) {
- const struct of_device_id *of_id;
-
- of_id = of_match_device(max14577_dt_match, &i2c->dev);
- if (of_id)
- max14577->dev_type = (uintptr_t)of_id->data;
- } else {
- max14577->dev_type = id->driver_data;
- }
+ max14577->dev_type = (enum maxim_device_type)i2c_get_match_data(i2c);
max14577_print_dev_type(max14577);
diff --git a/drivers/mfd/max77541.c b/drivers/mfd/max77541.c
index 10c2e274b4af..d77c31c86e43 100644
--- a/drivers/mfd/max77541.c
+++ b/drivers/mfd/max77541.c
@@ -162,7 +162,6 @@ static int max77541_pmic_setup(struct device *dev)
static int max77541_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct max77541 *max77541;
@@ -173,10 +172,7 @@ static int max77541_probe(struct i2c_client *client)
i2c_set_clientdata(client, max77541);
max77541->i2c = client;
- max77541->id = (uintptr_t)device_get_match_data(dev);
- if (!max77541->id)
- max77541->id = (enum max7754x_ids)id->driver_data;
-
+ max77541->id = (uintptr_t)i2c_get_match_data(client);
if (!max77541->id)
return -EINVAL;
diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c
index e63e8e47d908..74ef3f6d576c 100644
--- a/drivers/mfd/max77620.c
+++ b/drivers/mfd/max77620.c
@@ -172,7 +172,7 @@ static const struct regmap_config max77620_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77620_REG_DVSSD4 + 1,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.rd_table = &max77620_readable_table,
.wr_table = &max77620_writable_table,
.volatile_table = &max77620_volatile_table,
@@ -184,7 +184,7 @@ static const struct regmap_config max20024_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX20024_REG_MAX_ADD + 1,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.rd_table = &max20024_readable_table,
.wr_table = &max77620_writable_table,
.volatile_table = &max77620_volatile_table,
@@ -213,7 +213,7 @@ static const struct regmap_config max77663_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77620_REG_CID5 + 1,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.rd_table = &max77663_readable_table,
.wr_table = &max77663_writable_table,
.volatile_table = &max77620_volatile_table,
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index 91c286c4571c..0118a444a68b 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -108,7 +108,7 @@ static const struct regmap_config max77802_regmap_config = {
.precious_reg = max77802_is_precious_reg,
.volatile_reg = max77802_is_volatile_reg,
.name = "max77802-pmic",
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static const struct regmap_irq max77686_irqs[] = {
diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index 8bbe7979db91..accf426234b6 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -63,7 +63,7 @@ static const struct regmap_config max8907_regmap_gen_config = {
.precious_reg = max8907_gen_is_precious_reg,
.writeable_reg = max8907_gen_is_writeable_reg,
.max_register = MAX8907_REG_LDO20VOUT,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static bool max8907_rtc_is_volatile_reg(struct device *dev, unsigned int reg)
@@ -108,7 +108,7 @@ static const struct regmap_config max8907_regmap_rtc_config = {
.precious_reg = max8907_rtc_is_precious_reg,
.writeable_reg = max8907_rtc_is_writeable_reg,
.max_register = MAX8907_REG_MPL_CNTL,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static const struct regmap_irq max8907_chg_irqs[] = {
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 110bef71f208..ffe96b40368e 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -142,18 +142,8 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
return pd;
}
-static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- if (i2c->dev.of_node)
- return (unsigned long)of_device_get_match_data(&i2c->dev);
-
- return id->driver_data;
-}
-
static int max8997_i2c_probe(struct i2c_client *i2c)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
struct max8997_dev *max8997;
struct max8997_platform_data *pdata = dev_get_platdata(&i2c->dev);
int ret = 0;
@@ -166,7 +156,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c)
i2c_set_clientdata(i2c, max8997);
max8997->dev = &i2c->dev;
max8997->i2c = i2c;
- max8997->type = max8997_i2c_get_driver_data(i2c, id);
+ max8997->type = (uintptr_t)i2c_get_match_data(i2c);
max8997->irq = i2c->irq;
if (IS_ENABLED(CONFIG_OF) && max8997->dev->of_node) {
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 4cc426a6c767..6ba27171da28 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -152,18 +152,8 @@ static struct max8998_platform_data *max8998_i2c_parse_dt_pdata(
return pd;
}
-static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- if (i2c->dev.of_node)
- return (unsigned long)of_device_get_match_data(&i2c->dev);
-
- return id->driver_data;
-}
-
static int max8998_i2c_probe(struct i2c_client *i2c)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
struct max8998_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct max8998_dev *max8998;
int ret = 0;
@@ -183,7 +173,7 @@ static int max8998_i2c_probe(struct i2c_client *i2c)
max8998->dev = &i2c->dev;
max8998->i2c = i2c;
max8998->irq = i2c->irq;
- max8998->type = max8998_i2c_get_driver_data(i2c, id);
+ max8998->type = (uintptr_t)i2c_get_match_data(i2c);
max8998->pdata = pdata;
if (pdata) {
max8998->ono = pdata->ono;
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index f70d79aa5a83..c973e2579bdf 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -8,13 +8,12 @@
*/
#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mc13xxx.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/err.h>
#include <linux/spi/spi.h>
@@ -151,16 +150,7 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
return ret;
}
- if (spi->dev.of_node) {
- const struct of_device_id *of_id =
- of_match_device(mc13xxx_dt_ids, &spi->dev);
-
- mc13xxx->variant = of_id->data;
- } else {
- const struct spi_device_id *id_entry = spi_get_device_id(spi);
-
- mc13xxx->variant = (void *)id_entry->driver_data;
- }
+ mc13xxx->variant = spi_get_device_match_data(spi);
return mc13xxx_common_init(&spi->dev);
}
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 0ed7c0d7784e..2b85509a90fc 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -146,6 +146,7 @@ static int mfd_add_device(struct device *parent, int id,
struct platform_device *pdev;
struct device_node *np = NULL;
struct mfd_of_node_entry *of_entry, *tmp;
+ bool disabled = false;
int ret = -ENOMEM;
int platform_id;
int r;
@@ -183,11 +184,10 @@ static int mfd_add_device(struct device *parent, int id,
if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) {
for_each_child_of_node(parent->of_node, np) {
if (of_device_is_compatible(np, cell->of_compatible)) {
- /* Ignore 'disabled' devices error free */
+ /* Skip 'disabled' devices */
if (!of_device_is_available(np)) {
- of_node_put(np);
- ret = 0;
- goto fail_alias;
+ disabled = true;
+ continue;
}
ret = mfd_match_of_node_to_dev(pdev, np, cell);
@@ -197,10 +197,17 @@ static int mfd_add_device(struct device *parent, int id,
if (ret)
goto fail_alias;
- break;
+ goto match;
}
}
+ if (disabled) {
+ /* Ignore 'disabled' devices error free */
+ ret = 0;
+ goto fail_alias;
+ }
+
+match:
if (!pdev->dev.of_node)
pr_warn("%s: Failed to locate of_node [id: %d]\n",
cell->name, platform_id);
diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
index a19691ba8d8b..d8243b956f87 100644
--- a/drivers/mfd/motorola-cpcap.c
+++ b/drivers/mfd/motorola-cpcap.c
@@ -11,7 +11,7 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
#include <linux/regmap.h>
#include <linux/sysfs.h>
@@ -290,14 +290,9 @@ static const struct mfd_cell cpcap_mfd_devices[] = {
static int cpcap_probe(struct spi_device *spi)
{
- const struct of_device_id *match;
struct cpcap_ddata *cpcap;
int ret;
- match = of_match_device(cpcap_of_match, &spi->dev);
- if (!match)
- return -ENODEV;
-
cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
if (!cpcap)
return -ENOMEM;
diff --git a/drivers/mfd/mxs-lradc.c b/drivers/mfd/mxs-lradc.c
index 21f3033d6eb5..ec1b356562b9 100644
--- a/drivers/mfd/mxs-lradc.c
+++ b/drivers/mfd/mxs-lradc.c
@@ -16,8 +16,8 @@
#include <linux/mfd/mxs-lradc.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#define ADC_CELL 0
@@ -125,7 +125,6 @@ MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
static int mxs_lradc_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id;
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct mxs_lradc *lradc;
@@ -138,11 +137,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
if (!lradc)
return -ENOMEM;
- of_id = of_match_device(mxs_lradc_dt_ids, &pdev->dev);
- if (!of_id)
- return -EINVAL;
-
- lradc->soc = (uintptr_t)of_id->data;
+ lradc->soc = (enum mxs_lradc_id)device_get_match_data(&pdev->dev);
lradc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(lradc->clk)) {
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index 6e562bab62e4..7fc886f4f80e 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -296,7 +296,7 @@ static const struct regmap_irq palmas_irqs[] = {
},
};
-static struct regmap_irq_chip palmas_irq_chip = {
+static const struct regmap_irq_chip palmas_irq_chip = {
.name = "palmas",
.irqs = palmas_irqs,
.num_irqs = ARRAY_SIZE(palmas_irqs),
@@ -309,7 +309,7 @@ static struct regmap_irq_chip palmas_irq_chip = {
PALMAS_INT1_MASK),
};
-static struct regmap_irq_chip tps65917_irq_chip = {
+static const struct regmap_irq_chip tps65917_irq_chip = {
.name = "tps65917",
.irqs = tps65917_irqs,
.num_irqs = ARRAY_SIZE(tps65917_irqs),
@@ -463,51 +463,29 @@ static void palmas_power_off(void)
__func__, ret);
}
-static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST;
-static unsigned int tps659038_features;
-
struct palmas_driver_data {
- unsigned int *features;
- struct regmap_irq_chip *irq_chip;
+ unsigned int features;
+ const struct regmap_irq_chip *irq_chip;
};
-static struct palmas_driver_data palmas_data = {
- .features = &palmas_features,
+static const struct palmas_driver_data palmas_data = {
+ .features = PALMAS_PMIC_FEATURE_SMPS10_BOOST,
.irq_chip = &palmas_irq_chip,
};
-static struct palmas_driver_data tps659038_data = {
- .features = &tps659038_features,
+static const struct palmas_driver_data tps659038_data = {
.irq_chip = &palmas_irq_chip,
};
-static struct palmas_driver_data tps65917_data = {
- .features = &tps659038_features,
+static const struct palmas_driver_data tps65917_data = {
.irq_chip = &tps65917_irq_chip,
};
-static const struct of_device_id of_palmas_match_tbl[] = {
- {
- .compatible = "ti,palmas",
- .data = &palmas_data,
- },
- {
- .compatible = "ti,tps659038",
- .data = &tps659038_data,
- },
- {
- .compatible = "ti,tps65917",
- .data = &tps65917_data,
- },
- { },
-};
-MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
-
static int palmas_i2c_probe(struct i2c_client *i2c)
{
struct palmas *palmas;
struct palmas_platform_data *pdata;
- struct palmas_driver_data *driver_data;
+ const struct palmas_driver_data *driver_data;
struct device_node *node = i2c->dev.of_node;
int ret = 0, i;
unsigned int reg, addr;
@@ -535,8 +513,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c)
palmas->dev = &i2c->dev;
palmas->irq = i2c->irq;
- driver_data = (struct palmas_driver_data *) device_get_match_data(&i2c->dev);
- palmas->features = *driver_data->features;
+ driver_data = i2c_get_match_data(i2c);
+ palmas->features = driver_data->features;
for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
if (i == 0)
@@ -712,11 +690,19 @@ static void palmas_i2c_remove(struct i2c_client *i2c)
}
}
+static const struct of_device_id of_palmas_match_tbl[] = {
+ { .compatible = "ti,palmas", .data = &palmas_data },
+ { .compatible = "ti,tps659038", .data = &tps659038_data },
+ { .compatible = "ti,tps65917", .data = &tps65917_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
+
static const struct i2c_device_id palmas_i2c_id[] = {
- { "palmas", },
- { "twl6035", },
- { "twl6037", },
- { "tps65913", },
+ { "palmas", (kernel_ulong_t)&palmas_data },
+ { "twl6035", (kernel_ulong_t)&palmas_data },
+ { "twl6037", (kernel_ulong_t)&palmas_data },
+ { "tps65913", (kernel_ulong_t)&palmas_data },
{ /* end */ }
};
MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c
index 7e2cd79d17eb..4549fa9f7d4b 100644
--- a/drivers/mfd/qcom-spmi-pmic.c
+++ b/drivers/mfd/qcom-spmi-pmic.c
@@ -8,10 +8,12 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
#include <linux/spmi.h>
#include <linux/types.h>
#include <linux/regmap.h>
-#include <linux/of_platform.h>
#include <soc/qcom/qcom-spmi-pmic.h>
#define PMIC_REV2 0x101
@@ -30,6 +32,8 @@ struct qcom_spmi_dev {
struct qcom_spmi_pmic pmic;
};
+static DEFINE_MUTEX(pmic_spmi_revid_lock);
+
#define N_USIDS(n) ((void *)n)
static const struct of_device_id pmic_spmi_id_table[] = {
@@ -76,24 +80,21 @@ static const struct of_device_id pmic_spmi_id_table[] = {
*
* This only supports PMICs with 1 or 2 USIDs.
*/
-static struct spmi_device *qcom_pmic_get_base_usid(struct device *dev)
+static struct spmi_device *qcom_pmic_get_base_usid(struct spmi_device *sdev, struct qcom_spmi_dev *ctx)
{
- struct spmi_device *sdev;
- struct qcom_spmi_dev *ctx;
struct device_node *spmi_bus;
- struct device_node *other_usid = NULL;
+ struct device_node *child;
int function_parent_usid, ret;
u32 pmic_addr;
- sdev = to_spmi_device(dev);
- ctx = dev_get_drvdata(&sdev->dev);
-
/*
* Quick return if the function device is already in the base
* USID. This will always be hit for PMICs with only 1 USID.
*/
- if (sdev->usid % ctx->num_usids == 0)
+ if (sdev->usid % ctx->num_usids == 0) {
+ get_device(&sdev->dev);
return sdev;
+ }
function_parent_usid = sdev->usid;
@@ -105,28 +106,61 @@ static struct spmi_device *qcom_pmic_get_base_usid(struct device *dev)
* device for USID 2.
*/
spmi_bus = of_get_parent(sdev->dev.of_node);
- do {
- other_usid = of_get_next_child(spmi_bus, other_usid);
-
- ret = of_property_read_u32_index(other_usid, "reg", 0, &pmic_addr);
- if (ret)
- return ERR_PTR(ret);
+ sdev = ERR_PTR(-ENODATA);
+ for_each_child_of_node(spmi_bus, child) {
+ ret = of_property_read_u32_index(child, "reg", 0, &pmic_addr);
+ if (ret) {
+ of_node_put(child);
+ sdev = ERR_PTR(ret);
+ break;
+ }
- sdev = spmi_device_from_of(other_usid);
if (pmic_addr == function_parent_usid - (ctx->num_usids - 1)) {
- if (!sdev)
+ sdev = spmi_find_device_by_of_node(child);
+ if (!sdev) {
/*
- * If the base USID for this PMIC hasn't probed yet
- * but the secondary USID has, then we need to defer
- * the function driver so that it will attempt to
- * probe again when the base USID is ready.
+ * If the base USID for this PMIC hasn't been
+ * registered yet then we need to defer.
*/
- return ERR_PTR(-EPROBE_DEFER);
- return sdev;
+ sdev = ERR_PTR(-EPROBE_DEFER);
+ }
+ of_node_put(child);
+ break;
}
- } while (other_usid->sibling);
+ }
- return ERR_PTR(-ENODATA);
+ of_node_put(spmi_bus);
+
+ return sdev;
+}
+
+static int pmic_spmi_get_base_revid(struct spmi_device *sdev, struct qcom_spmi_dev *ctx)
+{
+ struct qcom_spmi_dev *base_ctx;
+ struct spmi_device *base;
+ int ret = 0;
+
+ base = qcom_pmic_get_base_usid(sdev, ctx);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ /*
+ * Copy revid info from base device if it has probed and is still
+ * bound to its driver.
+ */
+ mutex_lock(&pmic_spmi_revid_lock);
+ base_ctx = spmi_device_get_drvdata(base);
+ if (!base_ctx) {
+ ret = -EPROBE_DEFER;
+ goto out_unlock;
+ }
+ memcpy(&ctx->pmic, &base_ctx->pmic, sizeof(ctx->pmic));
+out_unlock:
+ mutex_unlock(&pmic_spmi_revid_lock);
+
+ put_device(&base->dev);
+
+ return ret;
}
static int pmic_spmi_load_revid(struct regmap *map, struct device *dev,
@@ -204,16 +238,12 @@ const struct qcom_spmi_pmic *qcom_pmic_get(struct device *dev)
if (!of_match_device(pmic_spmi_id_table, dev->parent))
return ERR_PTR(-EINVAL);
- sdev = qcom_pmic_get_base_usid(dev->parent);
-
- if (IS_ERR(sdev))
- return ERR_CAST(sdev);
-
+ sdev = to_spmi_device(dev->parent);
spmi = dev_get_drvdata(&sdev->dev);
return &spmi->pmic;
}
-EXPORT_SYMBOL(qcom_pmic_get);
+EXPORT_SYMBOL_GPL(qcom_pmic_get);
static const struct regmap_config spmi_regmap_config = {
.reg_bits = 16,
@@ -236,23 +266,38 @@ static int pmic_spmi_probe(struct spmi_device *sdev)
if (!ctx)
return -ENOMEM;
- ctx->num_usids = (uintptr_t)of_device_get_match_data(&sdev->dev);
+ ctx->num_usids = (uintptr_t)device_get_match_data(&sdev->dev);
/* Only the first slave id for a PMIC contains this information */
if (sdev->usid % ctx->num_usids == 0) {
ret = pmic_spmi_load_revid(regmap, &sdev->dev, &ctx->pmic);
if (ret < 0)
return ret;
+ } else {
+ ret = pmic_spmi_get_base_revid(sdev, ctx);
+ if (ret)
+ return ret;
}
+
+ mutex_lock(&pmic_spmi_revid_lock);
spmi_device_set_drvdata(sdev, ctx);
+ mutex_unlock(&pmic_spmi_revid_lock);
return devm_of_platform_populate(&sdev->dev);
}
+static void pmic_spmi_remove(struct spmi_device *sdev)
+{
+ mutex_lock(&pmic_spmi_revid_lock);
+ spmi_device_set_drvdata(sdev, NULL);
+ mutex_unlock(&pmic_spmi_revid_lock);
+}
+
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/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 086611322874..27446f43e3f3 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -7,6 +7,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/io.h>
#include <linux/interrupt.h>
@@ -528,7 +530,6 @@ static irqreturn_t qcom_rpm_wakeup_interrupt(int irq, void *dev)
static int qcom_rpm_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
struct device_node *syscon_np;
struct qcom_rpm *rpm;
u32 fw_version[3];
@@ -570,10 +571,9 @@ static int qcom_rpm_probe(struct platform_device *pdev)
if (irq_wakeup < 0)
return irq_wakeup;
- match = of_match_device(qcom_rpm_of_match, &pdev->dev);
- if (!match)
+ rpm->data = device_get_match_data(&pdev->dev);
+ if (!rpm->data)
return -ENODEV;
- rpm->data = match->data;
rpm->status_regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(rpm->status_regs))
diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c
index 11a831e92da8..c47164a3ec1d 100644
--- a/drivers/mfd/rk8xx-core.c
+++ b/drivers/mfd/rk8xx-core.c
@@ -525,6 +525,10 @@ static int rk808_power_off(struct sys_off_data *data)
reg = RK805_DEV_CTRL_REG;
bit = DEV_OFF;
break;
+ case RK806_ID:
+ reg = RK806_SYS_CFG3;
+ bit = DEV_OFF;
+ break;
case RK808_ID:
reg = RK808_DEVCTRL_REG,
bit = DEV_OFF_RST;
@@ -685,7 +689,8 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
if (ret)
return dev_err_probe(dev, ret, "failed to add MFD devices\n");
- if (device_property_read_bool(dev, "rockchip,system-power-controller")) {
+ if (device_property_read_bool(dev, "rockchip,system-power-controller") ||
+ device_property_read_bool(dev, "system-power-controller")) {
ret = devm_register_sys_off_handler(dev,
SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,
&rk808_power_off, rk808);
diff --git a/drivers/mfd/rk8xx-i2c.c b/drivers/mfd/rk8xx-i2c.c
index 1a98feea97e2..75b5cf09d5a0 100644
--- a/drivers/mfd/rk8xx-i2c.c
+++ b/drivers/mfd/rk8xx-i2c.c
@@ -80,7 +80,7 @@ static const struct regmap_config rk818_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK818_USB_CTRL_REG,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = rk808_is_volatile_reg,
};
@@ -88,7 +88,7 @@ static const struct regmap_config rk805_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK805_OFF_SOURCE_REG,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = rk808_is_volatile_reg,
};
@@ -96,7 +96,7 @@ static const struct regmap_config rk808_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK808_IO_POL_REG,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = rk808_is_volatile_reg,
};
diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c
index 0fe616b2db8e..7336e6d8a001 100644
--- a/drivers/mfd/rn5t618.c
+++ b/drivers/mfd/rn5t618.c
@@ -13,7 +13,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/rn5t618.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
@@ -179,22 +179,15 @@ MODULE_DEVICE_TABLE(of, rn5t618_of_match);
static int rn5t618_i2c_probe(struct i2c_client *i2c)
{
- const struct of_device_id *of_id;
struct rn5t618 *priv;
int ret;
- of_id = of_match_device(rn5t618_of_match, &i2c->dev);
- if (!of_id) {
- dev_err(&i2c->dev, "Failed to find matching DT ID\n");
- return -EINVAL;
- }
-
priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
i2c_set_clientdata(i2c, priv);
- priv->variant = (long)of_id->data;
+ priv->variant = (long)i2c_get_match_data(i2c);
priv->irq = i2c->irq;
priv->dev = &i2c->dev;
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
index 732a28db80fa..a656a1c186a8 100644
--- a/drivers/mfd/stm32-timers.c
+++ b/drivers/mfd/stm32-timers.c
@@ -215,6 +215,48 @@ static void stm32_timers_dma_remove(struct device *dev,
dma_release_channel(ddata->dma.chans[i]);
}
+static const char * const stm32_timers_irq_name[STM32_TIMERS_MAX_IRQS] = {
+ "brk", "up", "trg-com", "cc"
+};
+
+static int stm32_timers_irq_probe(struct platform_device *pdev,
+ struct stm32_timers *ddata)
+{
+ int i, ret;
+
+ /*
+ * STM32 Timer may have either:
+ * - a unique global interrupt line
+ * - four dedicated interrupt lines that may be handled separately.
+ * Optionally get them here, to be used by child devices.
+ */
+ ret = platform_get_irq_byname_optional(pdev, "global");
+ if (ret < 0 && ret != -ENXIO) {
+ return ret;
+ } else if (ret != -ENXIO) {
+ ddata->irq[STM32_TIMERS_IRQ_GLOBAL_BRK] = ret;
+ ddata->nr_irqs = 1;
+ return 0;
+ }
+
+ for (i = 0; i < STM32_TIMERS_MAX_IRQS; i++) {
+ ret = platform_get_irq_byname_optional(pdev, stm32_timers_irq_name[i]);
+ if (ret < 0 && ret != -ENXIO) {
+ return ret;
+ } else if (ret != -ENXIO) {
+ ddata->irq[i] = ret;
+ ddata->nr_irqs++;
+ }
+ }
+
+ if (ddata->nr_irqs && ddata->nr_irqs != STM32_TIMERS_MAX_IRQS) {
+ dev_err(&pdev->dev, "Invalid number of IRQs %d\n", ddata->nr_irqs);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int stm32_timers_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -245,6 +287,10 @@ static int stm32_timers_probe(struct platform_device *pdev)
stm32_timers_get_arr_size(ddata);
+ ret = stm32_timers_irq_probe(pdev, ddata);
+ if (ret)
+ return ret;
+
ret = stm32_timers_dma_probe(dev, ddata);
if (ret) {
stm32_timers_dma_remove(dev, ddata);
diff --git a/drivers/mfd/tps65086.c b/drivers/mfd/tps65086.c
index 9bb7d7d8dcfc..152179ee11ca 100644
--- a/drivers/mfd/tps65086.c
+++ b/drivers/mfd/tps65086.c
@@ -34,7 +34,7 @@ static const struct regmap_access_table tps65086_volatile_table = {
static const struct regmap_config tps65086_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_table = &tps65086_volatile_table,
};
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index 9245e11219f3..b764badaa62a 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -151,7 +151,7 @@ static const struct regmap_config tps65090_regmap_config = {
.val_bits = 8,
.max_register = TPS65090_MAX_REG,
.num_reg_defaults_raw = TPS65090_NUM_REGS,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = is_volatile_reg,
};
diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
index 11e4e52b56be..427a2b97f117 100644
--- a/drivers/mfd/tps65218.c
+++ b/drivers/mfd/tps65218.c
@@ -127,7 +127,7 @@ static const struct regmap_access_table tps65218_volatile_table = {
static const struct regmap_config tps65218_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_table = &tps65218_volatile_table,
};
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 55675ceedcd3..03c65bbf2143 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -22,6 +22,7 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
+#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/of.h>
@@ -29,6 +30,7 @@
#include <linux/mfd/tps6586x.h>
#define TPS6586X_SUPPLYENE 0x14
+#define SOFT_RST_BIT BIT(0)
#define EXITSLREQ_BIT BIT(1)
#define SLEEP_MODE_BIT BIT(3)
@@ -454,16 +456,37 @@ static const struct regmap_config tps6586x_regmap_config = {
.val_bits = 8,
.max_register = TPS6586X_MAX_REGISTER,
.volatile_reg = is_volatile_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
-static struct device *tps6586x_dev;
-static void tps6586x_power_off(void)
+static int tps6586x_power_off_handler(struct sys_off_data *data)
{
- if (tps6586x_clr_bits(tps6586x_dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT))
- return;
+ int ret;
+
+ /* Put the PMIC into sleep state. This takes at least 20ms. */
+ ret = tps6586x_clr_bits(data->dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT);
+ if (ret)
+ return notifier_from_errno(ret);
+
+ ret = tps6586x_set_bits(data->dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+ if (ret)
+ return notifier_from_errno(ret);
+
+ mdelay(50);
+ return notifier_from_errno(-ETIME);
+}
+
+static int tps6586x_restart_handler(struct sys_off_data *data)
+{
+ int ret;
+
+ /* Put the PMIC into hard reboot state. This takes at least 20ms. */
+ ret = tps6586x_set_bits(data->dev, TPS6586X_SUPPLYENE, SOFT_RST_BIT);
+ if (ret)
+ return notifier_from_errno(ret);
- tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+ mdelay(50);
+ return notifier_from_errno(-ETIME);
}
static void tps6586x_print_version(struct i2c_client *client, int version)
@@ -559,9 +582,20 @@ static int tps6586x_i2c_probe(struct i2c_client *client)
goto err_add_devs;
}
- if (pdata->pm_off && !pm_power_off) {
- tps6586x_dev = &client->dev;
- pm_power_off = tps6586x_power_off;
+ if (pdata->pm_off) {
+ ret = devm_register_power_off_handler(&client->dev, &tps6586x_power_off_handler,
+ NULL);
+ if (ret) {
+ dev_err(&client->dev, "register power off handler failed: %d\n", ret);
+ goto err_add_devs;
+ }
+
+ ret = devm_register_restart_handler(&client->dev, &tps6586x_restart_handler,
+ NULL);
+ if (ret) {
+ dev_err(&client->dev, "register restart handler failed: %d\n", ret);
+ goto err_add_devs;
+ }
}
return 0;
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 41408df1712f..8fb0384d5a8e 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -19,7 +19,7 @@
#include <linux/regmap.h>
#include <linux/mfd/tps65910.h>
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/property.h>
static const struct resource rtc_resources[] = {
{
@@ -281,7 +281,7 @@ static const struct regmap_config tps65910_regmap_config = {
.val_bits = 8,
.volatile_reg = is_volatile_reg,
.max_register = TPS65910_MAX_REGISTER - 1,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int tps65910_ck32k_init(struct tps65910 *tps65910,
@@ -374,16 +374,9 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
struct device_node *np = client->dev.of_node;
struct tps65910_board *board_info;
unsigned int prop;
- const struct of_device_id *match;
int ret;
- match = of_match_device(tps65910_of_match, &client->dev);
- if (!match) {
- dev_err(&client->dev, "Failed to find matching dt id\n");
- return NULL;
- }
-
- *chip_id = (unsigned long)match->data;
+ *chip_id = (unsigned long)device_get_match_data(&client->dev);
board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
GFP_KERNEL);
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c
index 7d994b8a5965..2305ea60367a 100644
--- a/drivers/mfd/tps65912-core.c
+++ b/drivers/mfd/tps65912-core.c
@@ -81,7 +81,7 @@ static const struct regmap_access_table tps65912_volatile_table = {
const struct regmap_config tps65912_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_table = &tps65912_volatile_table,
};
EXPORT_SYMBOL_GPL(tps65912_regmap_config);
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index ce01a87f8dc3..6e384a79e341 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -31,6 +31,8 @@
#include <linux/regulator/machine.h>
#include <linux/i2c.h>
+
+#include <linux/mfd/core.h>
#include <linux/mfd/twl.h>
/* Register descriptions for audio */
@@ -312,7 +314,7 @@ static const struct regmap_config twl4030_regmap_config[4] = {
.reg_defaults = twl4030_49_defaults,
.num_reg_defaults = ARRAY_SIZE(twl4030_49_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
},
{
/* Address 0x4a */
@@ -690,6 +692,10 @@ static struct of_dev_auxdata twl_auxdata_lookup[] = {
{ /* sentinel */ },
};
+static const struct mfd_cell twl6032_cells[] = {
+ { .name = "twl6032-clk" },
+};
+
/* NOTE: This driver only handles a single twl4030/tps659x0 chip */
static int
twl_probe(struct i2c_client *client)
@@ -836,6 +842,16 @@ twl_probe(struct i2c_client *client)
TWL4030_DCDC_GLOBAL_CFG);
}
+ if (id->driver_data == (TWL6030_CLASS | TWL6032_SUBCLASS)) {
+ status = devm_mfd_add_devices(&client->dev,
+ PLATFORM_DEVID_NONE,
+ twl6032_cells,
+ ARRAY_SIZE(twl6032_cells),
+ NULL, 0, NULL);
+ if (status < 0)
+ goto free;
+ }
+
status = of_platform_populate(node, NULL, twl_auxdata_lookup,
&client->dev);
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index e35b0f788c50..1595e9c76132 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -27,8 +27,8 @@
#include <linux/pm.h>
#include <linux/mfd/twl.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <asm/mach-types.h>
@@ -883,7 +883,6 @@ static int twl4030_power_probe(struct platform_device *pdev)
{
const struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev);
struct device_node *node = pdev->dev.of_node;
- const struct of_device_id *match;
int err = 0;
int err2 = 0;
u8 val;
@@ -904,10 +903,8 @@ static int twl4030_power_probe(struct platform_device *pdev)
return err;
}
- match = of_match_device(of_match_ptr(twl4030_power_of_match),
- &pdev->dev);
- if (match && match->data)
- pdata = match->data;
+ if (node)
+ pdata = device_get_match_data(&pdev->dev);
if (pdata) {
err = twl4030_power_configure_scripts(pdata);
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 3c03681c124c..f9fce8408c2c 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -24,10 +24,10 @@
#include <linux/kthread.h>
#include <linux/mfd/twl.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/suspend.h>
#include <linux/of.h>
#include <linux/irqdomain.h>
-#include <linux/of_device.h>
#include "twl-core.h"
@@ -368,10 +368,10 @@ int twl6030_init_irq(struct device *dev, int irq_num)
int nr_irqs;
int status;
u8 mask[3];
- const struct of_device_id *of_id;
+ const int *irq_tbl;
- of_id = of_match_device(twl6030_of_match, dev);
- if (!of_id || !of_id->data) {
+ irq_tbl = device_get_match_data(dev);
+ if (!irq_tbl) {
dev_err(dev, "Unknown TWL device model\n");
return -EINVAL;
}
@@ -409,7 +409,7 @@ int twl6030_init_irq(struct device *dev, int irq_num)
twl6030_irq->pm_nb.notifier_call = twl6030_irq_pm_notifier;
atomic_set(&twl6030_irq->wakeirqs, 0);
- twl6030_irq->irq_mapping_tbl = of_id->data;
+ twl6030_irq->irq_mapping_tbl = irq_tbl;
twl6030_irq->irq_domain =
irq_domain_add_linear(node, nr_irqs,
diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c
index 6b942d5270c1..7b9873b72c37 100644
--- a/drivers/mfd/wcd934x.c
+++ b/drivers/mfd/wcd934x.c
@@ -112,7 +112,7 @@ static const struct regmap_range_cfg wcd934x_ranges[] = {
static struct regmap_config wcd934x_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = 0xffff,
.can_multi_write = true,
.ranges = wcd934x_ranges,
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
index 694ddbbf0372..9bee007f9c99 100644
--- a/drivers/mfd/wm831x-i2c.c
+++ b/drivers/mfd/wm831x-i2c.c
@@ -15,7 +15,6 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/mfd/wm831x/core.h>
@@ -23,22 +22,15 @@
static int wm831x_i2c_probe(struct i2c_client *i2c)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
struct wm831x_pdata *pdata = dev_get_platdata(&i2c->dev);
- const struct of_device_id *of_id;
struct wm831x *wm831x;
enum wm831x_parent type;
int ret;
- 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 = (uintptr_t)of_id->data;
- } else {
- type = (enum wm831x_parent)id->driver_data;
+ type = (uintptr_t)i2c_get_match_data(i2c);
+ if (!type) {
+ dev_err(&i2c->dev, "Failed to match device\n");
+ return -ENODEV;
}
wm831x = devm_kzalloc(&i2c->dev, sizeof(struct wm831x), GFP_KERNEL);
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 76be7ef5c970..54c87267917b 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -10,7 +10,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
@@ -21,21 +20,14 @@
static int wm831x_spi_probe(struct spi_device *spi)
{
struct wm831x_pdata *pdata = dev_get_platdata(&spi->dev);
- const struct spi_device_id *id = spi_get_device_id(spi);
- const struct of_device_id *of_id;
struct wm831x *wm831x;
enum wm831x_parent type;
int ret;
- 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 = (uintptr_t)of_id->data;
- } else {
- type = (enum wm831x_parent)id->driver_data;
+ type = (uintptr_t)spi_get_device_match_data(spi);
+ if (!type) {
+ dev_err(&spi->dev, "Failed to match device\n");
+ return -ENODEV;
}
wm831x = devm_kzalloc(&spi->dev, sizeof(struct wm831x), GFP_KERNEL);
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index aba7af688175..d5ac066f9db4 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -15,7 +15,6 @@
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -612,8 +611,6 @@ MODULE_DEVICE_TABLE(of, wm8994_of_match);
static int wm8994_i2c_probe(struct i2c_client *i2c)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
- const struct of_device_id *of_id;
struct wm8994 *wm8994;
int ret;
@@ -625,13 +622,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c)
wm8994->dev = &i2c->dev;
wm8994->irq = i2c->irq;
- if (i2c->dev.of_node) {
- of_id = of_match_device(wm8994_of_match, &i2c->dev);
- if (of_id)
- wm8994->type = (uintptr_t)of_id->data;
- } else {
- wm8994->type = id->driver_data;
- }
+ wm8994->type = (enum wm8994_type)i2c_get_match_data(i2c);
wm8994->regmap = devm_regmap_init_i2c(i2c, &wm8994_base_regmap_config);
if (IS_ERR(wm8994->regmap)) {
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 7313d4c18a04..93cd4a34debc 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -388,13 +388,16 @@ static struct bus_type spmi_bus_type = {
};
/**
- * spmi_device_from_of() - get the associated SPMI device from a device node
+ * spmi_find_device_by_of_node() - look up an SPMI device from a device node
*
* @np: device node
*
+ * Takes a reference to the embedded struct device which needs to be dropped
+ * after use.
+ *
* Returns the struct spmi_device associated with a device node or NULL.
*/
-struct spmi_device *spmi_device_from_of(struct device_node *np)
+struct spmi_device *spmi_find_device_by_of_node(struct device_node *np)
{
struct device *dev = bus_find_device_by_of_node(&spmi_bus_type, np);
@@ -402,7 +405,7 @@ struct spmi_device *spmi_device_from_of(struct device_node *np)
return to_spmi_device(dev);
return NULL;
}
-EXPORT_SYMBOL_GPL(spmi_device_from_of);
+EXPORT_SYMBOL_GPL(spmi_find_device_by_of_node);
/**
* spmi_device_alloc() - Allocate a new SPMI device