linux设备树-LCD触摸屏设备驱动

----------------------------------------------------------------------------------------------------------------------------
内核版本:linux 5.2.8
根文件系统:busybox 1.25.0
u-boot:2016.05
----------------------------------------------------------------------------------------------------------------------------

在上一节我们已经移植了LCD驱动,那么本节将会移植LCD触摸屏驱动。有关触摸屏的原理,以及硬件接线,我们在linux驱动移植-LCD触摸屏设备驱动章节已经介绍的非常清楚了。同时在这一篇博客,我们也详细介绍了触摸屏驱动的实现,并进行了代码演示。

linux 5.2.8内核已经自带了s3c2440触摸屏驱动,该驱动还依赖于ADC驱动,相当于把我们在linux驱动移植-LCD触摸屏设备驱动中写的驱动程序拆成了两个部分,但是代码整体逻辑大致是一样的。

这一节,我们将尝试引入设备树,通过设备树来实现触摸屏驱动程序。

一、触摸屏驱动

linux 5.2.8自带的s3c2440触摸屏驱动,其采用platform设备驱动模型。

1.1 platform device

名字为"s3c2410-ts"的platform device定义在arch/arm/plat-samsung/devs.c文件:

static struct resource s3c_ts_resource[] = {
        [0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),   // 0x58000000  SZ_1M
        [1] = DEFINE_RES_IRQ(IRQ_TC),                           // IRQ_TC为子中断 子中断控制器硬件中断号9,对应的主中断控制器硬件中断号31
};

struct platform_device s3c_device_ts = {
        .name           = "s3c2410-ts",
        .id             = -1,
        .dev.parent     = &s3c_device_adc.dev,
        .num_resources  = ARRAY_SIZE(s3c_ts_resource),
        .resource       = s3c_ts_resource,
};

