Implementation of touch screen driver in Linux (1) - based on s3c6410 processor

Publisher:不染尘埃Latest update time:2022-06-09 Source: eefocusKeywords:linux Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

These articles are mainly about touch screen drivers in Linux, based on the s3c6410 processor. This article is mainly about the implementation of touch screen devices as platform devices, as well as the source code analysis of the corresponding probe function and remove function.


1. Loading and unloading functions of touch screen module


static char banner[] __initdata = KERN_INFO "S3C Touchscreen driver, (c) 2008 Samsung Electronicsn";


static int __init s3c_ts_init(void)

{

printk(banner);

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);


No matter how things change, he remains the same familiar person, but each time is a new journey.


Corresponding platform device resources: in the Dev-ts.c (linux2.6.28archarmplat-s3c) file


/* Touch srcreen */

static struct resource s3c_ts_resource[] = {

[0] = {

.start = S3C_PA_ADC, I/O port

.end = S3C_PA_ADC + SZ_4K - 1,

.flags = IORESOURCE_MEM,

},

[1] = {

.start = IRQ_PENDN, interrupt

.end   = IRQ_PENDN,

.flags = IORESOURCE_IRQ,

},

[2] = {

.start = IRQ_ADC, interrupt

.end   = IRQ_ADC,

.flags = IORESOURCE_IRQ,

}


};

struct platform_device s3c_device_ts = {

.name  = "s3c-ts",

.id  = -1,

.num_resources = ARRAY_SIZE(s3c_ts_resource),

.resource   = s3c_ts_resource,

};


The corresponding platform_driver structure is defined as follows:


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",

},

};


2. I think I should know what to do, then look at the probe function, the source code is as follows:


/*

 * The functions for inserting/removing us as a module.

 */

static int __init s3c_ts_probe(struct platform_device *pdev)

{

struct resource *res;

struct device *dev;

struct input_dev *input_dev;

struct s3c_ts_mach_info * s3c_ts_cfg;

int ret, size;



dev = &pdev->dev;



res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

if (res == NULL) {

dev_err(dev,"no memory resource specifiedn");

return -ENOENT;

} Get the register operation address


size = (res->end - res->start) + 1;

ts_mem = request_mem_region(res->start, size, pdev->name); Apply for this memory area


注:static struct resource*ts_mem;

if (ts_mem == NULL) {

dev_err(dev, "failed to get memory regionn");

right = -ENOENT;

goto err_req;

}



ts_base = ioremap(res->start, size); Mapping

if (ts_base == NULL) {

dev_err(dev, "failed to ioremap() regionn");

ret = -SINGLE SELECT;

goto err_map;

}


ts_clock = clk_get(&pdev->dev, "adc"); Get the clock

if (IS_ERR(ts_clock)) {

dev_err(dev, "failed to find watchdog clock sourcen");

ret = PTR_ERR(ts_clock);

goto err_clk;

}



clk_enable(ts_clock); Enable clock



s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev);


static struct s3c_ts_mach_info *s3c_ts_get_platdata (struct device *dev)

{

if (dev->platform_data != NULL)

return (struct s3c_ts_mach_info *)dev->platform_data;



return &s3c_ts_default_cfg;

}


default value:


/* Touchscreen default configuration */

struct s3c_ts_mach_info s3c_ts_default_cfg __initdata = {

                .delay = 5000,//10000,

                .almost = 49,

                .oversampling_shift = 4,//2,

.resol_bit = 10

};


This involves a structure s3c_ts_mach_info


struct s3c_ts_mach_info {

int delay; delay time

int presc; prescale value

int oversampling_shift; number of conversions

int resol_bit; division rate

enum s3c_adc_types3c_adc_con; see below:

};


Including


enum s3c_adc_type {

ADC_TYPE_0,

ADC_TYPE_1,  /* S3C2416, S3C2450 */

ADC_TYPE_2,/* S3C64XX, S5PC1XX */

};


if ((s3c_ts_cfg->presc&0xff) > 0) set the prescaler value

writel(S3C_ADCCON_PRSCEN | S3C_ADCCON_PRSCVL(s3c_ts_cfg->presc&0xFF),

ts_base+S3C_ADCCON);

else

writel(0, ts_base+S3C_ADCCON); If not defined, write 0, which actually disables pre-scaling


This is mainly related to the setting of the ADCCON register, and has the following definitions:


#define S3C_ADCCON_PRSCEN(1<<14)


#define S3C_ADCCON_PRSCVL(x)(((x)&0xFF)<<6)


