In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)05/31 Report--
This article focuses on "how to use Linux's Platform bus structure". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to use Linux's Platform bus structure.
I. concept
There are many physical buses in embedded systems: I2C, SPI, USB, uart, PCIE, APB, AHB
Linux has added a new set of driver management and registration mechanism platform platform bus since 2.6. it is a virtual bus, not a physical bus.
Compared with PCI and USB, it is mainly used to describe on-chip resources on SOC. The resources described by platform have one thing in common: they are addressed directly on CPU's bus.
The platform device is assigned a name (used in the driver binding) and a series of resources such as address and interrupt request number (IRQ).
The device is represented by platform_device and the driver is registered with platform_driver.
Compared with the traditional bus/device/driver mechanism, platform is uniformly managed by the kernel and uses resources in the driver, which improves the security and portability of the code.
II. Platform
1. The two most important structures of platform bus
All drivers maintained by platform must be defined with this structure:
Platform_driver
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 (* resume) (struct platform_device *); struct device_driver driver; const struct platform_device_id * id_table; bool prevent_deferred_probe;}
The structure is used to register the driver to the platform bus
Member meaning probe when the driver and hardware information match successfully, the probe function is called, and the registration and initialization of all the driver resources are placed in the probe function. The remove hardware information is removed, or the driver is uninstalled and all are to be released. The operation of releasing resources is placed in this function. All drivers maintained by the struct device_driver driver kernel must contain this member. Usually driver- > name is used to match devices const struct platform_device_id * id_table often one driver may be able to support multiple hardware at the same time, and the names of these hardware are put in the structure array
When we write drivers, we often need to fill in the above members.
Platform_device
The platform bus is used to describe the structure of device hardware information, including all the resources of the hardware (io,memory, interrupt, DMA, etc.).
Struct platform_device {const char * name; int id; bool id_auto; struct device dev; U32 num_resources; struct resource * resource; const struct platform_device_id * id_entry; / * MFD cell pointer * / struct mfd_cell * mfd_cell; / * arch specific additions * / struct pdev_archdata archdata;} The name of the const char*name device that is used to match the driver. All devices maintained in the struct devicedev kernel that match the driver must contain this member, the number of u32num_resources resources struct resource*resource describes the resource
Struct devicedev- > release () must be implemented
The member struct resource that describes the hardware information
0x139d0000
Struct resource {resource_size_t start; / / represents the starting value of the resource, and resource_size_t end; / / represents the address of the last byte of the resource. If it is an interrupt, end and satrt have the same const char * name; / / but do not write unsigned long flags; / / resource type struct resource * parent, * sibling, * child;} Type description of flags # define IORESOURCE_MEM 0x00000200 / / memory # define IORESOURCE_IRQ 0x00000400 / / interrupt
All drivers managed by the kernel must contain a hardware called struct device_driver member, / / male description, and must contain struct device structure members. / / female
Struct device_driver {const char * name; struct bus_type * bus; struct module * owner; const char * mod_name; / * used for built-in modules * / bool suppress_bind_attrs; / * disables bind/unbind via sysfs * / const struct of_device_id * of_match_table; const struct acpi_device_id * acpi_match_table; int (* probe) (struct device * dev); int (* remove) (struct device * dev) Void (* shutdown) (struct device * dev); int (* suspend) (struct device * dev, pm_message_t state); int (* resume) (struct device * dev); const struct attribute_group * * groups; const struct dev_pm_ops * pm; struct driver_private * p;}
Where:
Const char * name
Used to match the hardware.
The kernel describes the hardware and must contain struct device structure members:
Struct device {struct device * parent; struct device_private * p; struct kobject kobj; const char * init_name; / * initial name of the device * / const struct device_type * type; struct mutex mutex; / * mutex to synchronize calls to * its driver. * / struct bus_type * bus; / * type of bus device is on * / struct device_driver * driver; / * which driver has allocated this device * / void * platform_data; / * Platform specific data, device core doesn't touch it * / struct dev_pm_info power; struct dev_pm_domain * pm_domain; # ifdef CONFIG_PINCTRL struct dev_pin_info * pins; # endif # ifdef CONFIG_NUMA int numa_node / * NUMA node this device is close to * / # endif U64 * dma_mask;/* dma mask (if dma'able device) * / U64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as not all hardware supports 64 bit addresses for consistent allocations such descriptors. * / struct device_dma_parameters * dma_parms; struct list_head dma_pools; / * dma pools (if dma'ble) * / struct dma_coherent_mem * dma_mem; / * internal for coherent mem override * / # ifdef CONFIG_DMA_CMA struct cma * cma_area; / * contiguous memory area for dma allocations * / # endif / * arch specific additions * / struct dev_archdata archdata; struct device_node * of_node / * associated device tree node * / struct acpi_dev_node acpi_node; / * associated ACPI device node * / dev_t devt; / * dev_t, creates the sysfs "dev" * / U32 id; / * device instance * / spinlock_t devres_lock; struct list_head devres_head; struct klist_node knode_class; struct class * class; const struct attribute_group * * groups; / * optional groups * / void (* release) (struct device * dev) Struct iommu_group * iommu_group; bool offline_disabled:1; bool offline:1;}
Where:
Void (* release) (struct device * dev)
Cannot be empty.
two。 How to register
To register a platform driver
1) register the driver platform_device_register
/ * * platform_device_register-add a platform-level device * @ pdev: platform device we're adding * / int platform_device_register (struct platform_device * pdev) {device_initialize (& pdev- > dev); arch_setup_pdev_archdata (pdev); return platform_device_add (pdev);}
2) Registration device platform_driver_register
# define platform_driver_register (drv)\ _ _ platform_driver_register (drv, THIS_MODULE)
Third, give examples
1. Development steps
The development steps of the driver under the platform bus are:
Equipment
The structure that needs to be implemented is platform_device.
1) initialize resource structure variables
2) initialize platform_device structure variables
3) register the device with the system: platform_device_register.
The above three steps must be completed before the device driver loads, that is, before performing platform_driver_register (), because the driver registration needs to match all registered device names in the kernel.
Add device to the kernel's final call to the device_add function in platform_driver_register ().
The main difference between Platform_device_add and device_add is that there is one more step insert_resource (p, r), that is, platform resources (resource) are added to the kernel and managed by the kernel.
Drive
The structure that needs to be implemented in driver registration is: platform_driver.
In the initialization function of the driver, platform_driver_register () is called to register platform_driver.
It is important to note that the value of the name variable in platform_driver and platform_device must be the same [without considering the device tree, a new article on the device tree will be written later].
In this way, when platform_driver_register () is registered, the value of the name variable in the currently registered platform_driver is compared with the value of the name variable in all registered platform_device, and the registration will be successful only if a platform_device with the same name is found.
When the registration is successful, the platform_driver structure element probe function pointer is called.
Example 1
This example is relatively simple and is only used to test whether platform_driver and platform_device can match successfully.
On the left is the code registered for the platform_device structure, and on the right is the code for the registration of the platform_driver structure.
Platform_driver definition and registration:
1 # include 2 # include 3 # include 4 # include 56 static int hello_probe (struct platform_device * pdev) 7 {8 printk ("match ok\ n"); 9 return 0; 10} 11 static int hello_remove (struct platform_device * pdev) 12 {13 printk ("hello_remove\ n"); 14 return 0 15} 16 static struct platform_driver hello_driver = 17 {18. Probe = hello_probe, 19. Driver.name = "duang", 20. Remove = hello_remove, 21}; 22 static int hello_init (void) 23 {24 printk ("hello_init\ n"); 25 return platform_driver_register (& hello_driver); 26} 27 static void hello_exit (void) 28 {29 printk ("hello_exit\ n") 30 platform_driver_unregister (& hello_driver); 31 return; 32} 33 MODULE_LICENSE ("GPL"); 34 module_init (hello_init); 35 module_exit (hello_exit)
Platform_device definition and registration:
1 # include 2 # include 3 # include 4 # include 5 6 static void hello_release (struct device * dev) 7 {8 return 9} 10 static struct platform_device hello_device = 11 {12. Name = "duang", 13. ID =-1, 14. Dev.release = hello_release, 15}; 16 17 18 static int hello_init (void) 19 {20 printk ("hello_init\ n"); 21 return platform_device_register (& hello_device) 22 23} 24 static void hello_exit (void) 25 {26 printk ("hello_exit\ n"); 27 platform_device_unregister (& hello_device); 28 return; 29} 30 MODULE_LICENSE ("GPL"); 31 module_init (hello_init); 32 module_exit (hello_exit)
This program is only used to test whether the platform framework can match successfully, and struct platform_device hello_device does not set any hardware information.
Makfile
1 ifneq ($(KERNELRELEASE) ) 2 obj-m:=device.o driver.o 3 else 4 KDIR: = / lib/modules/$ (shell uname-r) / build 5 PWD: = $(shell pwd) 6 all: 7 Make-C $(KDIR) mod.c $(PWD) modules 8 clean: 9 rm-f * .ko * .o * .mod.o * .symvers * .cmd * .mod.c * .order 0 endif
The makefile can compile two C files into ko files at the same time.
Compile:
Compile
Compile the resulting file:
Insert a picture description here
Load module
Clear log information sudo dmesg-c
Match is successful.
Example 2
Add hardware information to the structure platform_device and read it in the kernel. This example adds the following information to the structure hello_device:
The base address register address 0x139d0000, the space of which is 0x4
Interrupt number 199 [Note] the actual kernel will calculate a new interrupt number based on HW id (usually a unique ID is defined for each interrupt source when soc equipment soc), and the interrupt number will be recognized by cpu.
Device.c
Struct resource res [] = {[0] = {.start = 0x139d0000, .end = 0x139d0000 + 0x3, .flags = IORESOURCE_MEM,}, [1] = {.start = 199,.end = 199,.flags = IORESOURCE_IRQ,},} Static struct platform_device hello_device = {.name = "duang", .id =-1, .dev.release = hello_release, .num _ resources = ARRAY_SIZE (res), .resource = res,}
Driver.c
Static int hello_probe (struct platform_device * pdev) {printk ("match ok\ n"); printk ("mem =% x\ n", pdev- > resource [0] .start); printk ("irq =% d\ n", pdev- > resource [1] .start); / / Registration interrupt, request memory return 0;}
Recompile, uninstall the module in the first example, and clear log:
Make sudo rmmod device sudo rmmod driver sudo dmesg-c
Execution
As can be seen from the results, the probe function reads the hardware information correctly.
4. How is platform_device managed?
1. No device tree
When there is no device tree, take Samsung Cortex-A8 s5pc100 as an example, the hardware information is placed in the following location
Arch\ arm\ mach-s5pc100\ Mach-smdkc100.c arch\ arm\ plat-samsung\
Register for platform_device
Platform_device definition
The array stores information about the hardware that the kernel needs to initialize.
two。 If there is a device tree
The kernel will have the complete code for device initialization, which will parse and initialize the device tree information and initialize the hardware information to the corresponding linked list when the kernel starts. After the bus matches successfully, the hardware information is passed to the probe () function.
Fourth, other knowledge points related to the bus
1. Kernel bus related structure variables
All buses maintained by the kernel need to register a variable with the following structure.
Struct bus_type {const char * name; const char * dev_name; struct device * dev_root; struct device_attribute * dev_attrs; / * use dev_groups instead * / const struct attribute_group * * bus_groups; const struct attribute_group * * dev_groups; const struct attribute_group * * drv_groups; int (* match) (struct device * dev, struct device_driver * drv); int (* uevent) (struct device * dev, struct kobj_uevent_env * env) Int (* probe) (struct device * dev); int (* remove) (struct device * dev); void (* shutdown) (struct device * dev); int (* online) (struct device * dev); int (* offline) (struct device * dev); int (* suspend) (struct device * dev, pm_message_t state); int (* resume) (struct device * dev); const struct dev_pm_ops * pm; struct iommu_ops * iommu_ops; struct subsys_private * p Struct lock_class_key lock_key;}
The definition of platform bus variable struct bus_type platform_bus_type is as follows:
Struct bus_type platform_bus_type = {.name = "platform", .dev _ groups = platform_dev_groups, .match = platform_match, .uevent = platform_uevent, .pm = & platform_dev_pm_ops,}
The most important member is * * .match * *.
When the hardware information of a device is registered with the platform_bus_type bus, it traverses all the drivers maintained by the platform bus and matches them by name. If they are the same, it means that the hardware information matches the driver, and the platform_driver-> probe function of the driver is called to initialize all the resources of the driver to make the driver effective.
When a driver with a device registers to the platform_bus_type bus, it traverses all the hardware information maintained by the platform bus and matches it by name. If it is the same, it means that the hardware information matches the driver, and the platform_driver-> probe function of the driver is called to initialize all the resources of the driver to make the driver effective.
Registered location
Drivers\ base\ Platform.c
Registration of platform_bus_type
5. Detailed explanation of the registration code process
The advantage of understanding the structure is that it can help us locate the problem.
1. When will the match function be called?
2. When the probe function is called to
The following is the process of invoking the above two problem codes:
At this point, I believe you have a deeper understanding of "how to use Linux's Platform bus structure". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.