2 * Copyright (C) 2012 ROCKCHIP, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License.
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/device.h>
13 #include <linux/platform_device.h>
14 #include <linux/err.h>
15 #include <linux/clk.h>
16 #include <linux/interrupt.h>
18 #include <linux/delay.h>
19 #include <linux/slab.h>
21 #define TSADC_DATA 0x00
22 #define TSADC_DATA_MASK 0xfff
24 #define TSADC_STAS 0x04
25 #define TSADC_STAS_BUSY (1 << 0)
26 #define TSADC_STAS_BUSY_MASK (1 << 0)
28 #define TSADC_CTRL 0x08
29 #define TSADC_CTRL_CH(ch) ((ch) << 0)
30 #define TSADC_CTRL_POWER_UP (1 << 3)
31 #define TSADC_CTRL_START (1 << 4)
32 #define TSADC_CTRL_IRQ_ENABLE (1 << 5)
33 #define TSADC_CTRL_IRQ_STATUS (1 << 6)
35 #define TSADC_DLY_PU_SOC 0x0C
37 #define TSADC_CLK_RATE 50000 /* 50KHz */
45 static const struct tsadc_table table[] =
47 {TSADC_DATA_MASK, -40},
90 struct rk30_tsadc_device {
94 struct resource *ioarea;
97 static struct rk30_tsadc_device *g_dev;
99 static u32 tsadc_readl(u32 offset)
101 return readl_relaxed(g_dev->regs + offset);
104 static void tsadc_writel(u32 val, u32 offset)
106 writel_relaxed(val, g_dev->regs + offset);
109 static DEFINE_MUTEX(tsadc_mutex);
110 static void rk30_tsadc_get(unsigned int chn, int *temp, int *code)
115 if (!g_dev || chn > 1)
118 mutex_lock(&tsadc_mutex);
120 clk_enable(g_dev->pclk);
121 clk_enable(g_dev->clk);
124 tsadc_writel(0, TSADC_CTRL);
125 tsadc_writel(TSADC_CTRL_POWER_UP | TSADC_CTRL_CH(chn), TSADC_CTRL);
127 if ((tsadc_readl(TSADC_STAS) & TSADC_STAS_BUSY_MASK) != TSADC_STAS_BUSY) {
129 *code = tsadc_readl(TSADC_DATA) & TSADC_DATA_MASK;
130 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
131 if ((*code) <= table[i].code && (*code) > table[i + 1].code) {
132 *temp = table[i].temp + (table[i + 1].temp - table[i].temp) * (table[i].code - (*code)) / (table[i].code - table[i + 1].code);
136 tsadc_writel(0, TSADC_CTRL);
138 clk_disable(g_dev->clk);
139 clk_disable(g_dev->pclk);
141 mutex_unlock(&tsadc_mutex);
144 int rk30_tsadc_get_temp(unsigned int chn)
148 rk30_tsadc_get(chn, &temp, &code);
151 EXPORT_SYMBOL(rk30_tsadc_get_temp);
153 static int rk30_tsadc_get_temp0(char *buffer, struct kernel_param *kp)
156 rk30_tsadc_get(0, &temp, &code);
157 return sprintf(buffer, "temp: %d code: %d", temp, code);
159 module_param_call(temp0, NULL, rk30_tsadc_get_temp0, NULL, S_IRUGO);
161 static int rk30_tsadc_get_temp1(char *buffer, struct kernel_param *kp)
164 rk30_tsadc_get(1, &temp, &code);
165 return sprintf(buffer, "temp: %d code: %d", temp, code);
167 module_param_call(temp1, NULL, rk30_tsadc_get_temp1, NULL, S_IRUGO);
169 static int __init rk30_tsadc_probe(struct platform_device *pdev)
171 struct rk30_tsadc_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
172 struct resource *res;
176 dev_err(&pdev->dev, "failed to alloc mem\n");
180 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
182 dev_err(&pdev->dev, "cannot find IO resource\n");
187 dev->ioarea = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);
189 dev_err(&pdev->dev, "cannot request IO\n");
194 dev->regs = ioremap(res->start, (res->end - res->start) + 1);
196 dev_err(&pdev->dev, "cannot map IO\n");
201 dev->clk = clk_get(NULL, "tsadc");
202 if (IS_ERR(dev->clk)) {
203 dev_err(&pdev->dev, "failed to get clk\n");
204 ret = PTR_ERR(dev->clk);
208 ret = clk_set_rate(dev->clk, TSADC_CLK_RATE);
210 dev_err(&pdev->dev, "failed to set clk\n");
214 dev->pclk = clk_get(NULL, "pclk_tsadc");
215 if (IS_ERR(dev->pclk)) {
216 dev_err(&pdev->dev, "failed to get pclk\n");
217 ret = PTR_ERR(dev->clk);
221 platform_set_drvdata(pdev, dev);
224 dev_info(&pdev->dev, "initialized\n");
233 release_resource(dev->ioarea);
239 static struct platform_driver rk30_tsadc_driver = {
241 .name = "rk30-tsadc",
242 .owner = THIS_MODULE,
246 static int __init rk30_tsadc_init(void)
248 return platform_driver_probe(&rk30_tsadc_driver, rk30_tsadc_probe);
250 rootfs_initcall(rk30_tsadc_init);
252 MODULE_DESCRIPTION("Driver for TSADC");
253 MODULE_AUTHOR("lw, lw@rock-chips.com");
254 MODULE_LICENSE("GPL");