diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-02 14:40:51 -1000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-02 14:40:51 -1000 |
commit | 27bc0782ef8ec26ed94b9fa16c75c11fdb3cd78b (patch) | |
tree | ffaaa95c5a435ef5f3afc234f32481feb12d0de2 /drivers | |
parent | edd8e84ae9514e93368f56c3715b11af52df6c3b (diff) | |
parent | 2b481822446e30943fb7c02744a7b49ebec0e696 (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')
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 |