1 /* drivers/adc/chips/rk30_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/adc.h>
\r
9 #include "../adc_priv.h"
\r
10 #include "rk30_adc.h"
\r
13 #define SAMPLE_COUNT 10
\r
14 #define MIN_SAMPLE_VALUE 310
\r
15 struct rk30_adc_device {
\r
20 struct resource *ioarea;
\r
21 struct adc_host *adc;
\r
23 static void rk30_adc_dump(struct adc_host *adc)
\r
25 struct rk30_adc_device *dev = adc_priv(adc);
\r
27 dev_info(adc->dev, "[0x00-0x0c]: 0x%08x 0x%08x 0x%08x 0x%08x\n",
\r
28 adc_readl(dev->regs + 0x00),
\r
29 adc_readl(dev->regs + 0x04),
\r
30 adc_readl(dev->regs + 0x08),
\r
31 adc_readl(dev->regs + 0x0c));
\r
33 static void rk30_adc_start(struct adc_host *adc)
\r
35 struct rk30_adc_device *dev = adc_priv(adc);
\r
38 //adc_writel(0, dev->regs + ADC_CTRL);
\r
39 adc_writel(0x08, dev->regs + ADC_DELAY_PU_SOC);
\r
40 adc_writel(ADC_CTRL_POWER_UP|ADC_CTRL_CH(chn)|ADC_CTRL_IRQ_ENABLE, dev->regs + ADC_CTRL);
\r
44 static void rk30_adc_stop(struct adc_host *adc)
\r
46 struct rk30_adc_device *dev = adc_priv(adc);
\r
48 adc_writel(0, dev->regs + ADC_CTRL);
\r
50 static int rk30_adc_read(struct adc_host *adc)
\r
52 struct rk30_adc_device *dev = adc_priv(adc);
\r
54 return adc_readl(dev->regs + ADC_DATA) & ADC_DATA_MASK;
\r
56 static irqreturn_t rk30_adc_irq(int irq, void *data)
\r
58 struct rk30_adc_device *dev = data;
\r
60 adc_core_irq_handle(dev->adc);
\r
63 static const struct adc_ops rk30_adc_ops = {
\r
64 .start = rk30_adc_start,
\r
65 .stop = rk30_adc_stop,
\r
66 .read = rk30_adc_read,
\r
67 .dump = rk30_adc_dump,
\r
71 struct workqueue_struct *adc_wq;
\r
72 struct adc_test_data {
\r
73 struct adc_client *client;
\r
74 struct timer_list timer;
\r
75 struct work_struct timer_work;
\r
77 static void callback(struct adc_client *client, void *param, int result)
\r
79 dev_dbg(client->adc->dev, "[chn%d] async_read = %d\n", client->chn, result);
\r
82 static void adc_timer(unsigned long data)
\r
84 struct adc_test_data *test=(struct adc_test_data *)data;
\r
86 queue_work(adc_wq, &test->timer_work);
\r
87 mod_timer(&test->timer, jiffies+msecs_to_jiffies(20));
\r
89 static void adc_timer_work(struct work_struct *work)
\r
92 struct adc_test_data *test = container_of(work, struct adc_test_data,
\r
94 adc_async_read(test->client);
\r
95 sync_read = adc_sync_read(test->client);
\r
96 dev_dbg(test->client->adc->dev, "[chn%d] sync_read = %d\n", test->client->chn, sync_read);
\r
99 static int rk30_adc_test(void)
\r
102 struct adc_test_data *test[CHN_NR];
\r
104 adc_wq = create_singlethread_workqueue("adc_test");
\r
105 for(i = 0; i < CHN_NR; i++){
\r
106 test[i] = kzalloc(sizeof(struct adc_test_data), GFP_KERNEL);
\r
107 test[i]->client = adc_register(i, callback, NULL);
\r
108 INIT_WORK(&test[i]->timer_work, adc_timer_work);
\r
109 setup_timer(&test[i]->timer, adc_timer, (unsigned long)test[i]);
\r
110 mod_timer(&test[i]->timer, jiffies+msecs_to_jiffies(20));
\r
118 static int rk30_adc_probe(struct platform_device *pdev)
\r
120 struct adc_platform_data *pdata = pdev->dev.platform_data;
\r
121 struct adc_host *adc = NULL;
\r
122 struct rk30_adc_device *dev;
\r
123 struct resource *res;
\r
129 adc = adc_alloc_host(&pdev->dev, sizeof(struct rk30_adc_device), SARADC_CHN_MASK);
\r
132 adc->ops = &rk30_adc_ops;
\r
133 adc->pdata = pdata;
\r
134 dev = adc_priv(adc);
\r
136 dev->irq = platform_get_irq(pdev, 0);
\r
137 if (dev->irq <= 0) {
\r
138 dev_err(&pdev->dev, "failed to get adc irq\n");
\r
143 ret = request_threaded_irq(dev->irq, NULL, rk30_adc_irq, IRQF_ONESHOT, pdev->name, dev);
\r
145 dev_err(&pdev->dev, "failed to attach adc irq\n");
\r
149 dev->pclk = clk_get(&pdev->dev, "pclk_saradc");
\r
150 if (IS_ERR(dev->pclk)) {
\r
151 dev_err(&pdev->dev, "failed to get adc pclk\n");
\r
152 ret = PTR_ERR(dev->pclk);
\r
155 clk_enable(dev->pclk);
\r
157 dev->clk = clk_get(&pdev->dev, "saradc");
\r
158 if (IS_ERR(dev->clk)) {
\r
159 dev_err(&pdev->dev, "failed to get adc clock\n");
\r
160 ret = PTR_ERR(dev->clk);
\r
164 ret = clk_set_rate(dev->clk, ADC_CLK_RATE * 1000 * 1000);
\r
166 dev_err(&pdev->dev, "failed to set adc clk\n");
\r
169 clk_enable(dev->clk);
\r
171 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
\r
173 dev_err(&pdev->dev, "cannot find IO resource\n");
\r
177 dev->ioarea = request_mem_region(res->start, (res->end - res->start) + 1,
\r
179 if(dev->ioarea == NULL) {
\r
180 dev_err(&pdev->dev, "cannot request IO\n");
\r
184 dev->regs = ioremap(res->start, (res->end - res->start) + 1);
\r
186 dev_err(&pdev->dev, "cannot map IO\n");
\r
191 platform_set_drvdata(pdev, dev);
\r
193 if(adc->pdata->base_chn > 0){
\r
194 adc->base_client = adc_register(adc->pdata->base_chn, NULL, NULL);
\r
195 if(!adc->base_client){
\r
196 dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn);
\r
198 goto err_adc_register;
\r
200 for(i = 0; i < SAMPLE_COUNT; i++){
\r
201 v = adc_sync_read(adc->base_client);
\r
203 dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn);
\r
205 goto err_adc_sync_read;
\r
206 }else if(v < MIN_SAMPLE_VALUE){
\r
207 dev_info(&pdev->dev, "chn[%d]: adc value(%d) is invalide\n", adc->pdata->base_chn, v);
\r
208 adc_unregister(adc->base_client);
\r
209 adc->base_client = NULL;
\r
212 adc_dbg(&pdev->dev, "read ref_adc: %d\n", v);
\r
216 dev_info(&pdev->dev, "rk30 adc: driver initialized\n");
\r
219 adc_unregister(adc->base_client);
\r
220 adc->base_client = NULL;
\r
222 iounmap(dev->regs);
\r
224 release_resource(dev->ioarea);
\r
225 kfree(dev->ioarea);
\r
228 clk_disable(dev->clk);
\r
231 clk_disable(dev->pclk);
\r
232 clk_put(dev->pclk);
\r
238 free_irq(dev->irq, dev);
\r
241 adc_free_host(dev->adc);
\r
245 static int rk30_adc_remove(struct platform_device *pdev)
\r
247 struct rk30_adc_device *dev = platform_get_drvdata(pdev);
\r
249 if(dev->adc->base_client){
\r
250 adc_unregister(dev->adc->base_client);
\r
251 dev->adc->base_client = NULL;
\r
253 iounmap(dev->regs);
\r
254 release_resource(dev->ioarea);
\r
255 kfree(dev->ioarea);
\r
256 free_irq(dev->irq, dev);
\r
257 clk_disable(dev->clk);
\r
259 clk_disable(dev->pclk);
\r
260 clk_put(dev->pclk);
\r
261 adc_free_host(dev->adc);
\r
267 static int rk30_adc_suspend(struct platform_device *pdev, pm_message_t state)
\r
269 struct rk30_adc_device *dev = platform_get_drvdata(pdev);
\r
271 dev->adc->is_suspended = 1;
\r
275 static int rk30_adc_resume(struct platform_device *pdev)
\r
277 struct rk30_adc_device *dev = platform_get_drvdata(pdev);
\r
279 dev->adc->is_suspended = 0;
\r
284 #define rk30_adc_suspend NULL
\r
285 #define rk30_adc_resume NULL
\r
288 static struct platform_driver rk30_adc_driver = {
\r
290 .name = "rk30-adc",
\r
291 .owner = THIS_MODULE,
\r
293 .probe = rk30_adc_probe,
\r
294 .remove = __devexit_p(rk30_adc_remove),
\r
295 .suspend = rk30_adc_suspend,
\r
296 .resume = rk30_adc_resume,
\r
299 static int __init rk30_adc_init(void)
\r
301 return platform_driver_register(&rk30_adc_driver);
\r
303 subsys_initcall(rk30_adc_init);
\r
305 static void __exit rk30_adc_exit(void)
\r
307 platform_driver_unregister(&rk30_adc_driver);
\r
309 module_exit(rk30_adc_exit);
\r
311 MODULE_DESCRIPTION("Driver for ADC");
\r
312 MODULE_AUTHOR("kfx, kfx@rock-chips.com");
\r
313 MODULE_LICENSE("GPL");
\r
314 static int __init adc_test_init(void)
\r
316 printk("def_ref_volt: %dmV, curr_ref_volt: %dmV\n",
\r
317 get_def_ref_volt(), get_curr_ref_volt());
\r
325 module_init(adc_test_init);
\r