S3C2440 linux 2.6.32.2 ADC HWMON驱动移植

准备添加液晶屏触屏驱动程序,网上很多资料都说触屏驱动要有ADC支持因此必须先添加ADC驱动,网上都说linux2.6.32.2没有ADC驱动,但是经过自己查找分析内核是支持ADC驱动的。源码中有adc.c在arch/arm/plat-s3c24xx目录下。我们先来移植HWMON驱动,HWMON是Hardware Monitoring缩写,是用于检测设备状态的一种设备,比如电脑上检测测风扇转速、CPU温度的设备,实际上就是一些传感器,ADC也属于这样的设备。

1.在mach-fz2440.c中添加HWMON设备: 
加入必要的头文件: 
#include <plat/hwmon.h> 
 
在fz2440_devices[ ]结构中加入: 
  &s3c_device_adc,  
  &s3c_device_hwmon, 
 
构建HWMON设备平台数据结构: 
/* ADC */ 
static struct s3c_hwmon_pdata fz2440_hwmon_info __initdata = { 
  .in[0] = &(struct s3c_hwmon_chcfg) { 
   .name  = "adc-ch0", 
   .mult  = 3300, 
   .div  = 512, 
  }, 
  .in[1] = &(struct s3c_hwmon_chcfg) { 
   .name  = "adc-ch1", 
   .mult  = 3300, 
   .div  = 1024, 
  }, 
  .in[2] = &(struct s3c_hwmon_chcfg) { 
   .name  = "adc-ch2", 
   .mult  = 3300, 
   .div  = 512, 
  }, 
  .in[3] = &(struct s3c_hwmon_chcfg) { 
   .name  = "adc-ch3", 
   .mult  = 3300,
   .div  = 1024, 
  }, 
};
2,在fz2440_machine_init函数中加入: 
s3c_hwmon_set_platdata(&fz2440_hwmon_info);
3,在内核中没有s3c_hwmon_set_platdata函数在arch/arm/plat-s3c24xx/devs.c(near 339 line)中添加如下函数:
void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
{
struct s3c_hwmon_pdata *npd;
if (!pd) {
printk(KERN_ERR "%s: no platform data\n", __func__);
return;
}
npd = kmemdup(pd, sizeof(struct s3c_hwmon_pdata), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
s3c_device_hwmon.dev.platform_data = npd;
}
arch/arm/plat-s3c/include/plat/hwmon.h中添加
extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd);
4,修改/drivers/hwmon/s3c-hwmon.c s3c_hwmon_probe函数的错误
static int __devinit s3c_hwmon_probe(struct platform_device *dev)
{
struct s3c_hwmon_pdata *pdata = dev->dev.platform_data;
struct s3c_hwmon *hwmon;
int ret = 0;
int i;
if (!pdata) {
dev_err(&dev->dev, "no platform data supplied\n");
return -EINVAL;
}
hwmon = kzalloc(sizeof(struct s3c_hwmon), GFP_KERNEL);
if (hwmon == NULL) {
dev_err(&dev->dev, "no memory\n");
return -ENOMEM;
}
platform_set_drvdata(dev, hwmon);
init_MUTEX(&hwmon->lock);
/* Register with the core ADC driver. */
hwmon->client = s3c_adc_register(dev, NULL, NULL, 0);
if (IS_ERR(hwmon->client)) {
dev_err(&dev->dev, "cannot register adc\n");
ret = PTR_ERR(hwmon->client);
goto err_mem;
}
/* add attributes for our adc devices. */
ret = s3c_hwmon_add_raw(&dev->dev);
if (ret)
goto err_registered;
/* register with the hwmon core */
hwmon->hwmon_dev = hwmon_device_register(&dev->dev);
if (IS_ERR(hwmon->hwmon_dev)) {
dev_err(&dev->dev, "error registering with hwmon\n");
ret = PTR_ERR(hwmon->hwmon_dev);
goto err_raw_attribute;
}
for (i = 0; i < ARRAY_SIZE(pdata->in); i++) {
struct s3c_hwmon_chcfg *cfg = pdata->in[i];
if (!cfg)
continue;
if (cfg->mult >= 0x10000)
dev_warn(&dev->dev,
"channel %d multiplier too large\n",
i);
if (cfg->div == 0) {
dev_err(&dev->dev, "channel %d divider zero\n", i);
continue;
}
ret = s3c_hwmon_create_attr(&dev->dev, pdata->in[i],
&hwmon->attrs[i], i);
if (ret) {
dev_err(&dev->dev,
"error creating channel %d\n", i);
for (i--; i >= 0; i--)
s3c_hwmon_remove_attr(&dev->dev,
&hwmon->attrs[i]);
goto err_hwmon_register;
}
}
return 0;
err_hwmon_register:
hwmon_device_unregister(hwmon->hwmon_dev);
err_raw_attribute:
s3c_hwmon_remove_raw(&dev->dev);
err_registered:
s3c_adc_release(hwmon->client);
err_mem:
kfree(hwmon);
return ret;
}

5,System Type  ---> 
  [*]  ADC common driver support 
Device Drivers  ---> 
  <*> Hardware Monitoring support  ---> 
   <*>   S3c24xx built-in ADC 
   [*]    Include raw channel attributes in sysfs
启动时打印: 
NET: Registered protocol family 16
s3c24xx-adc s3c24xx-adc: attached adc driver
S3C2440: Initialising architecture
 
查看设备: 
#cd  /sys/class/hwmon/hwmon0/device 
 
在这个目录下有 8个名为adcx_raw的文件,分别对应s3c2440 的 8 路ADC 
执行#cat  adc0_raw 查看该通道的AD转换值
笔者的开发板上ADC0连接的是可调电阻,改变可调电阻的值后发现电阻值发生变化,ADC移植成功。

 
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值