Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * wm831x-auxadc.c  --  AUXADC for Wolfson WM831x PMICs
0004  *
0005  * Copyright 2009-2011 Wolfson Microelectronics PLC.
0006  *
0007  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/delay.h>
0013 #include <linux/mfd/core.h>
0014 #include <linux/slab.h>
0015 #include <linux/list.h>
0016 
0017 #include <linux/mfd/wm831x/core.h>
0018 #include <linux/mfd/wm831x/pdata.h>
0019 #include <linux/mfd/wm831x/irq.h>
0020 #include <linux/mfd/wm831x/auxadc.h>
0021 #include <linux/mfd/wm831x/otp.h>
0022 #include <linux/mfd/wm831x/regulator.h>
0023 
0024 struct wm831x_auxadc_req {
0025     struct list_head list;
0026     enum wm831x_auxadc input;
0027     int val;
0028     struct completion done;
0029 };
0030 
0031 static int wm831x_auxadc_read_irq(struct wm831x *wm831x,
0032                   enum wm831x_auxadc input)
0033 {
0034     struct wm831x_auxadc_req *req;
0035     int ret;
0036     bool ena = false;
0037 
0038     req = kzalloc(sizeof(*req), GFP_KERNEL);
0039     if (!req)
0040         return -ENOMEM;
0041 
0042     init_completion(&req->done);
0043     req->input = input;
0044     req->val = -ETIMEDOUT;
0045 
0046     mutex_lock(&wm831x->auxadc_lock);
0047 
0048     /* Enqueue the request */
0049     list_add(&req->list, &wm831x->auxadc_pending);
0050 
0051     ena = !wm831x->auxadc_active;
0052 
0053     if (ena) {
0054         ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
0055                       WM831X_AUX_ENA, WM831X_AUX_ENA);
0056         if (ret != 0) {
0057             dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n",
0058                 ret);
0059             goto out;
0060         }
0061     }
0062 
0063     /* Enable the conversion if not already running */
0064     if (!(wm831x->auxadc_active & (1 << input))) {
0065         ret = wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
0066                       1 << input, 1 << input);
0067         if (ret != 0) {
0068             dev_err(wm831x->dev,
0069                 "Failed to set AUXADC source: %d\n", ret);
0070             goto out;
0071         }
0072 
0073         wm831x->auxadc_active |= 1 << input;
0074     }
0075 
0076     /* We convert at the fastest rate possible */
0077     if (ena) {
0078         ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
0079                       WM831X_AUX_CVT_ENA |
0080                       WM831X_AUX_RATE_MASK,
0081                       WM831X_AUX_CVT_ENA |
0082                       WM831X_AUX_RATE_MASK);
0083         if (ret != 0) {
0084             dev_err(wm831x->dev, "Failed to start AUXADC: %d\n",
0085                 ret);
0086             goto out;
0087         }
0088     }
0089 
0090     mutex_unlock(&wm831x->auxadc_lock);
0091 
0092     /* Wait for an interrupt */
0093     wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
0094 
0095     mutex_lock(&wm831x->auxadc_lock);
0096     ret = req->val;
0097 
0098 out:
0099     list_del(&req->list);
0100     mutex_unlock(&wm831x->auxadc_lock);
0101 
0102     kfree(req);
0103 
0104     return ret;
0105 }
0106 
0107 static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
0108 {
0109     struct wm831x *wm831x = irq_data;
0110     struct wm831x_auxadc_req *req;
0111     int ret, input, val;
0112 
0113     ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
0114     if (ret < 0) {
0115         dev_err(wm831x->dev,
0116             "Failed to read AUXADC data: %d\n", ret);
0117         return IRQ_NONE;
0118     }
0119 
0120     input = ((ret & WM831X_AUX_DATA_SRC_MASK)
0121          >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
0122 
0123     if (input == 14)
0124         input = WM831X_AUX_CAL;
0125 
0126     val = ret & WM831X_AUX_DATA_MASK;
0127 
0128     mutex_lock(&wm831x->auxadc_lock);
0129 
0130     /* Disable this conversion, we're about to complete all users */
0131     wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
0132             1 << input, 0);
0133     wm831x->auxadc_active &= ~(1 << input);
0134 
0135     /* Turn off the entire convertor if idle */
0136     if (!wm831x->auxadc_active)
0137         wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0);
0138 
0139     /* Wake up any threads waiting for this request */
0140     list_for_each_entry(req, &wm831x->auxadc_pending, list) {
0141         if (req->input == input) {
0142             req->val = val;
0143             complete(&req->done);
0144         }
0145     }
0146 
0147     mutex_unlock(&wm831x->auxadc_lock);
0148 
0149     return IRQ_HANDLED;
0150 }
0151 
0152 static int wm831x_auxadc_read_polled(struct wm831x *wm831x,
0153                      enum wm831x_auxadc input)
0154 {
0155     int ret, src, timeout;
0156 
0157     mutex_lock(&wm831x->auxadc_lock);
0158 
0159     ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
0160                   WM831X_AUX_ENA, WM831X_AUX_ENA);
0161     if (ret < 0) {
0162         dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
0163         goto out;
0164     }
0165 
0166     /* We force a single source at present */
0167     src = input;
0168     ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
0169                    1 << src);
0170     if (ret < 0) {
0171         dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
0172         goto out;
0173     }
0174 
0175     ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
0176                   WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
0177     if (ret < 0) {
0178         dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
0179         goto disable;
0180     }
0181 
0182     /* If we're not using interrupts then poll the
0183      * interrupt status register */
0184     timeout = 5;
0185     while (timeout) {
0186         msleep(1);
0187 
0188         ret = wm831x_reg_read(wm831x,
0189                       WM831X_INTERRUPT_STATUS_1);
0190         if (ret < 0) {
0191             dev_err(wm831x->dev,
0192                 "ISR 1 read failed: %d\n", ret);
0193             goto disable;
0194         }
0195 
0196         /* Did it complete? */
0197         if (ret & WM831X_AUXADC_DATA_EINT) {
0198             wm831x_reg_write(wm831x,
0199                      WM831X_INTERRUPT_STATUS_1,
0200                      WM831X_AUXADC_DATA_EINT);
0201             break;
0202         } else {
0203             dev_err(wm831x->dev,
0204                 "AUXADC conversion timeout\n");
0205             ret = -EBUSY;
0206             goto disable;
0207         }
0208     }
0209 
0210     ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
0211     if (ret < 0) {
0212         dev_err(wm831x->dev,
0213             "Failed to read AUXADC data: %d\n", ret);
0214         goto disable;
0215     }
0216 
0217     src = ((ret & WM831X_AUX_DATA_SRC_MASK)
0218            >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
0219 
0220     if (src == 14)
0221         src = WM831X_AUX_CAL;
0222 
0223     if (src != input) {
0224         dev_err(wm831x->dev, "Data from source %d not %d\n",
0225             src, input);
0226         ret = -EINVAL;
0227     } else {
0228         ret &= WM831X_AUX_DATA_MASK;
0229     }
0230 
0231 disable:
0232     wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
0233 out:
0234     mutex_unlock(&wm831x->auxadc_lock);
0235     return ret;
0236 }
0237 
0238 /**
0239  * wm831x_auxadc_read: Read a value from the WM831x AUXADC
0240  *
0241  * @wm831x: Device to read from.
0242  * @input: AUXADC input to read.
0243  */
0244 int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
0245 {
0246     return wm831x->auxadc_read(wm831x, input);
0247 }
0248 EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
0249 
0250 /**
0251  * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
0252  *
0253  * @wm831x: Device to read from.
0254  * @input: AUXADC input to read.
0255  */
0256 int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
0257 {
0258     int ret;
0259 
0260     ret = wm831x_auxadc_read(wm831x, input);
0261     if (ret < 0)
0262         return ret;
0263 
0264     ret *= 1465;
0265 
0266     return ret;
0267 }
0268 EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
0269 
0270 void wm831x_auxadc_init(struct wm831x *wm831x)
0271 {
0272     int ret;
0273 
0274     mutex_init(&wm831x->auxadc_lock);
0275     INIT_LIST_HEAD(&wm831x->auxadc_pending);
0276 
0277     if (wm831x->irq) {
0278         wm831x->auxadc_read = wm831x_auxadc_read_irq;
0279 
0280         ret = request_threaded_irq(wm831x_irq(wm831x,
0281                               WM831X_IRQ_AUXADC_DATA),
0282                        NULL, wm831x_auxadc_irq,
0283                        IRQF_ONESHOT,
0284                        "auxadc", wm831x);
0285         if (ret < 0) {
0286             dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
0287                 ret);
0288             wm831x->auxadc_read = NULL;
0289         }
0290     }
0291 
0292     if (!wm831x->auxadc_read)
0293         wm831x->auxadc_read = wm831x_auxadc_read_polled;
0294 }