一. device的注册
1.0 两个注册
//在smdk6410_machine_init中既注册了touchscreen的私有信息也注册了ts资源
1 在arch/arm/mach-s3c64xx/mach-smdk6410.c中
2 static void __init smdk6410_machine_init(void)
3 {
4 //在arch/arm/mach-s3c64xx/dev-ts.c中
5 s3c_ts_set_platdata(&s3c_ts_platform); //1.设备私有信息的注册
6 //在driver/base/platform.c中
7 platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices)); //2.设备资源的注册
8 }
1.1 ts私有信息的注册
在arch/arm/mach-s3c64xx/mach-smdk6410.c中
1 static struct s3c_ts_mach_info s3c_ts_platform __initdata = {
2 .delay = 10000, //延时
3 .presc = 49, //分频
4 .oversampling_shift = 2, //分频
5 .resol_bit = 12, //精度
6 .s3c_adc_con = ADC_TYPE_2, //分频
7 };
8 smdk6410_machine_init
9 {
10 //下面这个函数在arch/arm/mach-s3c64xx/dev-ts.c中
11 s3c_ts_set_platdata(&s3c_ts_platform);
12 }
1.2 ts设备资源的注册
1 //在arch/arm/mach-s3c64xx/dev-ts.c中
2 static struct resource s3c_ts_resource[] = {
3 [0] = {
4 .start = SAMSUNG_PA_ADC, //0x7E00B000
5 .end = SAMSUNG_PA_ADC + SZ_256 - 1, //0x7E00B100
6 .flags = IORESOURCE_MEM,
7 },
8 [1] = {
9 .start = IRQ_PENDN, //0x5e=94
10 .end = IRQ_PENDN,
11 .flags = IORESOURCE_IRQ,
12 },
13 [2] = {
14 .start = IRQ_ADC, //0x5f=95
15 .end = IRQ_ADC,
16 .flags = IORESOURCE_IRQ,
17 }
18 };
19 struct platform_device s3c_device_ts = {
20 .name = 's3c-ts',
21 .id = -1,
22 .num_resources = ARRAY_SIZE(s3c_ts_resource),
23 .resource = s3c_ts_resource,
24 };
25 //在arch/arm/mach-s3c64xx/mach-smdk6410.c中
26 static struct platform_device *smdk6410_devices[] __initdata = {
27 &s3c_device_ts, //把ts放入到总的ts列表中
28 }
29 //在arch/arm/mach-s3c64xx/mach-smdk6410.c中
30 static void __init smdk6410_machine_init(void)
31 {
32 //在driver/base/platform.c中一起注册
33 platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
34 }
二. device_driver
2.0 两个宏
1 #define WAIT4INT(x) //只是针对于S3C_ADCTSC寄存器
2 (((x)<<8) | //
3 S3C_ADCTSC_YM_SEN | //
4 S3C_ADCTSC_YP_SEN | //
5 //XM_SEN //
6 S3C_ADCTSC_XP_SEN | //
7 //PULL_UP //
8 //AUTO_PST //
9 S3C_ADCTSC_XY_PST(3)) //
10 #define AUTOPST
11 (S3C_ADCTSC_YM_SEN | //1 = Switch enable (YM = VSSA_ADC)
12 S3C_ADCTSC_YP_SEN | //1 = Switch disable (YP=AIN5, Hi-z)
13 S3C_ADCTSC_XP_SEN | //1 = Switch disable (XP=AIN7, Hi-z)
14 S3C_ADCTSC_AUTO_PST | //1 = Auto Sequential measurement of X-position, Y-position
15 S3C_ADCTSC_XY_PST(0)) //0 = No operation mode
16 WAIT4INT(x) :
17 当x=0时,设为等侍down中断
18 当x=1时,设为等侍up中断
2.1 初始化
ok6410的touchscreen在内核源码的位置:driver/input/touchscreen/s3c-ts.c
device 与 device_driver按名字s3c-ts匹配之后,就进入s3c_ts_probe函数
static struct platform_driver s3c_ts_driver = {
.probe = s3c_ts_probe,
.remove = s3c_ts_remove,
.suspend = s3c_ts_suspend,
.resume = s3c_ts_resume,
.driver = {
.owner = THIS_MODULE,
.name = 's3c-ts',
},
};
static int __init s3c_ts_init(void)
{
return platform_driver_register(&s3c_ts_driver);
}
static void __exit s3c_ts_exit(void)
{
platform_driver_unregister(&s3c_ts_driver);
}
module_init(s3c_ts_init);
module_exit(s3c_ts_exit);
2.2 probe函数
1 static int __init s3c_ts_probe(struct platform_device *pdev)
2 {
3 struct resource *res;
4 struct device *dev;
5 struct input_dev *input_dev;
6 struct s3c_ts_mach_info * s3c_ts_cfg;
7 int ret, size;
8 dev = &pdev->dev;
9 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取ts寄存器地址
10 size = (res->end - res->start) + 1;
11 ts_mem = request_mem_region(res->start, size, pdev->name); //申请I/O内存
12 ts_base = ioremap(res->start, size); //request_mem_region申请的内存在使用前要调用ioremap
13 ts_clock = clk_get(&pdev->dev, 'adc'); //获取clock
14 clk_enable(ts_clock); //在初始化时disable了ts_clock,这个地方要enable
15
16 //下面这几行是要把ts的配置信息写到寄存器中去
17 s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev); //获取ts的配置信息,
18 //ts的私有信息:在arch/arm/mach-s3c64xx/mach-smdk6410.c中
19 //enable prescaler && 设置prescaler_value=s3c_ts_cfg->presc
20 writel(S3C_ADCCON_PRSCEN | S3C_ADCCON_PRSCVL(s3c_ts_cfg->presc&0xff), ts_base+S3C_ADCCON);
21
22 //s3c_ts_cfg->delay=0x10000 --> External input clock
23 writel(s3c_ts_cfg->delay & 0xffff, ts_base+S3C_ADCDLY);
24
25 //A/D converter resolution selection--> 12-bit A/D conversion
26 writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT, ts_base+S3C_ADCCON);
27 //设为等侍down中断模式
28 writel(WAIT4INT(0), ts_base+S3C_ADCTSC);
29 ts = kzalloc(sizeof(struct s3c_ts_info), GFP_KERNEL); //下面这几行是要初始化s3c_ts_info结构体
30 input_dev = input_allocate_device();
31
32 ts->dev = input_dev;
33 ts->dev->evbit[0] = ts->dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
34 ts->dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
35 if (s3c_ts_cfg->resol_bit==12) {
36 input_set_abs_params(ts->dev, ABS_X, 0, 0xFFF, 0, 0); //设置x轴的最大最小值