#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,
.id = -1,
.num_resources = ARRAY_SIZE(rk29_adc_resource),
.resource = rk29_adc_resource,
+ .dev = {
+ .platform_data = &rk29_adc_pdata,
+ },
};
#endif
#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,
.id = -1,
.num_resources = ARRAY_SIZE(rk30_adc_resource),
.resource = rk30_adc_resource,
+ .dev = {
+ .platform_data = &rk30_adc_pdata,
+ },
};
#endif
/* global */
enum {
+ DEF_IS_PHONEPAD = 0,
DEF_PWR_ON = 0x000001b4,
};
#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,
.id = -1,
.num_resources = ARRAY_SIZE(rk30_adc_resource),
.resource = rk30_adc_resource,
+ .dev = {
+ .platform_data = &rk30_adc_pdata,
+ },
};
#endif
#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,
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
{\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
#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)
}
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)
{
\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
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
#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
\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
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
{\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
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
* 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
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