See the picture below:

/* Initialize registers */

if ((s3c_ts_cfg->delay&0xffff) > 0)

writel(s3c_ts_cfg->delay & 0xffff, ts_base+S3C_ADCDLY);

Similar to the above, mainly related to the ADCDLY register. See the picture directly: Note: It has different meanings in the two modes

if (s3c_ts_cfg->resol_bit==12) { division rate

switch(s3c_ts_cfg->s3c_adc_con) {

case ADC_TYPE_2:

writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT, ts_base+S3C_ADCCON);

break;


#define S3C_ADCCON_RESSEL_12BIT(0x1<<16)

case ADC_TYPE_1:

writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT_1, ts_base+S3C_ADCCON);

break;


default:

dev_err(dev, "Touchscreen over this type of AP isn't supported !n");

break;

}

}


writel(WAIT4INT(0), ts_base+S3C_ADCTSC); mainly operates the ADCTSC register to put the touch screen in the waiting interrupt mode

ts = kzalloc(sizeof(struct s3c_ts_info), GFP_KERNEL);


注:static struct s3c_ts_info*ts;


input_dev = input_allocate_device(); Apply for and initialize an input device. Through the input device, the driver can interact with the user.

注:struct input_dev *input_dev;

if (!input_dev) {

right = -ENOMEM;

goto err_alloc;

}


ts->dev = input_dev;



ts->dev->evbit[0] = ts->dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);

ts->dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);



if (s3c_ts_cfg->resol_bit==12) {

input_set_abs_params(ts->dev, ABS_X, 0, 0xFFF, 0, 0);

input_set_abs_params(ts->dev, ABS_Y, 0, 0xFFF, 0, 0);

}

else {

input_set_abs_params(ts->dev, ABS_X, 0, 0x3FF, 0, 0);

input_set_abs_params(ts->dev, ABS_Y, 0, 0x3FF, 0, 0);

}



input_set_abs_params(ts->dev, ABS_PRESSURE, 0, 1, 0, 0);



sprintf(ts->phys, "input(ts)");



ts->dev->name = s3c_ts_name;

ts->dev->phys = ts->phys;

ts->dev->id.bustype = BUS_RS232;

ts->dev->id.vendor = 0xDEAD;

ts->dev->id.product = 0xBEEF;

ts->dev->id.version = S3C_TSVERSION;



ts->shift = s3c_ts_cfg->oversampling_shift;

ts->resol_bit = s3c_ts_cfg->resol_bit;

ts->s3c_adc_con = s3c_ts_cfg->s3c_adc_con;


The above code is to initialize the global quantity ts of the touch screen device. The corresponding structure prototype is:


struct s3c_ts_info {

struct input_dev  *dev;

long xp;

long yp;

int count;

int shift;

char phys[32];

int resolve_bit;

enum s3c_adc_types3c_adc_con;

};


/* For IRQ_PENDUP */

ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); Get the touch screen interrupt IRQ_PENDUP

if (ts_irq == NULL) {

dev_err(dev, "no irq resource specifiedn");

right = -ENOENT;

goto err_irq;

}



ret = request_irq(ts_irq->start, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c_updown", ts); Apply for touch screen interrupt, the corresponding interrupt processing function is stylus_updown

if (ret != 0) {

dev_err(dev,"s3c_ts.c: Could not allocate ts IRQ_PENDN !n");

ret = -EIO;

goto err_irq;

}



/* For IRQ_ADC */

ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1); Get ADC interrupt

if (ts_irq == NULL) {

dev_err(dev, "no irq resource specifiedn");

right = -ENOENT;

goto err_irq;

}



ret = request_irq(ts_irq->start, stylus_action, IRQF_SAMPLE_RANDOM, "s3c_action", ts); Apply for ADC interrupt, the corresponding interrupt function is stylus_action

if (ret != 0) {

dev_err(dev, "s3c_ts.c: Could not allocate ts IRQ_ADC !n");

ret = -EIO;

goto err_irq;

}



printk(KERN_INFO "%s got loaded successfully : %d bitsn", s3c_ts_name, s3c_ts_cfg->resol_bit);



/* All went ok, so register to the input system */ Register the touch screen device to the input subsystem

ret = input_register_device(ts->dev);


if(ret) {

dev_err(dev, "s3c_ts.c: Could not register input device(touchscreen)!n");

ret = -EIO;

goto fail;

}



return 0;


These are the error handling codes:

fail:

free_irq(ts_irq->start, ts->dev);

free_irq(ts_irq->end, ts->dev);


