"Turn" (DT Series IV) drive loading, how to get the properties in device tree

Source: Internet
Author: User

Original URL: http://www.cnblogs.com/biglucky/p/4057488.html

Taking at91rm9200 platform as an example, this paper analyzes how the properties of device tree are obtained when driving loading from the angle of source code implementation.
One: System-level initialization
Dt_machine_start is primarily defined as the type of "struct Machine_desc", placed in section (". Arch.info.init"), which is the initialization data, which is discarded after Kernel up.
#define Dt_machine_start (_name, _namestr) \
static const struct MACHINE_DESC __mach_desc_# #_name \
__used \
__ATTRIBUTE__ ((__section__ (". Arch.info.init")) = {\
. NR = ~0,\
. Name = _namestr,


1,
Dt_machine_start (At91sam_dt, "Atmel At91sam (Device Tree)")
/* Maintainer:atmel */
. Timer = &at91sam926x_timer,
. Map_io = At91_map_io,
. init_early = At91_dt_initialize,
. INIT_IRQ = At91_dt_init_irq,
. Init_machine = At91_dt_device_init,
. Dt_compat = At91_dt_board_compat,
Machine_end


2,
void __init at91_map_io (void)
{
/* MAP Peripherals */
Iotable_init (&at91_io_desc, 1);


At91_soc_initdata.type = At91_soc_none;
At91_soc_initdata.subtype = At91_soc_subtype_none;


Soc_detect (AT91_BASE_DBGU0);
if (!at91_soc_is_detected ())
Soc_detect (AT91_BASE_DBGU1);


if (!at91_soc_is_detected ())
Panic ("at91:impossible to detect the SOC type");


Pr_info ("at91:detected Soc Type:%s\n",
At91_get_soc_type (&at91_soc_initdata));
Pr_info ("At91:detected Soc Subtype:%s\n",
At91_get_soc_subtype (&at91_soc_initdata));


if (!at91_soc_is_enabled ())
Panic ("AT91:SOC not Enabled");


if (at91_boot_soc.map_io)
At91_boot_soc.map_io ();
}


3,
static void __init Soc_detect (u32 dbgu_base)
{
U32 CIDR, Socid;


CIDR = __raw_readl (AT91_IO_P2V (dbgu_base) + AT91_DBGU_CIDR);
Socid = CIDR & ~at91_cidr_version;


Switch (SOCID) {
Case ARCH_ID_AT91RM9200:
At91_soc_initdata.type = at91_soc_rm9200;
AT91_BOOT_SOC = AT91RM9200_SOC;
Break


Case ARCH_ID_AT91SAM9260:
At91_soc_initdata.type = at91_soc_sam9260;
AT91_BOOT_SOC = AT91SAM9260_SOC;
Break
}
}


4,
static inline int at91_soc_is_enabled (void)
{
return at91_boot_soc.init! = NULL;
}


5,
Arch/arm/mach-at91/at91rm9200.c
struct AT91_INIT_SOC __initdata At91rm9200_soc = {
. Map_io = At91rm9200_map_io,
. default_irq_priority = At91rm9200_default_irq_priority,
. ioremap_registers = At91rm9200_ioremap_registers,
. register_clocks = At91rm9200_register_clocks,
. init = At91rm9200_initialize,
};


Second, the actual but simple initialization of the hardware
6,
static void __init at91rm9200_initialize (void)
{
Arm_pm_idle = At91rm9200_idle;
Arm_pm_restart = At91rm9200_restart;


/* Initialize the GPIO subsystem */
At91_gpio_init (At91rm9200_gpio,
CPU_IS_AT91RM9200_BGA ()? AT91RM9200_BGA:AT91RM9200_PQFP);
}


7,
/*
* This function is called when initialized by a particular processor to enable GPIO pin support.
*/
void __init at91_gpio_init (struct at91_gpio_bank *data, int nr_banks)
{
unsigned i;
struct At91_gpio_chip *at91_gpio, *last = NULL;


bug_on (Nr_banks > Max_gpio_banks);


if (Of_at91_gpio_init () < 0) {
/* No GPIO Controller found in device tree */
for (i = 0; i < nr_banks; i++)
At91_gpio_init_one (i, data[i].regbase, data[i].id);
}


for (i = 0; i < gpio_banks; i++) {
At91_gpio = &gpio_chip[i];


/*
* GPIO controller is grouped on some SoC:
* Pioc, Piod and Pioe can share the same IRQ line
*/
if (last && Last->pioc_hwirq = = AT91_GPIO-&GT;PIOC_HWIRQ)
Last->next = At91_gpio;
last = At91_gpio;


Gpiochip_add (&at91_gpio->chip);
}
}


8,
static int __init of_at91_gpio_init (void)
{
struct Device_node *np = NULL;


/*
* This isn ' t ideal, but it gets things hooked up until this
* Driver is converted into a platform_device
*/
/*1, querying operations on properties for each node
2, the hook function uses the scene: When the driver is loaded, device node generates the corresponding platform device. */
For_each_compatible_node (NP, NULL, "Atmel,at91rm9200-gpio")
Of_at91_gpio_init_one (NP);


Return gpio_banks > 0? 0:-einval;
}


Third, the actual property lookup process
9,
#define FOR_EACH_COMPATIBLE_NODE (DN, type, compatible) \
for (DN = Of_find_compatible_node (NULL, type, compatible); DN; \
DN = Of_find_compatible_node (DN, type, compatible))


10,
/**
* Of_find_compatible_node-find a node based on type and one of the
* Tokens in it "compatible" property
* @from: The node to start searching from or NULL, the node
* you pass won't is searched, only the next one
* would; Typically, what's the previous call
* Returned. Of_node_put () 'll be called on it
* @type: The type string to match ' Device_type ' or NULL to ignore
* @compatible: The string to match to one of the tokens in the device
* "Compatible" list.
*
* Returns a node pointer with RefCount incremented, use
* Of_node_put () on it when done.
*/
A node of the corresponding type is found through the type parameter, and a tokens of the node is in the parameter compatible property.
struct Device_node *of_find_compatible_node (struct Device_node *from,
const char *type, const char *compatible)
{
struct Device_node *np;


Read_lock (&devtree_lock);
NP = from? from->allnext:allnodes;
for (; NP; np = Np->allnext) {
Find the appropriate node by type
if (type
&&! (Np->type && (of_node_cmp (np->type, type) = = 0)))
Continue
Find the appropriate node by property
if (Of_device_is_compatible (NP, compatible) && Of_node_get (NP))
Break
}
Of_node_put (from);
Read_unlock (&devtree_lock);
return NP;
}


11,
Verify that the "Compat" string given is able to match the "compatible" attribute in a device node.
int of_device_is_compatible (const struct Device_node *device,
const char *compat)
{
Const char* CP;
int Cplen, l;


Find the properties of the corresponding node by the given name
CP = Of_get_property (device, "compatible", &cplen);
if (cp = = NULL)
return 0;
while (Cplen > 0) {


Re-verify that its compatible property matches
if (OF_COMPAT_CMP (CP, Compat, strlen (compat)) = = 0)
return 1;
L = strlen (cp) + 1;
CP + = l;
Cplen-= l;
}


return 0;
}


12,
/*
* The property of the corresponding node is found by the given name and its value is returned. If it is not found, it returns NULL.
*/
const void *of_get_property (const struct Device_node *np, const char *name,
int *LENP)
{
This function is really going to find the corresponding property in the device tree
struct Property *pp = Of_find_property (NP, name, LENP);


Return pp? pp->value:null;
}


13,//From the function definition, the return value is changed to the property, which is different than Of_get_property ().
struct Property *of_find_property (const struct Device_node *np,
const Char *name,
int *LENP)
{
struct property *pp;


if (!NP)
return NULL;


Read_lock (&devtree_lock);
for (pp = np->properties; pp! = 0; pp = pp->next) {
Call the basic string comparison function
if (of_prop_cmp (pp->name, name) = = 0) {
if (LENP! = 0)
*LENP = pp->length;
Break
}
}
Read_unlock (&devtree_lock);


Return pp;
}


14,//The property structure of the body
struct Property {
Char *name;
int length;
void *value;
struct property *next;
unsigned long _flags;
unsigned int unique_id;
};


15,//More than a layer of encapsulation, which should be in accordance with the Linux kernel coding specifications, pending confirmation.
#define OF_PROP_CMP (S1, S2) strcasecmp ((S1), (S2))


16,//ignores string comparisons of alphabetic case.
int strcasecmp (const char *S1, const char *S2)
{
int C1, C2;


do {
C1 = ToLower (*s1++);
C2 = ToLower (*s2++);
} while (C1 = = C2 && C1! = 0);
return C1-C2;
}


Four, real hardware initialization via properties
17, (from function 8 turned around)
Final call to the eighth function: For_each_compatible_node ()
After executing this function: Of_at91_gpio_init_one ()
Locate the corresponding property and initialize it with this property .....
static void __init Of_at91_gpio_init_one (struct Device_node *np)
{
int alias_idx;
struct At91_gpio_chip *at91_gpio;


if (!NP)
Return


ALIAS_IDX = of_alias_get_id (NP, "Gpio");
if (Alias_idx >= max_gpio_banks) {
Pr_err ("At91_gpio, failed alias idx (%d) > Max_gpio_banks (%d), ignoring.\n",
Alias_idx, max_gpio_banks);
Return
}


At91_gpio = &gpio_chip[alias_idx];
At91_gpio->chip.base = Alias_idx * at91_gpio->chip.ngpio;


At91_gpio->regbase = Of_iomap (NP, 0);
if (!at91_gpio->regbase) {
Pr_err ("at91_gpio.%d, failed to map registers, ignoring.\n",
ALIAS_IDX);
Return
}


/* Get Interrupt Properties */
if (OF_PROPERTY_READ_U32 (NP, "interrupts", &at91_gpio->pioc_hwirq)) {
Pr_err ("at91_gpio.%d, failed to get interrupts property, ignoring.\n",
ALIAS_IDX);
Goto Ioremap_err;
}


/* Get the relevant "ability" from the compatibility attribute */
if (Of_device_is_compatible (NP, "Atmel,at91sam9x5-gpio"))
At91_gpio_caps |= At91_gpio_cap_pio3;


/* Set Clock */
if (AT91_GPIO_SETUP_CLK (ALIAS_IDX))
Goto Ioremap_err;


At91_gpio->chip.of_node = NP;
Gpio_banks = Max (gpio_banks, Alias_idx + 1);
At91_gpio->pioc_idx = Alias_idx;
Return


Ioremap_err:
Iounmap (at91_gpio->regbase);
}


Five, specific tasks and related references
The above from four parts, through the tracking code, one after another described how the device tree properties to obtain, and play a corresponding role. The following will be analyzed from the perspective of the work task:
Task:
Drive loading in the device tree to get the attributes, what are the key functions, the functions of each
What to use. What is the implementation of the function?


Related references:
Key functions:
1,
Query operations on properties for each node
For_each_compatible_node (NP, NULL, "Atmel,at91rm9200-gpio")
2,
A node of the corresponding type is found through the type parameter, and a tokens of the node is in the parameter compatible property.
Of_find_compatible_node (NULL, type, compatible)
3,
Verify that the "Compat" string given is able to match the "compatible" attribute in a device node.
Of_device_is_compatible (NP, compatible) && Of_node_get (NP))
4,
Find the properties of the corresponding node by the given name
Of_get_property (device, "compatible", &cplen);
5,
From the function definition, the return value changes to the property than Of_get_property ().
Of_find_property (NP, name, LENP);


The use of each function is relatively simple and is a layer call. The final implementation is to invoke the corresponding string comparison function. It is relatively simple to write here, and richer later.

"Turn" (DT Series IV) drive loading, how to get the properties in device tree

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.