1 /* drivers/adc/chips/rk28_adc.c
\r
3 * This program is free software; you can redistribute it and/or modify
\r
4 * it under the terms of the GNU General Public License as published by
\r
5 * the Free Software Foundation; either version 2 of the License.
\r
7 #include <linux/kernel.h>
\r
8 #include <linux/module.h>
\r
9 #include <linux/init.h>
\r
10 #include <linux/device.h>
\r
11 #include <linux/platform_device.h>
\r
12 #include <linux/err.h>
\r
13 #include <linux/clk.h>
\r
14 #include <linux/interrupt.h>
\r
15 #include <linux/io.h>
\r
16 #include <linux/adc.h>
\r
17 #include <linux/delay.h>
\r
20 #include "rk28_adc.h"
\r
24 struct rk28_adc_device {
\r
28 struct resource *ioarea;
\r
29 struct adc_host *adc;
\r
31 static void rk28_adc_start(struct adc_host *adc)
\r
33 struct rk28_adc_device *dev = adc_priv(adc);
\r
34 int chn = adc->cur->chn;
\r
36 writel(ADC_CTRL_IRQ_ENABLE|ADC_CTRL_POWER_UP|ADC_CTRL_START|ADC_CTRL_CH(chn),
\r
37 dev->regs + ADC_CTRL);
\r
39 static void rk28_adc_stop(struct adc_host *adc)
\r
41 struct rk28_adc_device *dev = adc_priv(adc);
\r
43 writel(ADC_CTRL_IRQ_STATUS, dev->regs + ADC_CTRL);
\r
45 static int rk28_adc_read(struct adc_host *adc)
\r
47 struct rk28_adc_device *dev = adc_priv(adc);
\r
49 udelay(SAMPLE_RATE);
\r
50 return readl(dev->regs + ADC_DATA) & ADC_DATA_MASK;
\r
52 static irqreturn_t rk28_adc_irq(int irq, void *data)
\r
54 struct rk28_adc_device *dev = data;
\r
55 adc_core_irq_handle(dev->adc);
\r
58 static const struct adc_ops rk28_adc_ops = {
\r
59 .start = rk28_adc_start,
\r
60 .stop = rk28_adc_stop,
\r
61 .read = rk28_adc_read,
\r
64 static void callback(struct adc_client *client, void *param, int result)
\r
66 dev_info(client->adc->dev, "[chn%d] async_read = %d\n", client->chn, result);
\r
69 static int rk28_adc_test(void)
\r
72 struct adc_client *client = adc_register(1, callback, NULL);
\r
76 adc_async_read(client);
\r
78 sync_read = adc_sync_read(client);
\r
79 dev_info(client->adc->dev, "[chn%d] sync_read = %d\n", client->chn, sync_read);
\r
82 adc_unregister(client);
\r
87 static int rk28_adc_probe(struct platform_device *pdev)
\r
89 struct adc_host *adc = NULL;
\r
90 struct rk28_adc_device *dev;
\r
91 struct resource *res;
\r
94 adc = adc_alloc_host(sizeof(struct rk28_adc_device), &pdev->dev);
\r
97 mutex_init(&adc->queue_mutex);
\r
98 adc->dev = &pdev->dev;
\r
99 adc->is_suspended = 0;
\r
100 adc->ops = &rk28_adc_ops;
\r
101 dev = adc_priv(adc);
\r
103 dev->irq = platform_get_irq(pdev, 0);
\r
104 if (dev->irq <= 0) {
\r
105 dev_err(&pdev->dev, "failed to get adc irq\n");
\r
110 ret = request_irq(dev->irq, rk28_adc_irq, 0, pdev->name, dev);
\r
112 dev_err(&pdev->dev, "failed to attach adc irq\n");
\r
115 dev->clk = clk_get(&pdev->dev, "saradc");
\r
116 if (IS_ERR(dev->clk)) {
\r
117 dev_err(&pdev->dev, "failed to get adc clock\n");
\r
118 ret = PTR_ERR(dev->clk);
\r
122 ret = clk_set_rate(dev->clk, ADC_CLK_RATE * 1000 * 1000);
\r
124 dev_err(&pdev->dev, "failed to set adc clk\n");
\r
127 clk_enable(dev->clk);
\r
129 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
\r
131 dev_err(&pdev->dev, "cannot find IO resource\n");
\r
135 dev->ioarea = request_mem_region(res->start, (res->end - res->start) + 1,
\r
137 if(dev->ioarea == NULL) {
\r
138 dev_err(&pdev->dev, "cannot request IO\n");
\r
142 dev->regs = ioremap(res->start, (res->end - res->start) + 1);
\r
144 dev_err(&pdev->dev, "cannot map IO\n");
\r
148 platform_set_drvdata(pdev, dev);
\r
149 dev_info(&pdev->dev, "rk28 adc: driver initialized\n");
\r
155 // iounmap(dev->regs);
\r
158 release_resource(dev->ioarea);
\r
159 kfree(dev->ioarea);
\r
160 clk_disable(dev->clk);
\r
166 free_irq(dev->irq, dev);
\r
169 adc_free_host(dev->adc);
\r
173 static int rk28_adc_remove(struct platform_device *pdev)
\r
175 struct rk28_adc_device *dev = platform_get_drvdata(pdev);
\r
177 iounmap(dev->regs);
\r
178 release_resource(dev->ioarea);
\r
179 kfree(dev->ioarea);
\r
180 free_irq(dev->irq, dev);
\r
181 clk_disable(dev->clk);
\r
183 adc_free_host(dev->adc);
\r
189 static int rk28_adc_suspend(struct platform_device *pdev, pm_message_t state)
\r
191 struct rk28_adc_device *dev = platform_get_drvdata(pdev);
\r
193 dev->adc->is_suspended = 1;
\r
197 static int rk28_adc_resume(struct platform_device *pdev)
\r
199 struct rk28_adc_device *dev = platform_get_drvdata(pdev);
\r
201 dev->adc->is_suspended = 0;
\r
206 #define rk28_adc_suspend NULL
\r
207 #define rk28_adc_resume NULL
\r
210 static struct platform_driver rk28_adc_driver = {
\r
212 .name = "rk28-adc",
\r
213 .owner = THIS_MODULE,
\r
215 .probe = rk28_adc_probe,
\r
216 .remove = __devexit_p(rk28_adc_remove),
\r
217 .suspend = rk28_adc_suspend,
\r
218 .resume = rk28_adc_resume,
\r
221 static int __init rk28_adc_init(void)
\r
223 return platform_driver_register(&rk28_adc_driver);
\r
225 subsys_initcall(rk28_adc_init);
\r
227 static void __exit rk28_adc_exit(void)
\r
229 platform_driver_unregister(&rk28_adc_driver);
\r
231 module_exit(rk28_adc_exit);
\r
233 MODULE_DESCRIPTION("Driver for ADC");
\r
234 MODULE_AUTHOR("kfx, kfx@rock-chips.com");
\r
235 MODULE_LICENSE("GPL");
\r