From patchwork Thu Jun 23 18:38:23 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Shawn Guo X-Patchwork-Id: 2279 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id DDE4123F6D for ; Thu, 23 Jun 2011 18:32:56 +0000 (UTC) Received: from mail-qy0-f180.google.com (mail-qy0-f180.google.com [209.85.216.180]) by fiordland.canonical.com (Postfix) with ESMTP id 929BDA18632 for ; Thu, 23 Jun 2011 18:32:56 +0000 (UTC) Received: by qyk30 with SMTP id 30so1539381qyk.11 for ; Thu, 23 Jun 2011 11:32:56 -0700 (PDT) Received: by 10.229.137.149 with SMTP id w21mr1883160qct.59.1308853975968; Thu, 23 Jun 2011 11:32:55 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.230.139 with SMTP id jm11cs27246qcb; Thu, 23 Jun 2011 11:32:55 -0700 (PDT) Received: by 10.224.200.137 with SMTP id ew9mr1989248qab.51.1308853974522; Thu, 23 Jun 2011 11:32:54 -0700 (PDT) Received: from VA3EHSOBE009.bigfish.com (va3ehsobe006.messaging.microsoft.com [216.32.180.16]) by mx.google.com with ESMTPS id t39si2388113qcs.25.2011.06.23.11.32.52 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 23 Jun 2011 11:32:53 -0700 (PDT) Received-SPF: neutral (google.com: 216.32.180.16 is neither permitted nor denied by best guess record for domain of r65073@freescale.com) client-ip=216.32.180.16; Authentication-Results: mx.google.com; spf=neutral (google.com: 216.32.180.16 is neither permitted nor denied by best guess record for domain of r65073@freescale.com) smtp.mail=r65073@freescale.com Received: from mail121-va3-R.bigfish.com (10.7.14.243) by VA3EHSOBE009.bigfish.com (10.7.40.29) with Microsoft SMTP Server id 14.1.225.22; Thu, 23 Jun 2011 18:32:51 +0000 Received: from mail121-va3 (localhost.localdomain [127.0.0.1]) by mail121-va3-R.bigfish.com (Postfix) with ESMTP id 5E4FB1508189; Thu, 23 Jun 2011 18:32:51 +0000 (UTC) X-SpamScore: -10 X-BigFish: VS-10(zz1dbaL1432N98dKc8kzz1202hzzz2dh2a8h668h839h61h) X-Spam-TCS-SCL: 0:0 X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPVD:NLI; H:mail.freescale.net; RD:none; EFVD:NLI Received: from mail121-va3 (localhost.localdomain [127.0.0.1]) by mail121-va3 (MessageSwitch) id 130885397139940_2887; Thu, 23 Jun 2011 18:32:51 +0000 (UTC) Received: from VA3EHSMHS022.bigfish.com (unknown [10.7.14.243]) by mail121-va3.bigfish.com (Postfix) with ESMTP id D6C061D004D; Thu, 23 Jun 2011 18:32:50 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS022.bigfish.com (10.7.99.32) with Microsoft SMTP Server (TLS) id 14.1.225.22; Thu, 23 Jun 2011 18:32:43 +0000 Received: from az33smr02.freescale.net (10.64.34.200) by 039-SN1MMR1-001.039d.mgd.msft.net (10.84.1.13) with Microsoft SMTP Server id 14.1.289.8; Thu, 23 Jun 2011 13:32:31 -0500 Received: from S2100-06.ap.freescale.net (S2100-06.ap.freescale.net [10.192.242.125]) by az33smr02.freescale.net (8.13.1/8.13.0) with ESMTP id p5NIWQAU018269; Thu, 23 Jun 2011 13:32:27 -0500 (CDT) Date: Fri, 24 Jun 2011 02:38:23 +0800 From: Shawn Guo To: Grant Likely CC: , , , Jason Liu , , Jeremy Kerr , Sascha Hauer , , David Gibson Subject: Re: [PATCH 1/3] serial/imx: add device tree support Message-ID: <20110623183821.GA19188@S2100-06.ap.freescale.net> References: <1308410354-21387-1-git-send-email-shawn.guo@linaro.org> <1308410354-21387-2-git-send-email-shawn.guo@linaro.org> <20110618161934.GH8195@ponder.secretlab.ca> <20110619073000.GA23171@S2100-06.ap.freescale.net> <20110621135558.GB9228@S2101-09.ap.freescale.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-OriginatorOrg: freescale.com On Tue, Jun 21, 2011 at 01:13:50PM -0600, Grant Likely wrote: [...] > > > >  /** > > + *     of_get_device_index - Get device index by looking up "aliases" node > > + *     @np:    Pointer to device node that asks for device index > > + *     @name:  The device alias without index number > > + * > > + *     Returns the device index if find it, else returns -ENODEV. > > + */ > > +int of_get_device_index(struct device_node *np, const char *alias) > > +{ > > +       struct device_node *aliases = of_find_node_by_name(NULL, "aliases"); > > +       struct property *prop; > > +       char name[32]; > > +       int index = 0; > > + > > +       if (!aliases) > > +               return -ENODEV; > > + > > +       while (1) { > > +               snprintf(name, sizeof(name), "%s%d", alias, index); > > +               prop = of_find_property(aliases, name, NULL); > > +               if (!prop) > > +                       return -ENODEV; > > +               if (np == of_find_node_by_path(prop->value)) > > +                       break; > > +               index++; > > +       } > > Rather than parsing the alias strings everytime, it would probably be > better to preprocess all the properties in the aliases node and create > a lookup table of alias->node references that can be walked quickly > and trivially. > > Also, when obtaining an enumeration for a device, you'll need to be > careful about what number gets returned. If the node doesn't match a > given alias, but aliases do exist for other devices of like type, then > you need to be careful not to assign a number already assigned to > another device via an alias (this of course assumes the driver > supports dynamics enumeration, which many drivers will). It would be > Grant, please take a look at the second shot below. Please let me know what you think. diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts index 7976932..f4a5c3c 100644 --- a/arch/arm/boot/dts/imx51-babbage.dts +++ b/arch/arm/boot/dts/imx51-babbage.dts @@ -18,6 +18,12 @@ compatible = "fsl,imx51-babbage", "fsl,imx51"; interrupt-parent = <&tzic>; + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + }; + chosen { bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait"; }; @@ -47,29 +53,29 @@ reg = <0x70000000 0x40000>; ranges; - uart@7000c000 { - compatible = "fsl,imx51-uart", "fsl,imx-uart"; + uart2: uart@7000c000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; reg = <0x7000c000 0x4000>; interrupts = <33>; id = <3>; fsl,has-rts-cts; }; }; - uart@73fbc000 { - compatible = "fsl,imx51-uart", "fsl,imx-uart"; + uart0: uart@73fbc000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; reg = <0x73fbc000 0x4000>; interrupts = <31>; id = <1>; fsl,has-rts-cts; }; - uart@73fc0000 { - compatible = "fsl,imx51-uart", "fsl,imx-uart"; + uart1: uart@73fc0000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; reg = <0x73fc0000 0x4000>; interrupts = <32>; id = <2>; fsl,has-rts-cts; }; }; diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c index 8bfdb91..e6c7298 100644 --- a/arch/arm/mach-mx5/imx51-dt.c +++ b/arch/arm/mach-mx5/imx51-dt.c @@ -40,6 +40,8 @@ static const struct of_device_id tzic_of_match[] __initconst = { static void __init imx51_dt_init(void) { + of_scan_aliases(); + irq_domain_generate_simple(tzic_of_match, MX51_TZIC_BASE_ADDR, 0); of_platform_populate(NULL, of_default_bus_match_table, diff --git a/drivers/of/base.c b/drivers/of/base.c index 632ebae..90349a2 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -17,12 +17,27 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include #include #include #include +struct alias_devname { + char devname[32]; + struct list_head link; + struct list_head head; +}; + +struct alias_devid { + int devid; + struct device_node *node; + struct list_head link; +}; + +static LIST_HEAD(aliases_lookup); + struct device_node *allnodes; struct device_node *of_chosen; @@ -922,3 +937,170 @@ out_unlock: } #endif /* defined(CONFIG_OF_DYNAMIC) */ +/* + * get_alias_dev_name_id - Get device name and id from alias name + * + * an: The alias name passed in + * dn: The pointer used to return device name + * + * Returns device id which should be the number at the end of alias + * name, otherwise returns -1. + */ +static int get_alias_name_id(char *an, char *dn) +{ + int len = strlen(an); + char *end = an + len; + + while (isdigit(*--end)) + len--; + + end++; + strncpy(dn, an, len); + dn[len] = '\0'; + + return strlen(end) ? simple_strtol(end, NULL, 10) : -1; +} + +/* + * get_an_available_devid - Get an available devid for the given devname + * + * adn: The pointer to the given alias_devname + * + * Returns the available devid + */ +static int get_an_available_devid(struct alias_devname *adn) +{ + int devid = 0; + struct alias_devid *adi; + + while (1) { + bool used = false; + list_for_each_entry(adi, &adn->head, link) { + if (adi->devid == devid) { + used = true; + break; + } + } + + if (!used) + break; + + devid++; + } + + return devid; +} + +/* + * of_scan_aliases - Scan all properties of aliases node and populate the + * global lookup table with the device name and id info + * + * Returns the number of aliases properties found, or error code in error case. + */ +int of_scan_aliases(void) +{ + struct device_node *aliases = of_find_node_by_name(NULL, "aliases"); + struct property *pp; + struct alias_devname *adn; + struct alias_devid *adi; + int ret = 0; + + if (!aliases) { + ret = -ENODEV; + goto out; + } + + for (pp = aliases->properties; pp != NULL; pp = pp->next) { + bool found = false; + char devname[32]; + int devid = get_alias_name_id(pp->name, devname); + + /* We do not want to proceed this sentinel one */ + if (!strcmp(pp->name, "name") && !strcmp(pp->value, "aliases")) + break; + + /* See if the devname already exists */ + list_for_each_entry(adn, &aliases_lookup, link) { + if (!strcmp(adn->devname, devname)) { + found = true; + break; + } + } + + /* + * Create the entry for this devname if not found, + * and add it into aliases_lookup + */ + if (!found) { + adn = kzalloc(sizeof(*adn), GFP_KERNEL); + if (!adn) { + ret = -ENOMEM; + goto out; + } + + strcpy(adn->devname, devname); + INIT_LIST_HEAD(&adn->head); + list_add_tail(&adn->link, &aliases_lookup); + } + + /* + * Save the devid as one entry of the list for this + * specified devname + */ + adi = kzalloc(sizeof(*adi), GFP_KERNEL); + if (!adi) { + ret = -ENOMEM; + goto out; + } + + adi->devid = (devid == -1) ? get_an_available_devid(adn) : + devid; + adi->node = of_find_node_by_path(pp->value); + + list_add_tail(&adi->link, &adn->head); + ret++; + } + +out: + return ret; +} + +/** + * of_get_device_id - Get device id by looking up "aliases" node + * @np: Pointer to device node that asks for device id + * @name: The device alias name + * + * Returns the device id if find it, else returns -ENODEV. + */ +int of_get_device_id(struct device_node *np, const char *name) +{ + struct alias_devname *adn; + struct alias_devid *adi; + bool found = false; + int ret; + + list_for_each_entry(adn, &aliases_lookup, link) { + if (!strcmp(adn->devname, name)) { + found = true; + break; + } + } + + if (!found) { + ret = -ENODEV; + goto out; + } + + found = false; + list_for_each_entry(adi, &adn->head, link) { + if (np == adi->node) { + found = true; + break; + } + } + + ret = found ? adi->devid : -ENODEV; +out: + return ret; +} +EXPORT_SYMBOL(of_get_device_id); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 2769353..062639e 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1225,43 +1265,33 @@ static int serial_imx_resume(struct platform_device *dev) return 0; } static int serial_imx_probe_dt(struct imx_port *sport, struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; - const __be32 *line; + int line; if (!node) return -ENODEV; - line = of_get_property(node, "id", NULL); - if (!line) + line = of_get_device_id(node, "serial"); + if (IS_ERR_VALUE(line)) return -ENODEV; - sport->port.line = be32_to_cpup(line) - 1; + sport->port.line = line; diff --git a/include/linux/of.h b/include/linux/of.h index bfc0ed1..270c671 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -213,6 +213,9 @@ extern int of_parse_phandles_with_args(struct device_node *np, const char *list_name, const char *cells_name, int index, struct device_node **out_node, const void **out_args); +extern int of_scan_aliases(void); +extern int of_get_device_id(struct device_node *np, const char *name); + extern int of_machine_is_compatible(const char *compat); extern int prom_add_property(struct device_node* np, struct property* prop); -- Regards, Shawn