Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mux: mmio: Add suspend and resume support

The status of each mux is read during suspend and stored in the private
memory of the mux_chip.
Then the state is restored during the resume.

Reviewed-by: Andrew Davis <afd@ti.com>
Signed-off-by: Thomas Richard (TI.com) <thomas.richard@bootlin.com>
Link: https://patch.msgid.link/20251013-mux-mmio-resume-support-v5-1-de9467ceb2b2@bootlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Thomas Richard (TI.com) and committed by
Greg Kroah-Hartman
4863cb2b f0fdaa4a

+73 -9
+73 -9
drivers/mux/mmio.c
··· 15 15 #include <linux/property.h> 16 16 #include <linux/regmap.h> 17 17 18 + struct mux_mmio { 19 + struct regmap_field **fields; 20 + unsigned int *hardware_states; 21 + }; 22 + 23 + static int mux_mmio_get(struct mux_control *mux, int *state) 24 + { 25 + struct mux_mmio *mux_mmio = mux_chip_priv(mux->chip); 26 + unsigned int index = mux_control_get_index(mux); 27 + 28 + return regmap_field_read(mux_mmio->fields[index], state); 29 + } 30 + 18 31 static int mux_mmio_set(struct mux_control *mux, int state) 19 32 { 20 - struct regmap_field **fields = mux_chip_priv(mux->chip); 33 + struct mux_mmio *mux_mmio = mux_chip_priv(mux->chip); 34 + unsigned int index = mux_control_get_index(mux); 21 35 22 - return regmap_field_write(fields[mux_control_get_index(mux)], state); 36 + return regmap_field_write(mux_mmio->fields[index], state); 23 37 } 24 38 25 39 static const struct mux_control_ops mux_mmio_ops = { ··· 57 43 { 58 44 struct device *dev = &pdev->dev; 59 45 struct device_node *np = dev->of_node; 60 - struct regmap_field **fields; 61 46 struct mux_chip *mux_chip; 47 + struct mux_mmio *mux_mmio; 62 48 struct regmap *regmap; 63 49 void __iomem *base; 64 50 int num_fields; ··· 94 80 } 95 81 num_fields = ret / 2; 96 82 97 - mux_chip = devm_mux_chip_alloc(dev, num_fields, num_fields * 98 - sizeof(*fields)); 83 + mux_chip = devm_mux_chip_alloc(dev, num_fields, sizeof(struct mux_mmio)); 99 84 if (IS_ERR(mux_chip)) 100 85 return PTR_ERR(mux_chip); 101 86 102 - fields = mux_chip_priv(mux_chip); 87 + mux_mmio = mux_chip_priv(mux_chip); 88 + 89 + mux_mmio->fields = devm_kmalloc(dev, num_fields * sizeof(*mux_mmio->fields), GFP_KERNEL); 90 + if (IS_ERR(mux_mmio->fields)) 91 + return PTR_ERR(mux_mmio->fields); 92 + 93 + mux_mmio->hardware_states = devm_kmalloc(dev, num_fields * 94 + sizeof(*mux_mmio->hardware_states), GFP_KERNEL); 95 + if (IS_ERR(mux_mmio->hardware_states)) 96 + return PTR_ERR(mux_mmio->hardware_states); 103 97 104 98 for (i = 0; i < num_fields; i++) { 105 99 struct mux_control *mux = &mux_chip->mux[i]; ··· 137 115 return -EINVAL; 138 116 } 139 117 140 - fields[i] = devm_regmap_field_alloc(dev, regmap, field); 141 - if (IS_ERR(fields[i])) { 142 - ret = PTR_ERR(fields[i]); 118 + mux_mmio->fields[i] = devm_regmap_field_alloc(dev, regmap, field); 119 + if (IS_ERR(mux_mmio->fields[i])) { 120 + ret = PTR_ERR(mux_mmio->fields[i]); 143 121 dev_err(dev, "bitfield %d: failed to allocate: %d\n", 144 122 i, ret); 145 123 return ret; ··· 163 141 164 142 mux_chip->ops = &mux_mmio_ops; 165 143 144 + dev_set_drvdata(dev, mux_chip); 145 + 166 146 return devm_mux_chip_register(dev, mux_chip); 167 147 } 148 + 149 + static int mux_mmio_suspend_noirq(struct device *dev) 150 + { 151 + struct mux_chip *mux_chip = dev_get_drvdata(dev); 152 + struct mux_mmio *mux_mmio = mux_chip_priv(mux_chip); 153 + unsigned int state; 154 + int ret, i; 155 + 156 + for (i = 0; i < mux_chip->controllers; i++) { 157 + ret = mux_mmio_get(&mux_chip->mux[i], &state); 158 + if (ret) { 159 + dev_err(dev, "control %u: error saving mux: %d\n", i, ret); 160 + return ret; 161 + } 162 + 163 + mux_mmio->hardware_states[i] = state; 164 + } 165 + 166 + return 0; 167 + } 168 + 169 + static int mux_mmio_resume_noirq(struct device *dev) 170 + { 171 + struct mux_chip *mux_chip = dev_get_drvdata(dev); 172 + struct mux_mmio *mux_mmio = mux_chip_priv(mux_chip); 173 + int ret, i; 174 + 175 + for (i = 0; i < mux_chip->controllers; i++) { 176 + ret = mux_mmio_set(&mux_chip->mux[i], mux_mmio->hardware_states[i]); 177 + if (ret) { 178 + dev_err(dev, "control %u: error restoring mux: %d\n", i, ret); 179 + return ret; 180 + } 181 + } 182 + 183 + return 0; 184 + } 185 + 186 + static DEFINE_NOIRQ_DEV_PM_OPS(mux_mmio_pm_ops, mux_mmio_suspend_noirq, mux_mmio_resume_noirq); 168 187 169 188 static struct platform_driver mux_mmio_driver = { 170 189 .driver = { 171 190 .name = "mmio-mux", 172 191 .of_match_table = mux_mmio_dt_ids, 192 + .pm = pm_sleep_ptr(&mux_mmio_pm_ops), 173 193 }, 174 194 .probe = mux_mmio_probe, 175 195 };