err_irq:

input_free_device(input_dev);

kfree(ts);



err_alloc:

clk_disable(ts_clock);

clk_put(ts_clock);


err_clk:

iounmap(ts_base);



err_map:

release_resource(ts_mem);

kfree(ts_mem);



err_req:

return right;

}

At this point, the probe function of the touch screen device driver has been described.


3. Of course, several important functions in the probe function have not been mentioned, that is, about the input subsystem, which is not the focus of our attention now. Next, look at the corresponding remove function, the source code is as follows:


static int s3c_ts_remove(struct platform_device *dev)

{

printk(KERN_INFO "s3c_ts_remove() of TS called !n");



disable_irq(IRQ_ADC);

disable_irq(IRQ_PENDN);


free_irq(IRQ_PENDN, ts->dev);

free_irq(IRQ_ADC, ts->dev);



if (ts_clock) {

clk_disable(ts_clock);

clk_put(ts_clock);

ts_clock = NULL;

}



input_unregister_device(ts->dev);

iounmap(ts_base);



return 0;

}


In fact, if you understand the probe function, you don’t need to read the remove function at all.

Keywords:linux Reference address:Implementation of touch screen driver in Linux (1) - based on s3c6410 processor

Previous article:s3c6410 RTC driver in Linux (5)
Next article:Implementation of touch screen driver in Linux (3) - based on s3c6410 processor

Recommended ReadingLatest update time:2024-11-16 11:52

Novice self-study ARM: Programming under Linux to obtain system time and set time
There are several programmatic ways to get the time: 1 #include stdio.h #include time.h main(){ time_t t; struct tm *p; time(&t); p=gmtime(&t); printf("Year :%d\n",1900+p- tm_year); printf("Month :%d\n",1+p- tm_mon); printf("Day :%d\n",p- tm_mday); printf("Hour :%d\n",p- tm_hour); printf("Minute:%d\n",p-
[Microcontroller]
ARM-Linux s3c2440 interrupt analysis (I)
Hardware: S3C2440 is an arm920T architecture. Let’s first review the interrupt controller principles and related hardware architecture in s3c2440.   Interrupt Controller:   The interrupt controller of S3c2440A has 60 interrupt sources, such as DMA interrupt, UART interrupt, IIC interrupt, etc. The 60 interrupt
[Microcontroller]
ARM-Linux s3c2440 interrupt analysis (I)
Linux-2.6.38 to tiny6410 porting manual (Part 3) __ LCD & touch screen
This time the LCD and touch screen intelligence were transplanted together. As for the reason, I will post a detailed explanation tomorrow. http://www.arm9home.net/read.php?tid-14273.html It is mainly because of the first-line touch, which hijacked the LCD backlight control. It took me three days to find this out. It
[Microcontroller]
Linux system boot process on ARM platform
  Since I started learning embedded development, I have been using Linux as a learning platform. Now, both PC and ARM development board can run Linux smoothly, but I still don’t know much about the Linux boot process. So I started to search Baidu and Google, and of course I saw the introductions written by various expe
[Microcontroller]
Linux system boot process on ARM platform
s3c6410 linux gadget hid driver
The kernel I use is linux2.6.38. At the beginning, the development board can be used as a USB flash drive, but when using the HID function, the following problems occur: g_hid gadget: hid_setup crtl_request : bRequestType:0x21 bRequest:0xa Value:0x0 g_hid gadget: Unknown request 0xa s3c-hsotg s3
[Microcontroller]
How to use camera in embedded Linux system
  Introduction   This article mainly shows an example of using a camera in embedded Linux based on an ARM embedded module system. The module used is Toradex VF61, which is a very cost-effective module that does not include hardware video codec acceleration. The core processor is NXP/Freescale Vybrid, Cortex-A5 and M4
[Microcontroller]
How to use camera in embedded Linux system
s3c6410 pwm learning
The first time I learned by myself, I read the data sheet directly instead of the Chinese materials or sample code explanations of Da Duan. . But this is a process that everyone must go through. let's start! The 6410 RISC microprocessor comprises of five 32-bit  timers. These timers are used to generate internal
[Microcontroller]
s3c6410 pwm learning
Design and implementation of high-speed USB host controller under embedded Linux
In the development history of embedded systems, the Linux operating system has been widely used in the embedded field due to its open source code, clear structure, powerful functions and strong portability. The USB interface has the advantages of hot-swap, plug-and-play, reliable data transmission, convenient expansio
[Microcontroller]
Design and implementation of high-speed USB host controller under embedded Linux
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号