Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-1.0+
0002 //
0003 // Copyright (c) 2008 Simtec Electronics
0004 //  http://armlinux.simtec.co.uk/
0005 //  Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
0006 //
0007 // Samsung ADC device core
0008 
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mod_devicetable.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/sched.h>
0014 #include <linux/list.h>
0015 #include <linux/slab.h>
0016 #include <linux/err.h>
0017 #include <linux/clk.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/io.h>
0020 #include <linux/regulator/consumer.h>
0021 
0022 #include "regs-adc.h"
0023 #include <linux/soc/samsung/s3c-adc.h>
0024 
0025 /* This driver is designed to control the usage of the ADC block between
0026  * the touchscreen and any other drivers that may need to use it, such as
0027  * the hwmon driver.
0028  *
0029  * Priority will be given to the touchscreen driver, but as this itself is
0030  * rate limited it should not starve other requests which are processed in
0031  * order that they are received.
0032  *
0033  * Each user registers to get a client block which uniquely identifies it
0034  * and stores information such as the necessary functions to callback when
0035  * action is required.
0036  */
0037 
0038 enum s3c_cpu_type {
0039     TYPE_ADCV1, /* S3C24XX */
0040     TYPE_ADCV11, /* S3C2443 */
0041     TYPE_ADCV12, /* S3C2416, S3C2450 */
0042     TYPE_ADCV2, /* S3C64XX */
0043     TYPE_ADCV3, /* S5PV210, S5PC110, Exynos4210 */
0044 };
0045 
0046 struct s3c_adc_client {
0047     struct platform_device  *pdev;
0048     struct list_head     pend;
0049     wait_queue_head_t   *wait;
0050 
0051     unsigned int         nr_samples;
0052     int          result;
0053     unsigned char        is_ts;
0054     unsigned char        channel;
0055 
0056     void    (*select_cb)(struct s3c_adc_client *c, unsigned selected);
0057     void    (*convert_cb)(struct s3c_adc_client *c,
0058                   unsigned val1, unsigned val2,
0059                   unsigned *samples_left);
0060 };
0061 
0062 struct adc_device {
0063     struct platform_device  *pdev;
0064     struct platform_device  *owner;
0065     struct clk      *clk;
0066     struct s3c_adc_client   *cur;
0067     struct s3c_adc_client   *ts_pend;
0068     void __iomem        *regs;
0069     spinlock_t       lock;
0070 
0071     unsigned int         prescale;
0072 
0073     int          irq;
0074     struct regulator    *vdd;
0075 };
0076 
0077 static struct adc_device *adc_dev;
0078 
0079 static LIST_HEAD(adc_pending);  /* protected by adc_device.lock */
0080 
0081 #define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
0082 
0083 static inline void s3c_adc_convert(struct adc_device *adc)
0084 {
0085     unsigned con = readl(adc->regs + S3C2410_ADCCON);
0086 
0087     con |= S3C2410_ADCCON_ENABLE_START;
0088     writel(con, adc->regs + S3C2410_ADCCON);
0089 }
0090 
0091 static inline void s3c_adc_select(struct adc_device *adc,
0092                   struct s3c_adc_client *client)
0093 {
0094     unsigned con = readl(adc->regs + S3C2410_ADCCON);
0095     enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
0096 
0097     client->select_cb(client, 1);
0098 
0099     if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV2)
0100         con &= ~S3C2410_ADCCON_MUXMASK;
0101     con &= ~S3C2410_ADCCON_STDBM;
0102     con &= ~S3C2410_ADCCON_STARTMASK;
0103 
0104     if (!client->is_ts) {
0105         if (cpu == TYPE_ADCV3)
0106             writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
0107         else if (cpu == TYPE_ADCV11 || cpu == TYPE_ADCV12)
0108             writel(client->channel & 0xf,
0109                         adc->regs + S3C2443_ADCMUX);
0110         else
0111             con |= S3C2410_ADCCON_SELMUX(client->channel);
0112     }
0113 
0114     writel(con, adc->regs + S3C2410_ADCCON);
0115 }
0116 
0117 static void s3c_adc_dbgshow(struct adc_device *adc)
0118 {
0119     adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n",
0120         readl(adc->regs + S3C2410_ADCCON),
0121         readl(adc->regs + S3C2410_ADCTSC),
0122         readl(adc->regs + S3C2410_ADCDLY));
0123 }
0124 
0125 static void s3c_adc_try(struct adc_device *adc)
0126 {
0127     struct s3c_adc_client *next = adc->ts_pend;
0128 
0129     if (!next && !list_empty(&adc_pending)) {
0130         next = list_first_entry(&adc_pending,
0131                     struct s3c_adc_client, pend);
0132         list_del(&next->pend);
0133     } else
0134         adc->ts_pend = NULL;
0135 
0136     if (next) {
0137         adc_dbg(adc, "new client is %p\n", next);
0138         adc->cur = next;
0139         s3c_adc_select(adc, next);
0140         s3c_adc_convert(adc);
0141         s3c_adc_dbgshow(adc);
0142     }
0143 }
0144 
0145 int s3c_adc_start(struct s3c_adc_client *client,
0146           unsigned int channel, unsigned int nr_samples)
0147 {
0148     struct adc_device *adc = adc_dev;
0149     unsigned long flags;
0150 
0151     if (!adc) {
0152         printk(KERN_ERR "%s: failed to find adc\n", __func__);
0153         return -EINVAL;
0154     }
0155 
0156     spin_lock_irqsave(&adc->lock, flags);
0157 
0158     if (client->is_ts && adc->ts_pend) {
0159         spin_unlock_irqrestore(&adc->lock, flags);
0160         return -EAGAIN;
0161     }
0162 
0163     client->channel = channel;
0164     client->nr_samples = nr_samples;
0165 
0166     if (client->is_ts)
0167         adc->ts_pend = client;
0168     else
0169         list_add_tail(&client->pend, &adc_pending);
0170 
0171     if (!adc->cur)
0172         s3c_adc_try(adc);
0173 
0174     spin_unlock_irqrestore(&adc->lock, flags);
0175 
0176     return 0;
0177 }
0178 EXPORT_SYMBOL_GPL(s3c_adc_start);
0179 
0180 static void s3c_convert_done(struct s3c_adc_client *client,
0181                  unsigned v, unsigned u, unsigned *left)
0182 {
0183     client->result = v;
0184     wake_up(client->wait);
0185 }
0186 
0187 int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
0188 {
0189     DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
0190     int ret;
0191 
0192     client->convert_cb = s3c_convert_done;
0193     client->wait = &wake;
0194     client->result = -1;
0195 
0196     ret = s3c_adc_start(client, ch, 1);
0197     if (ret < 0)
0198         goto err;
0199 
0200     ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
0201     if (client->result < 0) {
0202         ret = -ETIMEDOUT;
0203         goto err;
0204     }
0205 
0206     client->convert_cb = NULL;
0207     return client->result;
0208 
0209 err:
0210     return ret;
0211 }
0212 EXPORT_SYMBOL_GPL(s3c_adc_read);
0213 
0214 static void s3c_adc_default_select(struct s3c_adc_client *client,
0215                    unsigned select)
0216 {
0217 }
0218 
0219 struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
0220                     void (*select)(struct s3c_adc_client *client,
0221                                unsigned int selected),
0222                     void (*conv)(struct s3c_adc_client *client,
0223                              unsigned d0, unsigned d1,
0224                              unsigned *samples_left),
0225                     unsigned int is_ts)
0226 {
0227     struct s3c_adc_client *client;
0228 
0229     WARN_ON(!pdev);
0230 
0231     if (!select)
0232         select = s3c_adc_default_select;
0233 
0234     if (!pdev)
0235         return ERR_PTR(-EINVAL);
0236 
0237     client = kzalloc(sizeof(*client), GFP_KERNEL);
0238     if (!client)
0239         return ERR_PTR(-ENOMEM);
0240 
0241     client->pdev = pdev;
0242     client->is_ts = is_ts;
0243     client->select_cb = select;
0244     client->convert_cb = conv;
0245 
0246     return client;
0247 }
0248 EXPORT_SYMBOL_GPL(s3c_adc_register);
0249 
0250 void s3c_adc_release(struct s3c_adc_client *client)
0251 {
0252     unsigned long flags;
0253 
0254     spin_lock_irqsave(&adc_dev->lock, flags);
0255 
0256     /* We should really check that nothing is in progress. */
0257     if (adc_dev->cur == client)
0258         adc_dev->cur = NULL;
0259     if (adc_dev->ts_pend == client)
0260         adc_dev->ts_pend = NULL;
0261     else {
0262         struct list_head *p, *n;
0263         struct s3c_adc_client *tmp;
0264 
0265         list_for_each_safe(p, n, &adc_pending) {
0266             tmp = list_entry(p, struct s3c_adc_client, pend);
0267             if (tmp == client)
0268                 list_del(&tmp->pend);
0269         }
0270     }
0271 
0272     if (adc_dev->cur == NULL)
0273         s3c_adc_try(adc_dev);
0274 
0275     spin_unlock_irqrestore(&adc_dev->lock, flags);
0276     kfree(client);
0277 }
0278 EXPORT_SYMBOL_GPL(s3c_adc_release);
0279 
0280 static irqreturn_t s3c_adc_irq(int irq, void *pw)
0281 {
0282     struct adc_device *adc = pw;
0283     struct s3c_adc_client *client = adc->cur;
0284     enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
0285     unsigned data0, data1;
0286 
0287     if (!client) {
0288         dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
0289         goto exit;
0290     }
0291 
0292     data0 = readl(adc->regs + S3C2410_ADCDAT0);
0293     data1 = readl(adc->regs + S3C2410_ADCDAT1);
0294     adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
0295 
0296     client->nr_samples--;
0297 
0298     if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV11) {
0299         data0 &= 0x3ff;
0300         data1 &= 0x3ff;
0301     } else {
0302         /* S3C2416/S3C64XX/S5P ADC resolution is 12-bit */
0303         data0 &= 0xfff;
0304         data1 &= 0xfff;
0305     }
0306 
0307     if (client->convert_cb)
0308         (client->convert_cb)(client, data0, data1, &client->nr_samples);
0309 
0310     if (client->nr_samples > 0) {
0311         /* fire another conversion for this */
0312 
0313         client->select_cb(client, 1);
0314         s3c_adc_convert(adc);
0315     } else {
0316         spin_lock(&adc->lock);
0317         (client->select_cb)(client, 0);
0318         adc->cur = NULL;
0319 
0320         s3c_adc_try(adc);
0321         spin_unlock(&adc->lock);
0322     }
0323 
0324 exit:
0325     if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3) {
0326         /* Clear ADC interrupt */
0327         writel(0, adc->regs + S3C64XX_ADCCLRINT);
0328     }
0329     return IRQ_HANDLED;
0330 }
0331 
0332 static int s3c_adc_probe(struct platform_device *pdev)
0333 {
0334     struct device *dev = &pdev->dev;
0335     struct adc_device *adc;
0336     enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
0337     int ret;
0338     unsigned tmp;
0339 
0340     adc = devm_kzalloc(dev, sizeof(*adc), GFP_KERNEL);
0341     if (!adc)
0342         return -ENOMEM;
0343 
0344     spin_lock_init(&adc->lock);
0345 
0346     adc->pdev = pdev;
0347     adc->prescale = S3C2410_ADCCON_PRSCVL(49);
0348 
0349     adc->vdd = devm_regulator_get(dev, "vdd");
0350     if (IS_ERR(adc->vdd)) {
0351         dev_err(dev, "operating without regulator \"vdd\" .\n");
0352         return PTR_ERR(adc->vdd);
0353     }
0354 
0355     adc->irq = platform_get_irq(pdev, 1);
0356     if (adc->irq <= 0)
0357         return -ENOENT;
0358 
0359     ret = devm_request_irq(dev, adc->irq, s3c_adc_irq, 0, dev_name(dev),
0360                 adc);
0361     if (ret < 0) {
0362         dev_err(dev, "failed to attach adc irq\n");
0363         return ret;
0364     }
0365 
0366     adc->clk = devm_clk_get(dev, "adc");
0367     if (IS_ERR(adc->clk)) {
0368         dev_err(dev, "failed to get adc clock\n");
0369         return PTR_ERR(adc->clk);
0370     }
0371 
0372     adc->regs = devm_platform_ioremap_resource(pdev, 0);
0373     if (IS_ERR(adc->regs))
0374         return PTR_ERR(adc->regs);
0375 
0376     ret = regulator_enable(adc->vdd);
0377     if (ret)
0378         return ret;
0379 
0380     clk_prepare_enable(adc->clk);
0381 
0382     tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
0383 
0384     /* Enable 12-bit ADC resolution */
0385     if (cpu == TYPE_ADCV12)
0386         tmp |= S3C2416_ADCCON_RESSEL;
0387     if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
0388         tmp |= S3C64XX_ADCCON_RESSEL;
0389 
0390     writel(tmp, adc->regs + S3C2410_ADCCON);
0391 
0392     dev_info(dev, "attached adc driver\n");
0393 
0394     platform_set_drvdata(pdev, adc);
0395     adc_dev = adc;
0396 
0397     return 0;
0398 }
0399 
0400 static int s3c_adc_remove(struct platform_device *pdev)
0401 {
0402     struct adc_device *adc = platform_get_drvdata(pdev);
0403 
0404     clk_disable_unprepare(adc->clk);
0405     regulator_disable(adc->vdd);
0406 
0407     return 0;
0408 }
0409 
0410 #ifdef CONFIG_PM
0411 static int s3c_adc_suspend(struct device *dev)
0412 {
0413     struct adc_device *adc = dev_get_drvdata(dev);
0414     unsigned long flags;
0415     u32 con;
0416 
0417     spin_lock_irqsave(&adc->lock, flags);
0418 
0419     con = readl(adc->regs + S3C2410_ADCCON);
0420     con |= S3C2410_ADCCON_STDBM;
0421     writel(con, adc->regs + S3C2410_ADCCON);
0422 
0423     disable_irq(adc->irq);
0424     spin_unlock_irqrestore(&adc->lock, flags);
0425     clk_disable(adc->clk);
0426     regulator_disable(adc->vdd);
0427 
0428     return 0;
0429 }
0430 
0431 static int s3c_adc_resume(struct device *dev)
0432 {
0433     struct platform_device *pdev = to_platform_device(dev);
0434     struct adc_device *adc = platform_get_drvdata(pdev);
0435     enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
0436     int ret;
0437     unsigned long tmp;
0438 
0439     ret = regulator_enable(adc->vdd);
0440     if (ret)
0441         return ret;
0442     clk_enable(adc->clk);
0443     enable_irq(adc->irq);
0444 
0445     tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
0446 
0447     /* Enable 12-bit ADC resolution */
0448     if (cpu == TYPE_ADCV12)
0449         tmp |= S3C2416_ADCCON_RESSEL;
0450     if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
0451         tmp |= S3C64XX_ADCCON_RESSEL;
0452 
0453     writel(tmp, adc->regs + S3C2410_ADCCON);
0454 
0455     return 0;
0456 }
0457 
0458 #else
0459 #define s3c_adc_suspend NULL
0460 #define s3c_adc_resume NULL
0461 #endif
0462 
0463 static const struct platform_device_id s3c_adc_driver_ids[] = {
0464     {
0465         .name           = "s3c24xx-adc",
0466         .driver_data    = TYPE_ADCV1,
0467     }, {
0468         .name       = "s3c2443-adc",
0469         .driver_data    = TYPE_ADCV11,
0470     }, {
0471         .name       = "s3c2416-adc",
0472         .driver_data    = TYPE_ADCV12,
0473     }, {
0474         .name           = "s3c64xx-adc",
0475         .driver_data    = TYPE_ADCV2,
0476     }, {
0477         .name       = "samsung-adc-v3",
0478         .driver_data    = TYPE_ADCV3,
0479     },
0480     { }
0481 };
0482 MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
0483 
0484 static const struct dev_pm_ops adc_pm_ops = {
0485     .suspend    = s3c_adc_suspend,
0486     .resume     = s3c_adc_resume,
0487 };
0488 
0489 static struct platform_driver s3c_adc_driver = {
0490     .id_table   = s3c_adc_driver_ids,
0491     .driver     = {
0492         .name   = "s3c-adc",
0493         .pm = &adc_pm_ops,
0494     },
0495     .probe      = s3c_adc_probe,
0496     .remove     = s3c_adc_remove,
0497 };
0498 
0499 static int __init adc_init(void)
0500 {
0501     int ret;
0502 
0503     ret = platform_driver_register(&s3c_adc_driver);
0504     if (ret)
0505         printk(KERN_ERR "%s: failed to add adc driver\n", __func__);
0506 
0507     return ret;
0508 }
0509 
0510 module_init(adc_init);