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

Input: sun4i-lradc-keys - add optional clock/reset support

Until the R329, the LRADC hardware was always active. Now it requires
enabling a clock gate and deasserting a reset line. Add support for this
variant of the hardware.

Signed-off-by: Samuel Holland <samuel@sholland.org>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Link: https://lore.kernel.org/r/20220414002349.24332-2-samuel@sholland.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Samuel Holland and committed by
Dmitry Torokhov
ac2d5b43 61f19f67

+33
+33
drivers/input/keyboard/sun4i-lradc-keys.c
··· 14 14 * there are no boards known to use channel 1. 15 15 */ 16 16 17 + #include <linux/clk.h> 17 18 #include <linux/err.h> 18 19 #include <linux/init.h> 19 20 #include <linux/input.h> ··· 26 25 #include <linux/pm_wakeirq.h> 27 26 #include <linux/pm_wakeup.h> 28 27 #include <linux/regulator/consumer.h> 28 + #include <linux/reset.h> 29 29 #include <linux/slab.h> 30 30 31 31 #define LRADC_CTRL 0x00 ··· 62 60 /* struct lradc_variant - Describe sun4i-a10-lradc-keys hardware variant 63 61 * @divisor_numerator: The numerator of lradc Vref internally divisor 64 62 * @divisor_denominator: The denominator of lradc Vref internally divisor 63 + * @has_clock_reset: If the binding requires a clock and reset 65 64 */ 66 65 struct lradc_variant { 67 66 u8 divisor_numerator; 68 67 u8 divisor_denominator; 68 + bool has_clock_reset; 69 69 }; 70 70 71 71 static const struct lradc_variant lradc_variant_a10 = { ··· 89 85 struct device *dev; 90 86 struct input_dev *input; 91 87 void __iomem *base; 88 + struct clk *clk; 89 + struct reset_control *reset; 92 90 struct regulator *vref_supply; 93 91 struct sun4i_lradc_keymap *chan0_map; 94 92 const struct lradc_variant *variant; ··· 148 142 if (error) 149 143 return error; 150 144 145 + error = reset_control_deassert(lradc->reset); 146 + if (error) 147 + goto err_disable_reg; 148 + 149 + error = clk_prepare_enable(lradc->clk); 150 + if (error) 151 + goto err_assert_reset; 152 + 151 153 lradc->vref = regulator_get_voltage(lradc->vref_supply) * 152 154 lradc->variant->divisor_numerator / 153 155 lradc->variant->divisor_denominator; ··· 169 155 writel(CHAN0_KEYUP_IRQ | CHAN0_KEYDOWN_IRQ, lradc->base + LRADC_INTC); 170 156 171 157 return 0; 158 + 159 + err_assert_reset: 160 + reset_control_assert(lradc->reset); 161 + err_disable_reg: 162 + regulator_disable(lradc->vref_supply); 163 + 164 + return error; 172 165 } 173 166 174 167 static void sun4i_lradc_close(struct input_dev *dev) ··· 187 166 SAMPLE_RATE(2), lradc->base + LRADC_CTRL); 188 167 writel(0, lradc->base + LRADC_INTC); 189 168 169 + clk_disable_unprepare(lradc->clk); 170 + reset_control_assert(lradc->reset); 190 171 regulator_disable(lradc->vref_supply); 191 172 } 192 173 ··· 265 242 if (!lradc->variant) { 266 243 dev_err(&pdev->dev, "Missing sun4i-a10-lradc-keys variant\n"); 267 244 return -EINVAL; 245 + } 246 + 247 + if (lradc->variant->has_clock_reset) { 248 + lradc->clk = devm_clk_get(dev, NULL); 249 + if (IS_ERR(lradc->clk)) 250 + return PTR_ERR(lradc->clk); 251 + 252 + lradc->reset = devm_reset_control_get_exclusive(dev, NULL); 253 + if (IS_ERR(lradc->reset)) 254 + return PTR_ERR(lradc->reset); 268 255 } 269 256 270 257 lradc->vref_supply = devm_regulator_get(dev, "vref");