1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * wm831x-auxadc.c -- AUXADC for Wolfson WM831x PMICs 4 * 5 * Copyright 2009-2011 Wolfson Microelectronics PLC. 6 * 7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/delay.h> 13 #include <linux/mfd/core.h> 14 #include <linux/slab.h> 15 #include <linux/list.h> 16 17 #include <linux/mfd/wm831x/core.h> 18 #include <linux/mfd/wm831x/pdata.h> 19 #include <linux/mfd/wm831x/irq.h> 20 #include <linux/mfd/wm831x/auxadc.h> 21 #include <linux/mfd/wm831x/otp.h> 22 #include <linux/mfd/wm831x/regulator.h> 23 24 struct wm831x_auxadc_req { 25 struct list_head list; 26 enum wm831x_auxadc input; 27 int val; 28 struct completion done; 29 }; 30 31 static int wm831x_auxadc_read_irq(struct wm831x *wm831x, 32 enum wm831x_auxadc input) 33 { 34 struct wm831x_auxadc_req *req; 35 int ret; 36 bool ena = false; 37 38 req = kzalloc(sizeof(*req), GFP_KERNEL); 39 if (!req) 40 return -ENOMEM; 41 42 init_completion(&req->done); 43 req->input = input; 44 req->val = -ETIMEDOUT; 45 46 mutex_lock(&wm831x->auxadc_lock); 47 48 /* Enqueue the request */ 49 list_add(&req->list, &wm831x->auxadc_pending); 50 51 ena = !wm831x->auxadc_active; 52 53 if (ena) { 54 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 55 WM831X_AUX_ENA, WM831X_AUX_ENA); 56 if (ret != 0) { 57 dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", 58 ret); 59 goto out; 60 } 61 } 62 63 /* Enable the conversion if not already running */ 64 if (!(wm831x->auxadc_active & (1 << input))) { 65 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE, 66 1 << input, 1 << input); 67 if (ret != 0) { 68 dev_err(wm831x->dev, 69 "Failed to set AUXADC source: %d\n", ret); 70 goto out; 71 } 72 73 wm831x->auxadc_active |= 1 << input; 74 } 75 76 /* We convert at the fastest rate possible */ 77 if (ena) { 78 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 79 WM831X_AUX_CVT_ENA | 80 WM831X_AUX_RATE_MASK, 81 WM831X_AUX_CVT_ENA | 82 WM831X_AUX_RATE_MASK); 83 if (ret != 0) { 84 dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", 85 ret); 86 goto out; 87 } 88 } 89 90 mutex_unlock(&wm831x->auxadc_lock); 91 92 /* Wait for an interrupt */ 93 wait_for_completion_timeout(&req->done, msecs_to_jiffies(500)); 94 95 mutex_lock(&wm831x->auxadc_lock); 96 ret = req->val; 97 98 out: 99 list_del(&req->list); 100 mutex_unlock(&wm831x->auxadc_lock); 101 102 kfree(req); 103 104 return ret; 105 } 106 107 static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data) 108 { 109 struct wm831x *wm831x = irq_data; 110 struct wm831x_auxadc_req *req; 111 int ret, input, val; 112 113 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 114 if (ret < 0) { 115 dev_err(wm831x->dev, 116 "Failed to read AUXADC data: %d\n", ret); 117 return IRQ_NONE; 118 } 119 120 input = ((ret & WM831X_AUX_DATA_SRC_MASK) 121 >> WM831X_AUX_DATA_SRC_SHIFT) - 1; 122 123 if (input == 14) 124 input = WM831X_AUX_CAL; 125 126 val = ret & WM831X_AUX_DATA_MASK; 127 128 mutex_lock(&wm831x->auxadc_lock); 129 130 /* Disable this conversion, we're about to complete all users */ 131 wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE, 132 1 << input, 0); 133 wm831x->auxadc_active &= ~(1 << input); 134 135 /* Turn off the entire convertor if idle */ 136 if (!wm831x->auxadc_active) 137 wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0); 138 139 /* Wake up any threads waiting for this request */ 140 list_for_each_entry(req, &wm831x->auxadc_pending, list) { 141 if (req->input == input) { 142 req->val = val; 143 complete(&req->done); 144 } 145 } 146 147 mutex_unlock(&wm831x->auxadc_lock); 148 149 return IRQ_HANDLED; 150 } 151 152 static int wm831x_auxadc_read_polled(struct wm831x *wm831x, 153 enum wm831x_auxadc input) 154 { 155 int ret, src; 156 157 mutex_lock(&wm831x->auxadc_lock); 158 159 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 160 WM831X_AUX_ENA, WM831X_AUX_ENA); 161 if (ret < 0) { 162 dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret); 163 goto out; 164 } 165 166 /* We force a single source at present */ 167 src = input; 168 ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE, 169 1 << src); 170 if (ret < 0) { 171 dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret); 172 goto out; 173 } 174 175 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 176 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA); 177 if (ret < 0) { 178 dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret); 179 goto disable; 180 } 181 182 /* If we're not using interrupts then read the interrupt status register */ 183 msleep(20); 184 185 ret = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1); 186 if (ret < 0) { 187 dev_err(wm831x->dev, 188 "ISR 1 read failed: %d\n", ret); 189 goto disable; 190 } 191 192 /* Did it complete? */ 193 if (ret & WM831X_AUXADC_DATA_EINT) { 194 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1, 195 WM831X_AUXADC_DATA_EINT); 196 } else { 197 dev_err(wm831x->dev, 198 "AUXADC conversion timeout\n"); 199 ret = -EBUSY; 200 goto disable; 201 } 202 203 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 204 if (ret < 0) { 205 dev_err(wm831x->dev, 206 "Failed to read AUXADC data: %d\n", ret); 207 goto disable; 208 } 209 210 src = ((ret & WM831X_AUX_DATA_SRC_MASK) 211 >> WM831X_AUX_DATA_SRC_SHIFT) - 1; 212 213 if (src == 14) 214 src = WM831X_AUX_CAL; 215 216 if (src != input) { 217 dev_err(wm831x->dev, "Data from source %d not %d\n", 218 src, input); 219 ret = -EINVAL; 220 } else { 221 ret &= WM831X_AUX_DATA_MASK; 222 } 223 224 disable: 225 wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0); 226 out: 227 mutex_unlock(&wm831x->auxadc_lock); 228 return ret; 229 } 230 231 /** 232 * wm831x_auxadc_read: Read a value from the WM831x AUXADC 233 * 234 * @wm831x: Device to read from. 235 * @input: AUXADC input to read. 236 */ 237 int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) 238 { 239 return wm831x->auxadc_read(wm831x, input); 240 } 241 EXPORT_SYMBOL_GPL(wm831x_auxadc_read); 242 243 /** 244 * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC 245 * 246 * @wm831x: Device to read from. 247 * @input: AUXADC input to read. 248 */ 249 int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input) 250 { 251 int ret; 252 253 ret = wm831x_auxadc_read(wm831x, input); 254 if (ret < 0) 255 return ret; 256 257 ret *= 1465; 258 259 return ret; 260 } 261 EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv); 262 263 void wm831x_auxadc_init(struct wm831x *wm831x) 264 { 265 int ret; 266 267 mutex_init(&wm831x->auxadc_lock); 268 INIT_LIST_HEAD(&wm831x->auxadc_pending); 269 270 if (wm831x->irq) { 271 wm831x->auxadc_read = wm831x_auxadc_read_irq; 272 273 ret = request_threaded_irq(wm831x_irq(wm831x, 274 WM831X_IRQ_AUXADC_DATA), 275 NULL, wm831x_auxadc_irq, 276 IRQF_ONESHOT, 277 "auxadc", wm831x); 278 if (ret < 0) { 279 dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n", 280 ret); 281 wm831x->auxadc_read = NULL; 282 } 283 } 284 285 if (!wm831x->auxadc_read) 286 wm831x->auxadc_read = wm831x_auxadc_read_polled; 287 } 288