[U-Boot] [PATCH 0/3] dm: add dev_get_reg() for getting device node's reg

Stephen Warren swarren at wwwdotorg.org
Wed Jan 6 20:14:25 CET 2016


On 01/05/2016 05:24 PM, Simon Glass wrote:...
 > I'm not super-keen on dev_get_reg() as it adds confusion - why is one
> reg dealt with differently from another. Perhaps just a different
> name, like dev_get_bus_addr()?
>
> Re Linux, can someone trace through the of_address_to_resource() call
> and see what it actually does? It seems to call of_translate_address()
> but presumably does not suffer from this problem. So maybe I am
> missing something. The S3C I2C driver calls platform_get_resource()
> which is presumably set up by a call to of_address_to_resource()?

At least in ARM DT land, most MMIO devices are "platform devices". There 
are also e.g. PCIe devices, but they're enumerated via HW protocols, not 
by parsing DT.

Construction of a platform device works as follows in the Linux source:

For each node that's found by scanning the DT, a struct platform_device 
is created to represent it, in drivers/of/platform.c of_device_alloc(). 
Note that this scanning process is only performed on DT nodes known to 
represent MMIO buses; recursion into child nodes is explicitly performed 
by drivers for particular nodes, and takes a different path for nodes 
representing non-MMIO buses, as described later, since the node's driver 
will be different. This scanning process is core code that executes 
before the kernel has any idea re: which type of device the child nodes 
represent, or which driver will manage them. This struct contains the 
values of a number of core resource types that are represented in DT, 
such as addresses, IRQs, etc. The address values are filled in via the 
following call stack:

drivers/of/platform.c of_device_alloc()

->

drivers/of/address.c of_address_to_resource()

->

drivers/of/address.c of_get_address()

[reads the reg property, picks out a single index in it, performs BE->LE 
conversion]

then unconditionally calls the following on the address:

drivers/of/address.c __of_address_to_resource()

[translates the address to the CPU address space, then writes the result 
into the supplied pointer, which the caller has set up to point into a 
struct resource associated with the struct platform_device]

->

drivers/of/address.c of_translate_address()

->

drivers/of/address.c __of_translate_address()

This is essentially exactly identical to U-Boot's 
__of_translate_address(), modulo a few printf()/debug() differences, and 
a few more of_node_get/put() calls in order to support dynamic 
modifications to the DT.


The driver for the a DT node is responsible for enumerating (or 
triggering enumeration of) any child nodes. For a node known to 
represent an MMIO bus (e.g. simple-bus), the algorithm above will simply 
be applied recursively. For a node that represents some kind of non-MMIO 
bus controller/host, custom (bus-type-specific) code is typically 
applied. In many cases, this custom code will parse the reg property of 
child nodes according to the semantics of that bus's definition of the 
reg property, and provide that value to the device driver for the child 
node. Examples of reg parsing in Linux are:

drivers/i2c/i2c-core.c of_i2c_register_device() about 20 lines in. Note 
that I2C addresses aren't simple integer values, but also encode some 
flags too, such as 7-vs-10-bit addresses, and whether the DT node 
represents a slave device that Linux should implement, or a regular device.

drivers/spi/spi.c of_register_spi_device() about 20 lines in. Here, the 
address is the identify of the chip select wire, which may be driven by 
the SPI controller, or via GPIOs, depending on the controller HW.

drivers/of/of_mdio.c of_mdio_parse_addr(). Here, the address is a simple 
integer, with a range check.

drivers/mmc/core/core.c mmc_of_find_child_device(). At least SDIO 
buses/devices (as opposed to eMMC/SD devices) appear to be able to host 
multiple functions, and DT appears to be able to represent each function 
as a separate child node of the SDIO controller.

drivers/spmi/spmi.c of_spmi_register_devices() about 10 lines in. I 
don't know what SPMI is, but the interpretation of the reg property in 
this code seems to have a few bus-specific rules.

drivers/nvmem/core.c of_nvmem_cell_get() about 25 lines in. I don't know 
what nvmem is, but reg here seems to be a pretty simple base/size pair.

All of this discussion implies to me that drivers (for buses) really 
should be calling different functions (or executing different local 
custom code) to parse the reg property. The property is interpreted 
quite differently depending on bus type.

Whether that means creating dev_get_addr_mmio() and dev_get_addr_i2c() 
such that dev_get_addr() doesn't unconditionally translate addresses vs. 
moving reg parsing into subsystem core code rather than drivers vs. any 
other solution seems like an implementation detail. The main point is 
that we certainly can't rely on a single dev_get_addr() that just works 
for all reg properties.

All file and line count references above are relative to Linux kernel 
version v4.4-rc8.


More information about the U-Boot mailing list