From 82b65d3a7b2570ab82cb397317466d23482652db Mon Sep 17 00:00:00 2001 From: kfx Date: Fri, 16 Nov 2012 10:17:42 +0800 Subject: [PATCH] adc: interface: 'get_def_ref_volt' and 'get_curr_ref_volt' --- arch/arm/mach-rk29/devices.c | 7 +++ arch/arm/mach-rk2928/devices.c | 23 ++++++++ arch/arm/mach-rk2928/include/mach/config.h | 1 + arch/arm/mach-rk30/devices.c | 11 ++++ arch/arm/plat-rk/include/plat/board.h | 6 +- drivers/adc/adc_priv.h | 5 +- drivers/adc/core.c | 26 +++++++++ drivers/adc/plat/rk29_adc.c | 6 ++ drivers/adc/plat/rk30_adc.c | 64 ++++++++++++++++++---- include/linux/adc.h | 10 ++++ 10 files changed, 145 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-rk29/devices.c b/arch/arm/mach-rk29/devices.c index 779a9f13786c..154c3f852d97 100644 --- a/arch/arm/mach-rk29/devices.c +++ b/arch/arm/mach-rk29/devices.c @@ -31,6 +31,10 @@ #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 diff --git a/arch/arm/mach-rk2928/devices.c b/arch/arm/mach-rk2928/devices.c index ccccbfa7f69c..7858914bd954 100755 --- a/arch/arm/mach-rk2928/devices.c +++ b/arch/arm/mach-rk2928/devices.c @@ -27,9 +27,29 @@ #include #include #include +#include #include +#include #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 diff --git a/arch/arm/mach-rk2928/include/mach/config.h b/arch/arm/mach-rk2928/include/mach/config.h index cb45ceadd247..761a7a9ec810 100755 --- a/arch/arm/mach-rk2928/include/mach/config.h +++ b/arch/arm/mach-rk2928/include/mach/config.h @@ -336,6 +336,7 @@ enum { /* global */ enum { + DEF_IS_PHONEPAD = 0, DEF_PWR_ON = 0x000001b4, }; diff --git a/arch/arm/mach-rk30/devices.c b/arch/arm/mach-rk30/devices.c index 9594b8bdaf28..8e43125a7dc8 100755 --- a/arch/arm/mach-rk30/devices.c +++ b/arch/arm/mach-rk30/devices.c @@ -27,6 +27,14 @@ #include #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 diff --git a/arch/arm/plat-rk/include/plat/board.h b/arch/arm/plat-rk/include/plat/board.h index d687ad00809a..97055875bb15 100755 --- a/arch/arm/plat-rk/include/plat/board.h +++ b/arch/arm/plat-rk/include/plat/board.h @@ -7,7 +7,11 @@ #include #include - +struct adc_platform_data { + int ref_volt; + int base_chn; + int (*get_base_volt)(void); +}; enum { I2C_IDLE = 0, I2C_SDA_LOW, diff --git a/drivers/adc/adc_priv.h b/drivers/adc/adc_priv.h index d7a3c7fd9ea8..9a1189226fce 100755 --- a/drivers/adc/adc_priv.h +++ b/drivers/adc/adc_priv.h @@ -72,6 +72,8 @@ struct adc_host { struct mutex m_lock; unsigned int client_count; const struct adc_ops *ops; + struct adc_client *base_client; + struct adc_platform_data *pdata; unsigned long priv[0]; }; @@ -79,10 +81,9 @@ static inline void *adc_priv(struct adc_host *adc) { return adc->priv; } - +extern struct adc_host *g_adc; struct adc_host *adc_alloc_host(struct device *dev, int extra, enum host_chn_mask mask); void adc_free_host(struct adc_host *adc); void adc_core_irq_handle(struct adc_host *adc); - #endif diff --git a/drivers/adc/core.c b/drivers/adc/core.c index ed8a4f78cd9a..35ba255d8bd3 100755 --- a/drivers/adc/core.c +++ b/drivers/adc/core.c @@ -7,6 +7,7 @@ #include #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) { diff --git a/drivers/adc/plat/rk29_adc.c b/drivers/adc/plat/rk29_adc.c index 63f91fb1c1d0..815b947ac89a 100755 --- a/drivers/adc/plat/rk29_adc.c +++ b/drivers/adc/plat/rk29_adc.c @@ -105,15 +105,20 @@ static int rk29_adc_test(void) static int rk29_adc_probe(struct platform_device *pdev) { + struct adc_platform_data *pdata = pdev->dev.platform_data; struct adc_host *adc = NULL; struct rk29_adc_device *dev; struct resource *res; int ret; + if(!pdata) + return -EINVAL; + adc = adc_alloc_host(&pdev->dev, sizeof(struct rk29_adc_device), SARADC_CHN_MASK); if (!adc) return -ENOMEM; adc->ops = &rk29_adc_ops; + adc->pdata = pdata; dev = adc_priv(adc); dev->adc = adc; dev->irq = platform_get_irq(pdev, 0); @@ -161,6 +166,7 @@ static int rk29_adc_probe(struct platform_device *pdev) ret = -ENXIO; goto err_ioarea; } + g_adc = adc; platform_set_drvdata(pdev, dev); dev_info(&pdev->dev, "rk29 adc: driver initialized\n"); return 0; diff --git a/drivers/adc/plat/rk30_adc.c b/drivers/adc/plat/rk30_adc.c index 359f275023c4..601f6b6aea8a 100755 --- a/drivers/adc/plat/rk30_adc.c +++ b/drivers/adc/plat/rk30_adc.c @@ -10,7 +10,8 @@ #include "rk30_adc.h" //#define ADC_TEST - +#define SAMPLE_COUNT 10 +#define MIN_SAMPLE_VALUE 310 struct rk30_adc_device { int irq; void __iomem *regs; @@ -116,15 +117,20 @@ static int rk30_adc_test(void) static int rk30_adc_probe(struct platform_device *pdev) { + struct adc_platform_data *pdata = pdev->dev.platform_data; struct adc_host *adc = NULL; struct rk30_adc_device *dev; struct resource *res; - int ret; + int ret = 0, i, v; + + if(!pdata) + return -EINVAL; adc = adc_alloc_host(&pdev->dev, sizeof(struct rk30_adc_device), SARADC_CHN_MASK); if (!adc) return -ENOMEM; adc->ops = &rk30_adc_ops; + adc->pdata = pdata; dev = adc_priv(adc); dev->adc = adc; dev->irq = platform_get_irq(pdev, 0); @@ -181,29 +187,58 @@ static int rk30_adc_probe(struct platform_device *pdev) ret = -ENXIO; goto err_ioarea; } + g_adc = adc; platform_set_drvdata(pdev, dev); + + if(adc->pdata->base_chn > 0){ + adc->base_client = adc_register(adc->pdata->base_chn, NULL, NULL); + if(!adc->base_client){ + dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn); + ret = -ENOMEM; + goto err_adc_register; + } + for(i = 0; i < SAMPLE_COUNT; i++){ + v = adc_sync_read(adc->base_client); + if(v < 0){ + dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn); + ret = v; + goto err_adc_sync_read; + }else if(v < MIN_SAMPLE_VALUE){ + dev_info(&pdev->dev, "chn[%d]: adc value(%d) is invalide\n", adc->pdata->base_chn, v); + adc_unregister(adc->base_client); + adc->base_client = NULL; + break; + } + adc_dbg(&pdev->dev, "read ref_adc: %d\n", v); + mdelay(1); + } + } dev_info(&pdev->dev, "rk30 adc: driver initialized\n"); return 0; - - err_ioarea: +err_adc_sync_read: + adc_unregister(adc->base_client); + adc->base_client = NULL; +err_adc_register: + iounmap(dev->regs); +err_ioarea: release_resource(dev->ioarea); kfree(dev->ioarea); - err_clk: +err_clk: clk_disable(dev->clk); - err_pclk: +err_pclk: clk_disable(dev->pclk); clk_put(dev->pclk); - err_clk2: +err_clk2: clk_put(dev->clk); - err_irq: +err_irq: free_irq(dev->irq, dev); - err_alloc: - adc_free_host(dev->adc); +err_alloc: + adc_free_host(dev->adc); return ret; } @@ -211,6 +246,10 @@ static int rk30_adc_remove(struct platform_device *pdev) { struct rk30_adc_device *dev = platform_get_drvdata(pdev); + if(dev->adc->base_client){ + adc_unregister(dev->adc->base_client); + dev->adc->base_client = NULL; + } iounmap(dev->regs); release_resource(dev->ioarea); kfree(dev->ioarea); @@ -274,8 +313,11 @@ MODULE_AUTHOR("kfx, kfx@rock-chips.com"); MODULE_LICENSE("GPL"); static int __init adc_test_init(void) { + printk("def_ref_volt: %dmV, curr_ref_volt: %dmV\n", + get_def_ref_volt(), get_curr_ref_volt()); + while(1); #ifdef ADC_TEST - rk30_adc_test(); + rk30_adc_test(); #endif return 0; diff --git a/include/linux/adc.h b/include/linux/adc.h index be4547b038c4..3cda18c687f4 100755 --- a/include/linux/adc.h +++ b/include/linux/adc.h @@ -55,6 +55,14 @@ int adc_sync_read(struct adc_client *client); * if timeout, sample value is -1; else sample value is non-negative */ int adc_async_read(struct adc_client *client); +/* + * function: return current reference voltage, unit: mV + */ +int get_curr_ref_volt(void); +/* + * function: return default reference voltage, unit: mV + */ +int get_def_ref_volt(void); #else static inline struct adc_client *adc_register(int chn, void (*callback)(struct adc_client *, void *, int), @@ -65,6 +73,8 @@ static inline struct adc_client *adc_register(int chn, static inline void adc_unregister(struct adc_client *client) {} static inline int adc_sync_read(struct adc_client *client) { return -1; } static inline int adc_async_read(struct adc_client *client) { return -1; } +static inline int get_curr_ref_volt(void) { return -1; } +static inline int get_def_ref_volt(void) { return -1; } #endif #endif -- 2.34.1