diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-01-22 09:16:02 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-01-22 09:16:02 -0800 |
commit | 909fd2b89f2edab8ec440a67dcf8627614e272b6 (patch) | |
tree | cc6448fc44d00d9d4d5ba218b32ba4d17c98314d /drivers/mfd/syscon.c | |
parent | 38f5265ed2c468f43a3080e4f82abfe53d7ea0be (diff) | |
parent | 2816b0c949af89640b8dc05de53e650cbf1d55fb (diff) |
Merge tag 'mfd-next-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull mfd updates from Lee Jones:
- Fix race in device_node_get_regmap() using more extensive locking
- Remove unused platform driver support for syscon
- Allow syscon nodes to be registered without a "syscon" compatible
string
- Make `platform_data` pointer const in struct mfd_cell
- Revert support for multiple AXP PMICs to avoid regressions
- Increase SoundWire attach timeout and use gpiod_set_raw() for GPIO
operation
- Store the result from fault_log() for use by other sub-components
- Fix an invalid regmap-config max_register value
- Add another Gemini Lake ISA bridge PCI device ID
- Use devm_register_power_off_handler() to simplify code
- Add support for QNAP microcontroller units, including LEDs, input,
and hwmon
- Use MFD_CELL macros and remove unused code
- Add support for AAEON UP board FPGA
- Remove unused includes
- Fix various typos and compatibility issues in multiple bindings
- Add new bindings for rk3562 QoS, LED1202, and qcom,tcsr-ipq5424
- Convert several bindings to YAML schema
- Update sprd,sc2731 bindings to reference sprd,sc2731-efuse bindings
directly
- Fix rohm,bd71815 bindings by correcting resistor values and typos
- Documentation improvements:
- Add documentation for LED1202 and qnap-mcu-hwmon
- Adjust the file entry for the qnap-mcu header in MAINTAINERS
* tag 'mfd-next-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (35 commits)
MAINTAINERS: Adjust the file entry for the qnap-mcu header
dt-bindings: mfd: syscon: Fix ti,j784s4-acspcie-proxy-ctrl compatible
dt-bindings: mfd: syscon: Fix al,alpine-sysfabric-service compatible
Revert "mfd: axp20x: Allow multiple regulators"
dt-bindings: mfd: syscon: Add rk3562 QoS register compatible
mfd: syscon: Allow syscon nodes without a "syscon" compatible
mfd: syscon: Remove the platform driver support
mfd: syscon: Fix race in device_node_get_regmap()
dt-bindings: mfd: atmel: Convert to YAML schema
dt-bindings: mfd: atmel,at91sam9260: Convert to YAML schema
dt-bindings: mfd: sprd,sc2731: Reference sprd,sc2731-efuse bindings
mfd: tps65219: Remove unused macros & add regmap.h
mfd: tps65219: Use MFD_CELL macros
leds: Add LED1202 I2C driver
dt-bindings: leds: Add LED1202 LED Controller
Documentation:leds: Add leds-st1202.rst
mfd: Add support for AAEON UP board FPGA
mfd: da9052: Store result from fault_log
mfd: intel_soc_pmic_chtdc_ti: Fix invalid regmap-config max_register value
mfd: cs42l43: Use devres for remove as well
...
Diffstat (limited to 'drivers/mfd/syscon.c')
-rw-r--r-- | drivers/mfd/syscon.c | 95 |
1 files changed, 15 insertions, 80 deletions
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 3e1d699ba934..226915ca3c93 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -12,22 +12,16 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/hwspinlock.h> -#include <linux/io.h> -#include <linux/init.h> #include <linux/list.h> +#include <linux/mutex.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_platform.h> -#include <linux/platform_data/syscon.h> -#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/reset.h> #include <linux/mfd/syscon.h> #include <linux/slab.h> -static struct platform_driver syscon_driver; - -static DEFINE_SPINLOCK(syscon_list_slock); +static DEFINE_MUTEX(syscon_list_lock); static LIST_HEAD(syscon_list); struct syscon { @@ -54,6 +48,8 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res) struct resource res; struct reset_control *reset; + WARN_ON(!mutex_is_locked(&syscon_list_lock)); + struct syscon *syscon __free(kfree) = kzalloc(sizeof(*syscon), GFP_KERNEL); if (!syscon) return ERR_PTR(-ENOMEM); @@ -146,9 +142,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res) syscon->regmap = regmap; syscon->np = np; - spin_lock(&syscon_list_slock); list_add_tail(&syscon->list, &syscon_list); - spin_unlock(&syscon_list_slock); return_ptr(syscon); @@ -169,7 +163,7 @@ static struct regmap *device_node_get_regmap(struct device_node *np, { struct syscon *entry, *syscon = NULL; - spin_lock(&syscon_list_slock); + mutex_lock(&syscon_list_lock); list_for_each_entry(entry, &syscon_list, list) if (entry->np == np) { @@ -177,10 +171,13 @@ static struct regmap *device_node_get_regmap(struct device_node *np, break; } - spin_unlock(&syscon_list_slock); - - if (!syscon) - syscon = of_syscon_register(np, check_res); + if (!syscon) { + if (of_device_is_compatible(np, "syscon")) + syscon = of_syscon_register(np, check_res); + else + syscon = ERR_PTR(-EINVAL); + } + mutex_unlock(&syscon_list_lock); if (IS_ERR(syscon)) return ERR_CAST(syscon); @@ -212,7 +209,7 @@ int of_syscon_register_regmap(struct device_node *np, struct regmap *regmap) return -ENOMEM; /* check if syscon entry already exists */ - spin_lock(&syscon_list_slock); + mutex_lock(&syscon_list_lock); list_for_each_entry(entry, &syscon_list, list) if (entry->np == np) { @@ -225,12 +222,12 @@ int of_syscon_register_regmap(struct device_node *np, struct regmap *regmap) /* register the regmap in syscon list */ list_add_tail(&syscon->list, &syscon_list); - spin_unlock(&syscon_list_slock); + mutex_unlock(&syscon_list_lock); return 0; err_unlock: - spin_unlock(&syscon_list_slock); + mutex_unlock(&syscon_list_lock); kfree(syscon); return ret; } @@ -244,9 +241,6 @@ EXPORT_SYMBOL_GPL(device_node_to_regmap); struct regmap *syscon_node_to_regmap(struct device_node *np) { - if (!of_device_is_compatible(np, "syscon")) - return ERR_PTR(-EINVAL); - return device_node_get_regmap(np, true); } EXPORT_SYMBOL_GPL(syscon_node_to_regmap); @@ -336,62 +330,3 @@ struct regmap *syscon_regmap_lookup_by_phandle_optional(struct device_node *np, return regmap; } EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_optional); - -static int syscon_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct syscon_platform_data *pdata = dev_get_platdata(dev); - struct syscon *syscon; - struct regmap_config syscon_config = syscon_regmap_config; - struct resource *res; - void __iomem *base; - - syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL); - if (!syscon) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - - base = devm_ioremap(dev, res->start, resource_size(res)); - if (!base) - return -ENOMEM; - - syscon_config.max_register = resource_size(res) - 4; - if (!syscon_config.max_register) - syscon_config.max_register_is_0 = true; - - if (pdata) - syscon_config.name = pdata->label; - syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_config); - if (IS_ERR(syscon->regmap)) { - dev_err(dev, "regmap init failed\n"); - return PTR_ERR(syscon->regmap); - } - - platform_set_drvdata(pdev, syscon); - - dev_dbg(dev, "regmap %pR registered\n", res); - - return 0; -} - -static const struct platform_device_id syscon_ids[] = { - { "syscon", }, - { } -}; - -static struct platform_driver syscon_driver = { - .driver = { - .name = "syscon", - }, - .probe = syscon_probe, - .id_table = syscon_ids, -}; - -static int __init syscon_init(void) -{ - return platform_driver_register(&syscon_driver); -} -postcore_initcall(syscon_init); |