void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
{
        s3c_set_platdata(hard_s3c2410ts_info,
                         sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
}

其中函数s3c24xx_ts_set_platdata用于设置platform设备的私有数据,数据类型为struct s3c2410_ts_mach_info,s3c_device_ts.dev.platform_data会被设置为&default_ts_data :

static struct s3c2410_ts_mach_info default_ts_data __initdata = {
        .delay                  = 10000,
        .presc                  = 49,
        .oversampling_shift     = 2,
};
default_ts_data定义在arch/arm/plat-samsung/devs.c文件中的,我们需要把s3c_device_ts成员里初始化的这些常量数据 抽离到设备树中。
1.2 platform driver

名字为"s3c2410-ts"的platform driver定义在drivers/input/touchscreen/s3c2410_ts.c文件:

static const struct dev_pm_ops s3c_ts_pmops = {
        .suspend        = s3c2410ts_suspend,
        .resume         = s3c2410ts_resume,
};
#endif

static const struct platform_device_id s3cts_driver_ids[] = {  
        { "s3c2410-ts", 0 },
        { "s3c2440-ts", 0 },
        { "s3c64xx-ts", FEAT_PEN_IRQ },
        { }
};
MODULE_DEVICE_TABLE(platform, s3cts_driver_ids);

static struct platform_driver s3c_ts_driver = {
        .driver         = {
                .name   = "samsung-ts",
#ifdef CONFIG_PM
                .pm     = &s3c_ts_pmops,
#endif
        },
        .id_table       = s3cts_driver_ids,
        .probe          = s3c2410ts_probe,
        .remove         = s3c2410ts_remove,
};

module_platform_driver(s3c_ts_driver);
1.3 s3c2410ts_probe

当platform设备和驱动匹配后,将会调用s3c2410ts_probe进行input设备的注册。函数定义在drivers/input/touchscreen/s3c2410_ts.c:

/**
 * s3c2410ts_probe - device core probe entry point
 * @pdev: The device we are being bound to.
 *
 * Initialise, find and allocate any resources we need to run and then
 * register with the ADC and input systems.
 */
static int s3c2410ts_probe(struct platform_device *pdev)
{
        struct s3c2410_ts_mach_info *info;
        struct device *dev = &pdev->dev;
        struct input_dev *input_dev;
        struct resource *res;
        int ret = -EINVAL;

        /* Initialise input stuff */
        memset(&ts, 0, sizeof(struct s3c2410ts));

        ts.dev = dev;

        info = dev_get_platdata(dev);          
        if (!info) {
                dev_err(dev, "no platform data, cannot attach\n");
                return -EINVAL;
        }

        dev_dbg(dev, "initialising touchscreen\n");

        ts.clock = clk_get(dev, "adc");        
        if (IS_ERR(ts.clock)) {
                dev_err(dev, "cannot get adc clock source\n");
                return -ENOENT;
        }

        ret = clk_prepare_enable(ts.clock);    
        if (ret) {
                dev_err(dev, "Failed! to enabled clocks\n");
                goto err_clk_get;
        }
        dev_dbg(dev, "got and enabled clocks\n");

        ts.irq_tc = ret = platform_get_irq(pdev, 0);     
        if (ret < 0) {
                dev_err(dev, "no resource for interrupt\n");
                goto err_clk;
        }

        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
        if (!res) {
                dev_err(dev, "no resource for registers\n");
                ret = -ENOENT;
                goto err_clk;
        }

        ts.io = ioremap(res->start, resource_size(res));
        if (ts.io == NULL) {
                dev_err(dev, "cannot map registers\n");
                ret = -ENOMEM;
                goto err_clk;
        }

        /* inititalise the gpio */
        if (info->cfg_gpio)
                info->cfg_gpio(to_platform_device(ts.dev));

        ts.client = s3c_adc_register(pdev, s3c24xx_ts_select,
                                     s3c24xx_ts_conversion, 1);
        if (IS_ERR(ts.client)) {
                dev_err(dev, "failed to register adc client\n");
                ret = PTR_ERR(ts.client);
                goto err_iomap;
        }

        /* Initialise registers */
        if ((info->delay & 0xffff) > 0)
                writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY);

        writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);

        input_dev = input_allocate_device();
        if (!input_dev) {
                dev_err(dev, "Unable to allocate the input device !!\n");
                ret = -ENOMEM;
                goto err_iomap;
        }

        ts.input = input_dev;
        ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
        ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
        input_set_abs_params(ts.input, ABS_X, 0, 0x3FF, 0, 0);
        input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0);

        ts.input->name = "S3C24XX TouchScreen";
        ts.input->id.bustype = BUS_HOST;
        ts.input->id.vendor = 0xDEAD;
        ts.input->id.product = 0xBEEF;
        ts.input->id.version = 0x0102;

        ts.shift = info->oversampling_shift;
        ts.features = platform_get_device_id(pdev)->driver_data;

        ret = request_irq(ts.irq_tc, stylus_irq, 0,
                          "s3c2410_ts_pen", ts.input);
        if (ret) {
                dev_err(dev, "cannot get TC interrupt\n");
                goto err_inputdev;
        }

        dev_info(dev, "driver attached, registering input device\n");

        /* All went ok, so register to the input system */
        ret = input_register_device(ts.input);
        if (ret < 0) {
                dev_err(dev, "failed to register input device\n");
                ret = -EIO;
                goto err_tcirq;
        }

        r
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux 设备驱动开发详解 linuxdriver_code_tool |-- 03 | `-- 2.6内核升级工具 | |-- device-mapper-1.00.19-2.i386.rpm | |-- lvm2-2.00.25-1.01.i386.rpm | |-- mkinitrd-4.2.0.3.tar.tar | |-- module-init-tools-3.2.2.tar.bz2 | `-- modutils-2.4.5-1.src.rpm |-- 04 | |-- 内核模块参数范例 | | `-- book.c | |-- 内核模块导出符号 | | `-- export_symb.c | `-- 最简单的内核模块 | `-- hello.c |-- 05 | `-- udev源代码 | `-- udev-114.tar.gz |-- 06 | |-- globalmem驱动 | | `-- globalmem.c | `-- 包含2个globalmem设备驱动 | `-- globalmem_two.c |-- 07 | `-- 含并发控制的globalmem驱动 | `-- globalmem_lock.c |-- 08 | |-- globalfifo驱动 | | `-- globalfifo.c | `-- poll应用程序范例 | `-- pollmonitor.c |-- 09 | |-- 异步通知应用程序范例 | | `-- asyncmonitor.c | `-- 支持异步通知的globalfifo | `-- globalfifo_async.c |-- 10 | |-- S3C2410实时钟驱动 | | `-- s3c2410-rtc.c | `-- 秒设备驱动与应用程序 | |-- second.c | `-- second_test.c |-- 11 | |-- DMA范例 | | |-- 3c505.c | | |-- 3c505.h | | `-- dma.h | `-- 静态映射范例 | `-- mach-smdk2440.c |-- 12 | |-- NVRAM驱动 | | `-- generic_nvram.c | |-- 触摸屏驱动 | | |-- 作为input设备 | | | |-- s3c2410_ts.c | | | `-- s3c2410_ts.h | | `-- 作为普通字符设备 | | `-- s3c2410-ts.c | |-- 看门狗驱动 | | `-- s3c2410_wdt.c | `-- 平台设备 | `-- devs.c |-- 13 | |-- IDE驱动 | | |-- ide-disk.c | | `-- ide-h8300.c | `-- RAMDISK驱动 | `-- rd.c |-- 14 | |-- S3C2410串口驱动 | | |-- regs-gpio.h | | |-- regs-serial.h | | `-- s3c2410.c | `-- 串口核心层 | |-- serial_core.c | `-- serial_core.h |-- 15 | |-- S3C2410 I2C主机驱动 | | |-- i2c-s3c2410.c | | |-- iic.h | | |-- regs-gpio.h | | `-- regs-iic.h | `-- SAA711x I2C设备驱动 | `-- saa711x.c |-- 16 | `-- CS8900以太网设备驱动 | |-- cs89x0.c | `-- cs89x0.h |-- 17 | |-- ALSA工具及库 | | |-- alsa-driver-1.0.15.tar.bz2 | | |-- alsa-firmware-1.0.15.tar.bz2 | | |-- alsa-lib-1.0.15.tar.bz2 | | |-- alsa-oss-1.0.15.tar.bz2 | | |-- alsa-tools-1.0.15.tar.bz2 | | |-- alsa-utils-1.0.13.tar.bz2 | | `-- pyalsa-1.0.15.tar.bz2 | |-- ALSA驱动范例 | | |-- sa11xx-uda1341.c | | `-- uda1341.h | |-- ALSA应用程序范例 | | |-- pcm.c | | `-- pcm_min.c | |-- OSS驱动范例 | | `-- s3c2410-uda1341.c | `-- OSS应用程序范例 | |-- mixer.c | `-- sound.c |-- 18 | |-- FRAMEBUFFER应用程序范例 | | `-- fb_display | | |-- fb_display.c | | |-- fb_display.h | | |-- Makefile | | |-- README | | `-- test.c | `-- S3C2410 LCD驱动 | |-- s3c2410fb.c | `-- s3c2410fb.h |-- 19 | |-- busybox源代码 | | `-- busybox-1.2.1.tar.bz2 | |-- MTD工具 | | `-- mtd-utils-1.0.0.tar.gz | |-- nand驱动范例 | | `-- s3c2410.c | |-- nor驱动范例 | | `-- s3c2410nor.c | `-- yaffs&yaffs2源代码 | |-- yaffs.tar.gz | `-- yaffs2.tar.gz |-- 20 | |-- USB串口驱动 | | |-- usb-serial.c | | `-- usb-serial.h | |-- USB工具 | | `-- usbview-1.0.tar.tar | |-- USB骨架程序 | | `-- usb-skeleton.c | |-- USB键盘驱动 | | |-- input.h | | |-- usb_input.h | | `-- usbkbd.c | `-- usb主机控制器驱动范例 | |-- ohci-s3c2410.c | `-- usb-control.h |-- 21 | |-- PCI骨架程序 | | `-- pci-skeleton.c | `-- PCI驱动范例 | `-- i810_audio.c `-- 22 |-- 范例代码 | |-- oops范例 | | |-- oops_example.asm | | `-- oops_example.c | `-- proc范例 | `-- sim_proc.c `-- 内核调试工具 |-- ddd-3.3.11.tar.gz |-- gdbmod-2.4.bz2 |-- kdb-v4.4-2.6.15-rc5-common-1.bz2 |-- kdb-v4.4-2.6.15-rc5-common-2.bz2 |-- kdb-v4.4-2.6.15-rc5-i386-1.bz2 `-- linux-2.6.15.5-kgdb-2.4.tar.tar 73 directories, 91 files

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Graceful_scenery

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值