platform bus (Linux Driver Development)

Briefly introduce the led driver, input device driver, i2c driver and spi driver in platform driver

1.Platform led driver

  • The simplest example of understanding the platform can be understood as three parts, which are composed of driver layer, system core layer and device driver:
    Driver layer: hardware device registration part.
    System core layer: None
    Device driver layer: the implementation of the device end, such as led flashing, etc
    In fact, the reason why it is divided into three parts here is to correspond to the later device driver.

  • Example of using steps:

            (1)platform_device_register(): Registration Platform led equipment
    
            (2)platform_driver_register(): Registration Platform led Drive.
    

2. Platform input driver

  • The Linux system provides an input subsystem. The input of keys, touch screen, keyboard and mouse can be driven by the input interface function.

  • linux is mainly composed of driver layer, input core layer and Event Handler layer.
    1. Driver layer: the hardware device registration part only registers the input device into the input subsystem, and the code itself in the driver layer does not create a node. Corresponding files such as gpio_key.c
    2. Input core: report key, touch screen, keyboard, mouse and other input events to the system (event, described through the input_event structure), so that the driver layer does not need to care about the file operation interface. Corresponding files, such as input
    3. Event Handler: provide input device interface. Corresponding file, such as evdev c,mousedev. C etc.

  • Generally speaking, if you want to use the input subsystem, you only need to change the driver layer.

3. Platform i2c driver

  • In Linux system, i2c driver consists of three parts: i2c bus driver, i2c core and i2c device driver.

  • I2C bus driver: the implementation of the adapter end in the I2C hardware architecture. The adapter can be controlled by the CPU or integrated inside the CPU. Corresponding files, such as i2c-at91 c

  • I2c core: provides the registration and cancellation methods of i2c bus driver and device driver, i2c algorithm. The code irrelevant to the specific adapter and the upper code of the detection device and the address of the detection device. Corresponding files, such as I2c core c

  • I2C device driver: the implementation of the device end in the I2C system hardware structure. The device is generally hung on the I2C adapter controlled by the CPU and exchanges data with the CPU through the I2C adapter. Corresponding files, such as at24 c. I2C dev.c et al.

  • The i2c bus is basically not used for the development of the main chip. Even if there is no i2c bus, it will basically provide i2c for io simulation, that is, the i2c bus driver generally does not need to write or change by itself. The I2c core part doesn't need to be moved, hehe. Therefore, to write an i2c device driver, you only need to write the i2c device driver (here corresponds to one of the three parts of the i2c driver mentioned above).

  • For most i2c device drivers, the kernel has been provided. Moreover, simple applications can also be realized by i2c dev.c.

4.Platform spi driver

  • In Linux system, spi driver consists of three parts: spi bus driver, spi core and spi device driver.

  • SPI bus driver: the implementation of hardware SPI driver. SPI can be integrated inside the main chip or simulated by io port. Corresponding files, such as atmel_spi.c

  • Spi core: provides registration and logout methods for spi bus driver and device driver.

  • spi device driver: the implementation of spi device end in spi architecture.

5. A common feature can be seen from the above simple drivers:

These drivers are basically composed of three parts:

(1) Bus driver: associated with the selected main chip, it is generally provided.

(2) Bus core: independent of the specific hardware, the core has been provided.

(3) Bus device driver: the specific device operated. According to the actual application needs, use or change the driver provided by the kernel, or rewrite a driver yourself.

In fact, most of the devices we have provided can be changed according to the drivers we have provided in the third part.

6.platform introduction

1. Platform bus

  • The platform bus is Linux 2 A virtual bus added by 6 kernel. The platform mechanism itself is not complicated to use and consists of two parts: platform_device and platform_driver

  • Compared with the traditional device driver model, the advantage of platform driver is that the platform mechanism registers the resources of the device itself into the kernel, which is uniformly managed by the kernel, and uses a unified interface when the driver uses these resources, which improves the portability of the program.

2. Workflow

  • Develop the underlying device driven process through platform mechanism:
    1. Write platform_device and register
    2. Write platform_driver and register
  • In the case of using the device tree (because your reception information has been added to the device tree)
    1. Write platform_driver and register

3. Platform equipment description

  • The platform device uses the Struct Platform_device to describe:
struct platform_device {
	const char *name; /*Device name*/
	int id; /*Equipment number, used in conjunction with equipment name*/
	struct device dev;
	u32 num_resources;
	struct resource *resource; /*Equipment resources*/
}

Struct Platform_device Allocation and use of:
struct platform_device *platform_device_alloc(const char *name, int id)
Parameters:
name: Device name
id: equipment id,Generally-1

4. Platform device registration

  • To register a platform device, use the function:
    int platform_device_add(struct platform_device *pdev)

5. Equipment resources

  • Platform device resources are described by struct resource:
struct resource {
resource_size_t start; //The starting physical address of the resource
resource_size_t end; //The end physical address of the resource
const char *name; //Name of the resource
unsigned long flags; //Types of resources, such as MEM, IO, IRQ
struct resource *parent, *sibling, *child; //Resource linked list pointer
}

Equipment resources-Example memory resources
static struct resource s3c_wdt_resource1 = {
.start = 0x44100000,
.end = 0x44200000,
.flags = IORESOURCE_MEM,
}

Interrupt resource
static struct resource s3c_wdt_resource2 = {
.start = 20,
.end = 20,
.flags = IORESOURCE_IRQ,
}

6. Get resources

  • struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num)
    Parameters:
    1) dev: the device to which the resource belongs
    2) Type: the type of resource obtained
    3) num: number of resources obtained
    Example: platform_get_resource(pdev, IORESOURCE_IRQ, 0) gets the interrupt number

7. Platform driven description

  • The platform driver uses struct platform_driver Description:
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
}

8. Platform driver registration

  • Platform driver registration function:
    int platform_driver_register(struct platform_driver *)

9. Case analysis

1) Platform device C source code

#include . . . . . . 

static struct platform_device *my_device;
static int __init my_device_init(void)
{
        int ret = 0;
        /*Assign the device structure, and the name of the device is "my_dev"“*/
        my_device = platform_device_alloc("my_dev", -1);
        /*Register device*/
        ret = platform_device_add(my_device);
        /*Registration failed, releasing related memory*/
        if(ret)
              platform_device_put(my_device);
        return ret;
}

static void my_device_exit(void)
{
        platform_device_unregister(my_device);
}

module_init(my_device_init);
module_exit(my_device_exit);


MODULE_AUTHOR("apple");
MODULE_LICENSE("GPL");

2) Platform driven driver C source code

#include . . . . . . . . 
static int my_probe(struct device *dev)
{
        printk("Drvicer found device which my driver can handle!\n");
        return 0;
}

static int my_remove(struct device *dev)
{
        printk("Driver found device unpluged!\n");
        return 0;
}

static struct platform_driver my_driver = {
        .probe          = my_probe,
        .remove         = my_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "my_dev",   //The name should be consistent with the name of the platform device
        }
};

static int __init my_driver_init(void)
{
        /*Register platform driver*/
        return platform_driver_register(&my_driver);
}

static void my_driver_exit(void)
{
        platform_driver_unregister(&my_driver);
}
module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_AUTHOR("apple");
MODULE_LICENSE("GPL");

Keywords: Linux

Added by petezaman on Sun, 13 Feb 2022 08:43:31 +0200