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

mfd: Support multiple active WM831x AUXADC conversions

The WM831x AUXADC hardware can schedule multiple conversions at once,
allowing higher performance when more than one source is in use as we
can have the hardware start new conversions without having to wait for
a register write.

Take advantage of this in the interrupt driven case, maintaining a list of
callers that are waiting for AUXADC conversions and completing them all
simultaneously. The external interface of the AUXADC is not changed so
there will be limited use of the feature immediately.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Mark Brown and committed by
Samuel Ortiz
78bb3688 a2495bc7

+189 -80
+178 -78
drivers/mfd/wm831x-auxadc.c
··· 17 17 #include <linux/delay.h> 18 18 #include <linux/mfd/core.h> 19 19 #include <linux/slab.h> 20 + #include <linux/list.h> 20 21 21 22 #include <linux/mfd/wm831x/core.h> 22 23 #include <linux/mfd/wm831x/pdata.h> ··· 26 25 #include <linux/mfd/wm831x/otp.h> 27 26 #include <linux/mfd/wm831x/regulator.h> 28 27 29 - /** 30 - * wm831x_auxadc_read: Read a value from the WM831x AUXADC 31 - * 32 - * @wm831x: Device to read from. 33 - * @input: AUXADC input to read. 34 - */ 35 - int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) 36 - { 37 - int ret, src, irq_masked, timeout; 28 + struct wm831x_auxadc_req { 29 + struct list_head list; 30 + enum wm831x_auxadc input; 31 + int val; 32 + struct completion done; 33 + }; 38 34 39 - /* Are we using the interrupt? */ 40 - irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK); 41 - irq_masked &= WM831X_AUXADC_DATA_EINT; 35 + static int wm831x_auxadc_read_irq(struct wm831x *wm831x, 36 + enum wm831x_auxadc input) 37 + { 38 + struct wm831x_auxadc_req *req; 39 + int ret; 40 + bool ena = false; 41 + 42 + req = kzalloc(sizeof(*req), GFP_KERNEL); 43 + if (!req) 44 + return -ENOMEM; 45 + 46 + init_completion(&req->done); 47 + req->input = input; 48 + req->val = -ETIMEDOUT; 49 + 50 + mutex_lock(&wm831x->auxadc_lock); 51 + 52 + /* Enqueue the request */ 53 + list_add(&req->list, &wm831x->auxadc_pending); 54 + 55 + ena = !wm831x->auxadc_active; 56 + 57 + if (ena) { 58 + ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 59 + WM831X_AUX_ENA, WM831X_AUX_ENA); 60 + if (ret != 0) { 61 + dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", 62 + ret); 63 + goto out; 64 + } 65 + } 66 + 67 + /* Enable the conversion if not already running */ 68 + if (!(wm831x->auxadc_active & (1 << input))) { 69 + ret = wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE, 70 + 1 << input, 1 << input); 71 + if (ret != 0) { 72 + dev_err(wm831x->dev, 73 + "Failed to set AUXADC source: %d\n", ret); 74 + goto out; 75 + } 76 + 77 + wm831x->auxadc_active |= 1 << input; 78 + } 79 + 80 + /* We convert at the fastest rate possible */ 81 + if (ena) { 82 + ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 83 + WM831X_AUX_CVT_ENA | 84 + WM831X_AUX_RATE_MASK, 85 + WM831X_AUX_CVT_ENA | 86 + WM831X_AUX_RATE_MASK); 87 + if (ret != 0) { 88 + dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", 89 + ret); 90 + goto out; 91 + } 92 + } 93 + 94 + mutex_unlock(&wm831x->auxadc_lock); 95 + 96 + /* Wait for an interrupt */ 97 + wait_for_completion_timeout(&req->done, msecs_to_jiffies(500)); 98 + 99 + mutex_lock(&wm831x->auxadc_lock); 100 + 101 + list_del(&req->list); 102 + ret = req->val; 103 + 104 + out: 105 + mutex_unlock(&wm831x->auxadc_lock); 106 + 107 + kfree(req); 108 + 109 + return ret; 110 + } 111 + 112 + static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data) 113 + { 114 + struct wm831x *wm831x = irq_data; 115 + struct wm831x_auxadc_req *req; 116 + int ret, input, val; 117 + 118 + ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 119 + if (ret < 0) { 120 + dev_err(wm831x->dev, 121 + "Failed to read AUXADC data: %d\n", ret); 122 + return IRQ_NONE; 123 + } 124 + 125 + input = ((ret & WM831X_AUX_DATA_SRC_MASK) 126 + >> WM831X_AUX_DATA_SRC_SHIFT) - 1; 127 + 128 + if (input == 14) 129 + input = WM831X_AUX_CAL; 130 + 131 + val = ret & WM831X_AUX_DATA_MASK; 132 + 133 + mutex_lock(&wm831x->auxadc_lock); 134 + 135 + /* Disable this conversion, we're about to complete all users */ 136 + wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE, 137 + 1 << input, 0); 138 + wm831x->auxadc_active &= ~(1 << input); 139 + 140 + /* Turn off the entire convertor if idle */ 141 + if (!wm831x->auxadc_active) 142 + wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0); 143 + 144 + /* Wake up any threads waiting for this request */ 145 + list_for_each_entry(req, &wm831x->auxadc_pending, list) { 146 + if (req->input == input) { 147 + req->val = val; 148 + complete(&req->done); 149 + } 150 + } 151 + 152 + mutex_unlock(&wm831x->auxadc_lock); 153 + 154 + return IRQ_HANDLED; 155 + } 156 + 157 + static int wm831x_auxadc_read_polled(struct wm831x *wm831x, 158 + enum wm831x_auxadc input) 159 + { 160 + int ret, src, timeout; 42 161 43 162 mutex_lock(&wm831x->auxadc_lock); 44 163 ··· 178 57 goto out; 179 58 } 180 59 181 - /* Clear any notification from a very late arriving interrupt */ 182 - try_wait_for_completion(&wm831x->auxadc_done); 183 - 184 60 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 185 61 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA); 186 62 if (ret < 0) { ··· 185 67 goto disable; 186 68 } 187 69 188 - if (irq_masked) { 189 - /* If we're not using interrupts then poll the 190 - * interrupt status register */ 191 - timeout = 5; 192 - while (timeout) { 193 - msleep(1); 70 + /* If we're not using interrupts then poll the 71 + * interrupt status register */ 72 + timeout = 5; 73 + while (timeout) { 74 + msleep(1); 194 75 195 - ret = wm831x_reg_read(wm831x, 196 - WM831X_INTERRUPT_STATUS_1); 197 - if (ret < 0) { 198 - dev_err(wm831x->dev, 199 - "ISR 1 read failed: %d\n", ret); 200 - goto disable; 201 - } 202 - 203 - /* Did it complete? */ 204 - if (ret & WM831X_AUXADC_DATA_EINT) { 205 - wm831x_reg_write(wm831x, 206 - WM831X_INTERRUPT_STATUS_1, 207 - WM831X_AUXADC_DATA_EINT); 208 - break; 209 - } else { 210 - dev_err(wm831x->dev, 211 - "AUXADC conversion timeout\n"); 212 - ret = -EBUSY; 213 - goto disable; 214 - } 215 - } 216 - 217 - ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 76 + ret = wm831x_reg_read(wm831x, 77 + WM831X_INTERRUPT_STATUS_1); 218 78 if (ret < 0) { 219 79 dev_err(wm831x->dev, 220 - "Failed to read AUXADC data: %d\n", ret); 80 + "ISR 1 read failed: %d\n", ret); 221 81 goto disable; 222 82 } 223 83 224 - wm831x->auxadc_data = ret; 225 - 226 - } else { 227 - /* If we are using interrupts then wait for the 228 - * interrupt to complete. Use an extremely long 229 - * timeout to handle situations with heavy load where 230 - * the notification of the interrupt may be delayed by 231 - * threaded IRQ handling. */ 232 - if (!wait_for_completion_timeout(&wm831x->auxadc_done, 233 - msecs_to_jiffies(500))) { 234 - dev_err(wm831x->dev, "Timed out waiting for AUXADC\n"); 84 + /* Did it complete? */ 85 + if (ret & WM831X_AUXADC_DATA_EINT) { 86 + wm831x_reg_write(wm831x, 87 + WM831X_INTERRUPT_STATUS_1, 88 + WM831X_AUXADC_DATA_EINT); 89 + break; 90 + } else { 91 + dev_err(wm831x->dev, 92 + "AUXADC conversion timeout\n"); 235 93 ret = -EBUSY; 236 94 goto disable; 237 95 } 238 96 } 239 97 240 - src = ((wm831x->auxadc_data & WM831X_AUX_DATA_SRC_MASK) 98 + ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 99 + if (ret < 0) { 100 + dev_err(wm831x->dev, 101 + "Failed to read AUXADC data: %d\n", ret); 102 + goto disable; 103 + } 104 + 105 + src = ((ret & WM831X_AUX_DATA_SRC_MASK) 241 106 >> WM831X_AUX_DATA_SRC_SHIFT) - 1; 242 107 243 108 if (src == 14) ··· 231 130 src, input); 232 131 ret = -EINVAL; 233 132 } else { 234 - ret = wm831x->auxadc_data & WM831X_AUX_DATA_MASK; 133 + ret &= WM831X_AUX_DATA_MASK; 235 134 } 236 135 237 136 disable: ··· 240 139 mutex_unlock(&wm831x->auxadc_lock); 241 140 return ret; 242 141 } 243 - EXPORT_SYMBOL_GPL(wm831x_auxadc_read); 244 142 245 - static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data) 143 + /** 144 + * wm831x_auxadc_read: Read a value from the WM831x AUXADC 145 + * 146 + * @wm831x: Device to read from. 147 + * @input: AUXADC input to read. 148 + */ 149 + int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) 246 150 { 247 - struct wm831x *wm831x = irq_data; 248 - int ret; 249 - 250 - ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 251 - if (ret < 0) { 252 - dev_err(wm831x->dev, 253 - "Failed to read AUXADC data: %d\n", ret); 254 - wm831x->auxadc_data = 0xffff; 255 - } else { 256 - wm831x->auxadc_data = ret; 257 - } 258 - 259 - complete(&wm831x->auxadc_done); 260 - 261 - return IRQ_HANDLED; 151 + return wm831x->auxadc_read(wm831x, input); 262 152 } 153 + EXPORT_SYMBOL_GPL(wm831x_auxadc_read); 263 154 264 155 /** 265 156 * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC ··· 278 185 int ret; 279 186 280 187 mutex_init(&wm831x->auxadc_lock); 281 - init_completion(&wm831x->auxadc_done); 188 + INIT_LIST_HEAD(&wm831x->auxadc_pending); 282 189 283 - if (wm831x->irq_base) { 190 + if (wm831x->irq && wm831x->irq_base) { 191 + wm831x->auxadc_read = wm831x_auxadc_read_irq; 192 + 284 193 ret = request_threaded_irq(wm831x->irq_base + 285 194 WM831X_IRQ_AUXADC_DATA, 286 195 NULL, wm831x_auxadc_irq, 0, 287 196 "auxadc", wm831x); 288 - if (ret < 0) 197 + if (ret < 0) { 289 198 dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n", 290 199 ret); 200 + wm831x->auxadc_read = NULL; 201 + } 291 202 } 203 + 204 + if (!wm831x->auxadc_read) 205 + wm831x->auxadc_read = wm831x_auxadc_read_polled; 292 206 }
+11 -2
include/linux/mfd/wm831x/core.h
··· 17 17 18 18 #include <linux/completion.h> 19 19 #include <linux/interrupt.h> 20 + #include <linux/list.h> 20 21 21 22 /* 22 23 * Register values. ··· 250 249 WM8326 = 0x8326, 251 250 }; 252 251 252 + struct wm831x; 253 + enum wm831x_auxadc; 254 + 255 + typedef int (*wm831x_auxadc_read_fn)(struct wm831x *wm831x, 256 + enum wm831x_auxadc input); 257 + 253 258 struct wm831x { 254 259 struct mutex io_lock; 255 260 ··· 284 277 int gpio_update[WM831X_NUM_GPIO_REGS]; 285 278 286 279 struct mutex auxadc_lock; 287 - struct completion auxadc_done; 288 - u16 auxadc_data; 280 + struct list_head auxadc_pending; 281 + u16 auxadc_active; 282 + wm831x_auxadc_read_fn auxadc_read; 289 283 290 284 /* The WM831x has a security key blocking access to certain 291 285 * registers. The mutex is taken by the accessors for locking ··· 313 305 int wm831x_device_suspend(struct wm831x *wm831x); 314 306 int wm831x_irq_init(struct wm831x *wm831x, int irq); 315 307 void wm831x_irq_exit(struct wm831x *wm831x); 308 + void wm831x_auxadc_init(struct wm831x *wm831x); 316 309 317 310 #endif