diff options
Diffstat (limited to 'drivers/mux')
| -rw-r--r-- | drivers/mux/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/mux/adg792a.c | 2 | ||||
| -rw-r--r-- | drivers/mux/adgs1408.c | 4 | ||||
| -rw-r--r-- | drivers/mux/core.c | 9 | ||||
| -rw-r--r-- | drivers/mux/gpio.c | 9 | ||||
| -rw-r--r-- | drivers/mux/mmio.c | 97 |
6 files changed, 99 insertions, 23 deletions
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig index 80f015cf6e54..c68132e38138 100644 --- a/drivers/mux/Kconfig +++ b/drivers/mux/Kconfig @@ -48,6 +48,7 @@ config MUX_GPIO config MUX_MMIO tristate "MMIO/Regmap register bitfield-controlled Multiplexer" depends on OF + select REGMAP_MMIO help MMIO/Regmap register bitfield-controlled Multiplexer controller. diff --git a/drivers/mux/adg792a.c b/drivers/mux/adg792a.c index 4da5aecb9fc6..a5afe29e3cf1 100644 --- a/drivers/mux/adg792a.c +++ b/drivers/mux/adg792a.c @@ -141,7 +141,7 @@ MODULE_DEVICE_TABLE(of, adg792a_of_match); static struct i2c_driver adg792a_driver = { .driver = { .name = "adg792a", - .of_match_table = of_match_ptr(adg792a_of_match), + .of_match_table = adg792a_of_match, }, .probe = adg792a_probe, .id_table = adg792a_id, diff --git a/drivers/mux/adgs1408.c b/drivers/mux/adgs1408.c index 22ed051eb1a4..5eaf07d09ac9 100644 --- a/drivers/mux/adgs1408.c +++ b/drivers/mux/adgs1408.c @@ -59,9 +59,7 @@ static int adgs1408_probe(struct spi_device *spi) s32 idle_state; int ret; - chip_id = (enum adgs1408_chip_id)device_get_match_data(dev); - if (!chip_id) - chip_id = spi_get_device_id(spi)->driver_data; + chip_id = (kernel_ulong_t)spi_get_device_match_data(spi); mux_chip = devm_mux_chip_alloc(dev, 1, 0); if (IS_ERR(mux_chip)) diff --git a/drivers/mux/core.c b/drivers/mux/core.c index 78c0022697ec..a3840fe0995f 100644 --- a/drivers/mux/core.c +++ b/drivers/mux/core.c @@ -42,7 +42,7 @@ struct mux_state { unsigned int state; }; -static struct class mux_class = { +static const struct class mux_class = { .name = "mux", }; @@ -98,13 +98,12 @@ struct mux_chip *mux_chip_alloc(struct device *dev, if (WARN_ON(!dev || !controllers)) return ERR_PTR(-EINVAL); - mux_chip = kzalloc(sizeof(*mux_chip) + - controllers * sizeof(*mux_chip->mux) + - sizeof_priv, GFP_KERNEL); + mux_chip = kzalloc(size_add(struct_size(mux_chip, mux, controllers), + sizeof_priv), + GFP_KERNEL); if (!mux_chip) return ERR_PTR(-ENOMEM); - mux_chip->mux = (struct mux_control *)(mux_chip + 1); mux_chip->dev.class = &mux_class; mux_chip->dev.type = &mux_type; mux_chip->dev.parent = dev; diff --git a/drivers/mux/gpio.c b/drivers/mux/gpio.c index cc5f2c1861d4..4cc3202c58f3 100644 --- a/drivers/mux/gpio.c +++ b/drivers/mux/gpio.c @@ -15,6 +15,7 @@ #include <linux/mux/driver.h> #include <linux/platform_device.h> #include <linux/property.h> +#include <linux/regulator/consumer.h> struct mux_gpio { struct gpio_descs *gpios; @@ -28,9 +29,7 @@ static int mux_gpio_set(struct mux_control *mux, int state) bitmap_from_arr32(values, &value, BITS_PER_TYPE(value)); - gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs, - mux_gpio->gpios->desc, - mux_gpio->gpios->info, values); + gpiod_multi_set_value_cansleep(mux_gpio->gpios, values); return 0; } @@ -82,6 +81,10 @@ static int mux_gpio_probe(struct platform_device *pdev) mux_chip->mux->idle_state = idle_state; } + ret = devm_regulator_get_enable_optional(dev, "mux"); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to get/enable mux supply\n"); + ret = devm_mux_chip_register(dev, mux_chip); if (ret < 0) return ret; diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c index 30a952c34365..e4ddb1e61923 100644 --- a/drivers/mux/mmio.c +++ b/drivers/mux/mmio.c @@ -15,11 +15,25 @@ #include <linux/property.h> #include <linux/regmap.h> +struct mux_mmio { + struct regmap_field **fields; + unsigned int *hardware_states; +}; + +static int mux_mmio_get(struct mux_control *mux, int *state) +{ + struct mux_mmio *mux_mmio = mux_chip_priv(mux->chip); + unsigned int index = mux_control_get_index(mux); + + return regmap_field_read(mux_mmio->fields[index], state); +} + static int mux_mmio_set(struct mux_control *mux, int state) { - struct regmap_field **fields = mux_chip_priv(mux->chip); + struct mux_mmio *mux_mmio = mux_chip_priv(mux->chip); + unsigned int index = mux_control_get_index(mux); - return regmap_field_write(fields[mux_control_get_index(mux)], state); + return regmap_field_write(mux_mmio->fields[index], state); } static const struct mux_control_ops mux_mmio_ops = { @@ -33,13 +47,20 @@ static const struct of_device_id mux_mmio_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, mux_mmio_dt_ids); +static const struct regmap_config mux_mmio_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + static int mux_mmio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct regmap_field **fields; struct mux_chip *mux_chip; + struct mux_mmio *mux_mmio; struct regmap *regmap; + void __iomem *base; int num_fields; int ret; int i; @@ -47,7 +68,11 @@ static int mux_mmio_probe(struct platform_device *pdev) if (of_device_is_compatible(np, "mmio-mux")) { regmap = syscon_node_to_regmap(np->parent); } else { - regmap = device_node_to_regmap(np); + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + regmap = ERR_PTR(-ENODEV); + else + regmap = regmap_init_mmio(dev, base, &mux_mmio_regmap_cfg); /* Fallback to checking the parent node on "real" errors. */ if (IS_ERR(regmap) && regmap != ERR_PTR(-EPROBE_DEFER)) { regmap = dev_get_regmap(dev->parent, NULL); @@ -69,12 +94,20 @@ static int mux_mmio_probe(struct platform_device *pdev) } num_fields = ret / 2; - mux_chip = devm_mux_chip_alloc(dev, num_fields, num_fields * - sizeof(*fields)); + mux_chip = devm_mux_chip_alloc(dev, num_fields, sizeof(struct mux_mmio)); if (IS_ERR(mux_chip)) return PTR_ERR(mux_chip); - fields = mux_chip_priv(mux_chip); + mux_mmio = mux_chip_priv(mux_chip); + + mux_mmio->fields = devm_kmalloc(dev, num_fields * sizeof(*mux_mmio->fields), GFP_KERNEL); + if (IS_ERR(mux_mmio->fields)) + return PTR_ERR(mux_mmio->fields); + + mux_mmio->hardware_states = devm_kmalloc(dev, num_fields * + sizeof(*mux_mmio->hardware_states), GFP_KERNEL); + if (IS_ERR(mux_mmio->hardware_states)) + return PTR_ERR(mux_mmio->hardware_states); for (i = 0; i < num_fields; i++) { struct mux_control *mux = &mux_chip->mux[i]; @@ -104,10 +137,10 @@ static int mux_mmio_probe(struct platform_device *pdev) return -EINVAL; } - fields[i] = devm_regmap_field_alloc(dev, regmap, field); - if (IS_ERR(fields[i])) { - ret = PTR_ERR(fields[i]); - dev_err(dev, "bitfield %d: failed allocate: %d\n", + mux_mmio->fields[i] = devm_regmap_field_alloc(dev, regmap, field); + if (IS_ERR(mux_mmio->fields[i])) { + ret = PTR_ERR(mux_mmio->fields[i]); + dev_err(dev, "bitfield %d: failed to allocate: %d\n", i, ret); return ret; } @@ -130,13 +163,55 @@ static int mux_mmio_probe(struct platform_device *pdev) mux_chip->ops = &mux_mmio_ops; + dev_set_drvdata(dev, mux_chip); + return devm_mux_chip_register(dev, mux_chip); } +static int mux_mmio_suspend_noirq(struct device *dev) +{ + struct mux_chip *mux_chip = dev_get_drvdata(dev); + struct mux_mmio *mux_mmio = mux_chip_priv(mux_chip); + unsigned int state; + int ret, i; + + for (i = 0; i < mux_chip->controllers; i++) { + ret = mux_mmio_get(&mux_chip->mux[i], &state); + if (ret) { + dev_err(dev, "control %u: error saving mux: %d\n", i, ret); + return ret; + } + + mux_mmio->hardware_states[i] = state; + } + + return 0; +} + +static int mux_mmio_resume_noirq(struct device *dev) +{ + struct mux_chip *mux_chip = dev_get_drvdata(dev); + struct mux_mmio *mux_mmio = mux_chip_priv(mux_chip); + int ret, i; + + for (i = 0; i < mux_chip->controllers; i++) { + ret = mux_mmio_set(&mux_chip->mux[i], mux_mmio->hardware_states[i]); + if (ret) { + dev_err(dev, "control %u: error restoring mux: %d\n", i, ret); + return ret; + } + } + + return 0; +} + +static DEFINE_NOIRQ_DEV_PM_OPS(mux_mmio_pm_ops, mux_mmio_suspend_noirq, mux_mmio_resume_noirq); + static struct platform_driver mux_mmio_driver = { .driver = { .name = "mmio-mux", .of_match_table = mux_mmio_dt_ids, + .pm = pm_sleep_ptr(&mux_mmio_pm_ops), }, .probe = mux_mmio_probe, }; |
