adc: interface: 'get_def_ref_volt' and 'get_curr_ref_volt'
authorkfx <kfx@rock-chips.com>
Fri, 16 Nov 2012 02:17:42 +0000 (10:17 +0800)
committerkfx <kfx@rock-chips.com>
Fri, 16 Nov 2012 02:17:42 +0000 (10:17 +0800)
arch/arm/mach-rk29/devices.c
arch/arm/mach-rk2928/devices.c
arch/arm/mach-rk2928/include/mach/config.h
arch/arm/mach-rk30/devices.c
arch/arm/plat-rk/include/plat/board.h
drivers/adc/adc_priv.h
drivers/adc/core.c
drivers/adc/plat/rk29_adc.c
drivers/adc/plat/rk30_adc.c
include/linux/adc.h

index 779a9f13786c62db65b6d3a1aca4c6055cd80338..154c3f852d97f239d47bf08a0e0544f853bf276a 100644 (file)
 #include "devices.h"
 
 #ifdef CONFIG_ADC_RK29
+static struct adc_platform_data rk30_adc_pdata = {
+        .ref_volt = 2500, //2500mV
+        .base_chn = -1,
+};
 static struct resource rk29_adc_resource[] = {
        {
                .start  = IRQ_SARADC,
@@ -49,6 +53,9 @@ struct platform_device rk29_device_adc = {
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rk29_adc_resource),
        .resource       = rk29_adc_resource,
+        .dev            = {
+               .platform_data = &rk29_adc_pdata,
+        },
 };
 #endif
 
index ccccbfa7f69c10291b30c6acc29525b90fe0a49b..7858914bd95467dda12a3fa05269b13800af7432 100755 (executable)
 #include <mach/dma-pl330.h>
 #include <mach/gpio.h>
 #include <mach/iomux.h>
+#include <mach/dvfs.h>
 #include <plat/rk_fiq_debugger.h>
+#include <linux/regulator/consumer.h>
 
 #ifdef CONFIG_ADC_RK30
+static int rk30_get_base_volt(void)
+{
+        int volt;
+        struct regulator *logic = dvfs_get_regulator("vdd_core");
+
+        if(unlikely(IS_ERR_OR_NULL(logic))){
+                printk("%s: fail to get logic voltage\n", __func__);
+                return -EINVAL;
+        }
+        volt =  regulator_get_voltage(logic)/1000;
+
+        return volt;
+}
+static struct adc_platform_data rk30_adc_pdata = {
+        .ref_volt = 3300, //3300mV
+        .base_chn = 3,
+        .get_base_volt = &rk30_get_base_volt,
+};
 static struct resource rk30_adc_resource[] = {
        {
                .start  = IRQ_SARADC,
@@ -48,6 +68,9 @@ struct platform_device device_adc = {
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rk30_adc_resource),
        .resource       = rk30_adc_resource,
+        .dev            = {
+               .platform_data = &rk30_adc_pdata,
+        },
 };
 #endif
 
index cb45ceadd24790978f3be13068a40929f53726de..761a7a9ec810d96950404af52b0cf2ad748c90e3 100755 (executable)
@@ -336,6 +336,7 @@ enum {
 
 /* global */
 enum {
+        DEF_IS_PHONEPAD = 0,
         DEF_PWR_ON = 0x000001b4,
 };
 
index 9594b8bdaf28552fe46b0760fa95711c6387f88f..8e43125a7dc895e50778369767a12bda2db8f585 100755 (executable)
 #include <plat/rk_fiq_debugger.h>
 
 #ifdef CONFIG_ADC_RK30
+static struct adc_platform_data rk30_adc_pdata = {
+        #if defind(CONFIG_ARCH_RK3066B)       
+        .ref_volt = 1800, //1800mV
+        #else
+        .ref_volt = 2500, //2500mV
+        #endif
+        .base_chn = -1,
+};
 static struct resource rk30_adc_resource[] = {
        {
                .start  = IRQ_SARADC,
@@ -45,6 +53,9 @@ struct platform_device device_adc = {
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rk30_adc_resource),
        .resource       = rk30_adc_resource,
+        .dev            = {
+               .platform_data = &rk30_adc_pdata,
+        },
 };
 #endif
 
index d687ad00809aa90f03c070b4d8d3efe6919acc63..97055875bb15da2b83c2d424fe023271c67ab1ec 100755 (executable)
@@ -7,7 +7,11 @@
 #include <linux/rk_screen.h>
 #include <plat/sram.h>
 
-
+struct adc_platform_data {
+        int ref_volt;
+        int base_chn;
+        int (*get_base_volt)(void);
+};
 enum {
         I2C_IDLE = 0,
         I2C_SDA_LOW,
index d7a3c7fd9ea83eecdb1c27b46f3bfa775d120fd7..9a1189226fcef446ad63598926ac4809be184dc6 100755 (executable)
@@ -72,6 +72,8 @@ struct adc_host {
         struct mutex m_lock;\r
         unsigned int client_count;\r
        const struct adc_ops *ops;\r
+        struct adc_client *base_client;\r
+        struct adc_platform_data *pdata;\r
         unsigned long priv[0];\r
 };\r
 \r
@@ -79,10 +81,9 @@ static inline void *adc_priv(struct adc_host *adc)
 {\r
        return adc->priv;\r
 }\r
-       \r
+extern struct adc_host *g_adc;\r
 struct adc_host *adc_alloc_host(struct device *dev, int extra, enum host_chn_mask mask);\r
 void adc_free_host(struct adc_host *adc);\r
 void adc_core_irq_handle(struct adc_host *adc);\r
-\r
 #endif\r
 \r
index ed8a4f78cd9ad5309e07fd222eb39d78d18e1b9e..35ba255d8bd39317e6f1420855d1040b1d11e88e 100755 (executable)
@@ -7,6 +7,7 @@
 #include <linux/adc.h>
 #include "adc_priv.h"
 
+struct adc_host *g_adc = NULL;
 struct list_head adc_host_head;
 
 struct adc_host *adc_alloc_host(struct device *dev, int extra, enum host_chn_mask mask)
@@ -239,6 +240,31 @@ int adc_async_read(struct adc_client *client)
 }
 
 EXPORT_SYMBOL(adc_async_read);
+int get_def_ref_volt(void)
+{
+        return g_adc->pdata->ref_volt;
+}
+EXPORT_SYMBOL(get_def_ref_volt);
+int get_curr_ref_volt(void)
+{
+        int v = 0, volt = 0;
+
+        if(!g_adc)
+                return -EINVAL;
+        if(!g_adc->base_client)
+                return g_adc->pdata->ref_volt;
+
+        volt = g_adc->pdata->get_base_volt();
+        if(volt < 0)
+                return g_adc->pdata->ref_volt;
+        
+        v = adc_sync_read(g_adc->base_client);
+        if(v < 0)
+                return v;
+
+        return volt * 1024 / v;
+}
+EXPORT_SYMBOL(get_curr_ref_volt);
 
 static int __init adc_core_init(void)
 {
index 63f91fb1c1d08c954170749124a3f79daef95e23..815b947ac89a1f324c5d2afeb7415afa94cde590 100755 (executable)
@@ -105,15 +105,20 @@ static int rk29_adc_test(void)
 \r
 static int rk29_adc_probe(struct platform_device *pdev)\r
 {\r
+        struct adc_platform_data *pdata = pdev->dev.platform_data;\r
        struct adc_host *adc = NULL;\r
        struct rk29_adc_device *dev;\r
        struct resource *res;\r
        int ret;\r
 \r
+        if(!pdata)\r
+                return -EINVAL;\r
+\r
        adc = adc_alloc_host(&pdev->dev, sizeof(struct rk29_adc_device), SARADC_CHN_MASK);\r
        if (!adc)\r
                return -ENOMEM;\r
        adc->ops = &rk29_adc_ops;\r
+        adc->pdata = pdata;\r
        dev = adc_priv(adc);\r
        dev->adc = adc;\r
        dev->irq = platform_get_irq(pdev, 0);\r
@@ -161,6 +166,7 @@ static int rk29_adc_probe(struct platform_device *pdev)
                ret = -ENXIO;\r
                goto err_ioarea;\r
        }\r
+        g_adc = adc;\r
        platform_set_drvdata(pdev, dev);\r
        dev_info(&pdev->dev, "rk29 adc: driver initialized\n");\r
        return 0;\r
index 359f275023c43368540d9169e129a1be395a0587..601f6b6aea8a93bdb2cd7dbc2bc30fd2cff833cb 100755 (executable)
@@ -10,7 +10,8 @@
 #include "rk30_adc.h"\r
 \r
 //#define ADC_TEST\r
-\r
+#define SAMPLE_COUNT            10\r
+#define MIN_SAMPLE_VALUE        310\r
 struct rk30_adc_device {\r
        int                      irq;\r
        void __iomem            *regs;\r
@@ -116,15 +117,20 @@ static int rk30_adc_test(void)
 \r
 static int rk30_adc_probe(struct platform_device *pdev)\r
 {\r
+        struct adc_platform_data *pdata = pdev->dev.platform_data;\r
        struct adc_host *adc = NULL;\r
        struct rk30_adc_device *dev;\r
        struct resource *res;\r
-       int ret;\r
+       int ret = 0, i, v;\r
+\r
+        if(!pdata)\r
+                return -EINVAL;\r
 \r
        adc = adc_alloc_host(&pdev->dev, sizeof(struct rk30_adc_device), SARADC_CHN_MASK);\r
        if (!adc)\r
                return -ENOMEM;\r
        adc->ops = &rk30_adc_ops;\r
+        adc->pdata = pdata;\r
        dev = adc_priv(adc);\r
        dev->adc = adc;\r
        dev->irq = platform_get_irq(pdev, 0);\r
@@ -181,29 +187,58 @@ static int rk30_adc_probe(struct platform_device *pdev)
                ret = -ENXIO;\r
                goto err_ioarea;\r
        }\r
+        g_adc = adc;\r
        platform_set_drvdata(pdev, dev);\r
+\r
+        if(adc->pdata->base_chn > 0){\r
+                adc->base_client = adc_register(adc->pdata->base_chn, NULL, NULL);\r
+                if(!adc->base_client){\r
+                       dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn);\r
+                        ret = -ENOMEM;\r
+                        goto err_adc_register;\r
+                }\r
+                for(i = 0; i < SAMPLE_COUNT; i++){\r
+                        v = adc_sync_read(adc->base_client);\r
+                        if(v < 0){\r
+                               dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn);\r
+                                ret = v;\r
+                                goto err_adc_sync_read;\r
+                        }else if(v < MIN_SAMPLE_VALUE){\r
+                               dev_info(&pdev->dev, "chn[%d]: adc value(%d) is invalide\n", adc->pdata->base_chn, v);\r
+                                adc_unregister(adc->base_client);\r
+                                adc->base_client = NULL;\r
+                                break;\r
+                        }\r
+                        adc_dbg(&pdev->dev, "read ref_adc: %d\n", v);\r
+                        mdelay(1);\r
+                }\r
+        }\r
        dev_info(&pdev->dev, "rk30 adc: driver initialized\n");\r
        return 0;\r
-\r
- err_ioarea:\r
+err_adc_sync_read:\r
+        adc_unregister(adc->base_client);\r
+        adc->base_client = NULL;\r
+err_adc_register:\r
+       iounmap(dev->regs);\r
+err_ioarea:\r
        release_resource(dev->ioarea);\r
        kfree(dev->ioarea);\r
 \r
- err_clk:\r
+err_clk:\r
        clk_disable(dev->clk);\r
 \r
- err_pclk:\r
+err_pclk:\r
        clk_disable(dev->pclk);\r
        clk_put(dev->pclk);\r
 \r
- err_clk2:\r
+err_clk2:\r
        clk_put(dev->clk);\r
 \r
- err_irq:\r
+err_irq:\r
        free_irq(dev->irq, dev);\r
 \r
- err_alloc:\r
-       adc_free_host(dev->adc);\r
+err_alloc:\r
+        adc_free_host(dev->adc);\r
        return ret;\r
 }\r
 \r
@@ -211,6 +246,10 @@ static int rk30_adc_remove(struct platform_device *pdev)
 {\r
        struct rk30_adc_device *dev = platform_get_drvdata(pdev);\r
 \r
+        if(dev->adc->base_client){\r
+                adc_unregister(dev->adc->base_client);\r
+                dev->adc->base_client = NULL;\r
+        }\r
        iounmap(dev->regs);\r
        release_resource(dev->ioarea);\r
        kfree(dev->ioarea);\r
@@ -274,8 +313,11 @@ MODULE_AUTHOR("kfx, kfx@rock-chips.com");
 MODULE_LICENSE("GPL");\r
 static int __init adc_test_init(void)\r
 {\r
+        printk("def_ref_volt: %dmV, curr_ref_volt: %dmV\n", \r
+                        get_def_ref_volt(), get_curr_ref_volt());\r
+        while(1);\r
 #ifdef ADC_TEST        \r
-               rk30_adc_test();\r
+       rk30_adc_test();\r
 #endif\r
        return 0;\r
 \r
index be4547b038c411b8ea0febeaa1ff7a176ce31e70..3cda18c687f4f8b64186b0b926135a21cc74e3fc 100755 (executable)
@@ -55,6 +55,14 @@ int adc_sync_read(struct adc_client *client);
  *     if timeout, sample value is -1; else sample value is non-negative\r
  */\r
 int adc_async_read(struct adc_client *client);\r
+/*\r
+ * function: return current reference voltage, unit: mV\r
+ */\r
+int get_curr_ref_volt(void);\r
+/*\r
+ * function: return default reference voltage, unit: mV\r
+ */\r
+int get_def_ref_volt(void);\r
 #else\r
 static inline struct adc_client *adc_register(int chn,\r
                                void (*callback)(struct adc_client *, void *, int),\r
@@ -65,6 +73,8 @@ static inline struct adc_client *adc_register(int chn,
 static inline void adc_unregister(struct adc_client *client) {}\r
 static inline int adc_sync_read(struct adc_client *client) { return -1; }\r
 static inline int adc_async_read(struct adc_client *client) { return -1; }\r
+static inline int get_curr_ref_volt(void) { return -1; }\r
+static inline int get_def_ref_volt(void) { return -1; }\r
 #endif\r
 \r
 #endif\r