I am studying UART Driver in kernel code and want to know, who first comes into picture, device_register()
or driver_register()
call?
For difference between them follow this.
and in UART probing, we call
uart_register_driver(struct uart_driver *drv)
and after successfully registration,
uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
Please explain this in details.
That's actually two questions, but I'll try to address both of them.
who first comes into picture,
device_register()
ordriver_register()
call?
As it stated in Documentation/driver-model/binding.txt, it doesn't matter in which particular order you call device_register()
and driver_register()
.
device_register()
adds device to device list and iterates over driver list to find the matchdriver_register()
adds driver to driver list and iterates over device list to find the matchOnce match is found, matched device and driver are binded and corresponding probe function is called in driver code.
If you are still curious which one is called first (because it doesn't matter) -- usually it's device_register()
, because devices are usually being registered on initcalls from core_initcall
to arch_initcall
, and drivers are usually being registered on device_initcall
, which executed later.
See also:
[1] From where platform device gets it name
[2] Who calls the probe() of driver
[3] module_init() vs. core_initcall() vs. early_initcall()
Difference between
uart_register_driver
andplatform_driver_register
?
As you noticed there are 2 drivers (platform driver and UART driver) for one device. But don't let this confuse you: those are just two driver APIs used in one (in fact) driver. The explanation is simple: UART driver API just lacks some functionality we need, and this functionality is implemented in platform driver API. Here is responsibility of each API in regular tty driver:
Let's use drivers/tty/serial/omap-serial.c
for driver reference and arch/arm/boot/dts/omap5.dtsi
for device reference. Let's say, for example, we have next device described in device tree:
uart1: serial@4806a000 {
compatible = "ti,omap4-uart";
reg = <0x4806a000 0x100>;
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart1";
clock-frequency = <48000000>;
};
It will be matched with platform driver in omap-serial.c
by "ti,omap4-uart"
string (you can find it in driver code). Then, using that platform driver, we can read properties from device tree node above, and use them for some platform stuff (setting up clocks, handling UART interrupt, etc.).
But in order to expose our device as standard TTY device we need to use UART framework (all those uart_*
functions). Hence 2 different APIs: platform driver and UART driver.