From patchwork Fri Jul 29 08:43:16 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Guo X-Patchwork-Id: 1019242 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6T8VYMd024296 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 29 Jul 2011 08:31:55 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QmiTY-0003oS-CX; Fri, 29 Jul 2011 08:31:20 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QmiTX-00054W-T5; Fri, 29 Jul 2011 08:31:19 +0000 Received: from mail-gy0-f177.google.com ([209.85.160.177]) by canuck.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QmiTT-000544-SP for linux-arm-kernel@lists.infradead.org; Fri, 29 Jul 2011 08:31:17 +0000 Received: by gya1 with SMTP id 1so2753500gya.36 for ; Fri, 29 Jul 2011 01:31:11 -0700 (PDT) Received: by 10.68.28.129 with SMTP id b1mr1762308pbh.438.1311928270964; Fri, 29 Jul 2011 01:31:10 -0700 (PDT) Received: from localhost.localdomain ([114.216.156.189]) by mx.google.com with ESMTPS id k3sm1906283pbj.93.2011.07.29.01.31.03 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 29 Jul 2011 01:31:09 -0700 (PDT) From: Shawn Guo To: netdev@vger.kernel.org Subject: [PATCH v2] net/smsc911x: add device tree probe support Date: Fri, 29 Jul 2011 16:43:16 +0800 Message-Id: <1311928996-10729-1-git-send-email-shawn.guo@linaro.org> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1311587040-8988-1-git-send-email-shawn.guo@linaro.org> References: <1311587040-8988-1-git-send-email-shawn.guo@linaro.org> X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110729_043116_208039_8E548429 X-CRM114-Status: GOOD ( 23.06 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.160.177 listed in list.dnswl.org] Cc: patches@linaro.org, devicetree-discuss@lists.ozlabs.org, Grant Likely , Steve Glendinning , Shawn Guo , "David S. Miller" , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 29 Jul 2011 08:31:55 +0000 (UTC) It adds device tree probe support for smsc911x driver. Signed-off-by: Shawn Guo Cc: Grant Likely Cc: Steve Glendinning Cc: David S. Miller Reviewed-by: Grant Likely --- Changes since v1: * Instead of getting irq line from gpio number, it use irq domain to keep platform_get_resource(IORESOURCE_IRQ) works for dt too. * Use 'lan9115' the first model that smsc911x supports in the match table * Use reg-shift and reg-io-width which already used in of_serial for shift and access size binding Documentation/devicetree/bindings/net/smsc911x.txt | 38 +++++++++ drivers/net/smsc911x.c | 85 +++++++++++++++++--- 2 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/smsc911x.txt diff --git a/Documentation/devicetree/bindings/net/smsc911x.txt b/Documentation/devicetree/bindings/net/smsc911x.txt new file mode 100644 index 0000000..271c454 --- /dev/null +++ b/Documentation/devicetree/bindings/net/smsc911x.txt @@ -0,0 +1,38 @@ +* Smart Mixed-Signal Connectivity (SMSC) LAN911x/912x Controller + +Required properties: +- compatible : Should be "smsc,lan", "smsc,lan9115" +- reg : Address and length of the io space for SMSC LAN +- interrupts : Should contain SMSC LAN interrupt line +- interrupt-parent : Should be the phandle for the interrupt controller + that services interrupts for this device +- phy-mode : String, operation mode of the PHY interface. + Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii", + "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii". + +Optional properties: +- reg-shift : Specify the quantity to shift the register offsets by +- reg-io-width : Specify the size (in bytes) of the IO accesses that + should be performed on the device. Valid value for SMSC LAN is + 2 or 4. If it's omitted or invalid, the size would be 2. +- smsc,irq-active-high : Indicates the IRQ polarity is active-low +- smsc,irq-push-pull : Indicates the IRQ type is push-pull +- smsc,force-internal-phy : Forces SMSC LAN controller to use + internal PHY +- smsc,force-external-phy : Forces SMSC LAN controller to use + external PHY +- smsc,save-mac-address : Indicates that mac address needs to be saved + before resetting the controller +- local-mac-address : 6 bytes, mac address + +Examples: + +lan9220@f4000000 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0xf4000000 0x2000000>; + phy-mode = "mii"; + interrupt-parent = <&gpio1>; + interrupts = <31>; + reg-io-width = <4>; + smsc,irq-push-pull; +}; diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index b9016a3..75c08a5 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -53,6 +53,10 @@ #include #include #include +#include +#include +#include +#include #include "smsc911x.h" #define SMSC_CHIPNAME "smsc911x" @@ -2095,8 +2099,58 @@ static const struct smsc911x_ops shifted_smsc911x_ops = { .tx_writefifo = smsc911x_tx_writefifo_shift, }; +#ifdef CONFIG_OF +static int __devinit smsc911x_probe_config_dt( + struct smsc911x_platform_config *config, + struct device_node *np) +{ + const char *mac; + u32 width = 0; + + if (!np) + return -ENODEV; + + config->phy_interface = of_get_phy_mode(np); + + mac = of_get_mac_address(np); + if (mac) + memcpy(config->mac, mac, ETH_ALEN); + + of_property_read_u32(np, "reg-shift", &config->shift); + + of_property_read_u32(np, "reg-io-width", &width); + if (width == 4) + config->flags |= SMSC911X_USE_32BIT; + + if (of_get_property(np, "smsc,irq-active-high", NULL)) + config->irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH; + + if (of_get_property(np, "smsc,irq-push-pull", NULL)) + config->irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL; + + if (of_get_property(np, "smsc,force-internal-phy", NULL)) + config->flags |= SMSC911X_FORCE_INTERNAL_PHY; + + if (of_get_property(np, "smsc,force-external-phy", NULL)) + config->flags |= SMSC911X_FORCE_EXTERNAL_PHY; + + if (of_get_property(np, "smsc,save-mac-address", NULL)) + config->flags |= SMSC911X_SAVE_MAC_ADDRESS; + + return 0; +} +#else +static inline int smsc911x_probe_config_dt( + struct smsc911x_platform_config *config, + struct device_node *np) +{ + return -ENODEV; +} +#endif /* CONFIG_OF */ + static int __devinit smsc911x_drv_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct net_device *dev; struct smsc911x_data *pdata; struct smsc911x_platform_config *config = pdev->dev.platform_data; @@ -2107,13 +2161,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) pr_info("Driver version %s\n", SMSC_DRV_VERSION); - /* platform data specifies irq & dynamic bus configuration */ - if (!pdev->dev.platform_data) { - pr_warn("platform_data not provided\n"); - retval = -ENODEV; - goto out_0; - } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smsc911x-memory"); if (!res) @@ -2152,9 +2199,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; pdata->ioaddr = ioremap_nocache(res->start, res_size); - /* copy config parameters across to pdata */ - memcpy(&pdata->config, config, sizeof(pdata->config)); - pdata->dev = dev; pdata->msg_enable = ((1 << debug) - 1); @@ -2164,10 +2208,22 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) goto out_free_netdev_2; } + retval = smsc911x_probe_config_dt(&pdata->config, np); + if (retval && config) { + /* copy config parameters across to pdata */ + memcpy(&pdata->config, config, sizeof(pdata->config)); + retval = 0; + } + + if (retval) { + SMSC_WARN(pdata, probe, "Error smsc911x config not found"); + goto out_unmap_io_3; + } + /* assume standard, non-shifted, access to HW registers */ pdata->ops = &standard_smsc911x_ops; /* apply the right access if shifting is needed */ - if (config->shift) + if (pdata->config.shift) pdata->ops = &shifted_smsc911x_ops; retval = smsc911x_init(dev); @@ -2314,6 +2370,12 @@ static const struct dev_pm_ops smsc911x_pm_ops = { #define SMSC911X_PM_OPS NULL #endif +static const struct of_device_id smsc911x_dt_ids[] = { + { .compatible = "smsc,lan9115", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, smsc911x_dt_ids); + static struct platform_driver smsc911x_driver = { .probe = smsc911x_drv_probe, .remove = __devexit_p(smsc911x_drv_remove), @@ -2321,6 +2383,7 @@ static struct platform_driver smsc911x_driver = { .name = SMSC_CHIPNAME, .owner = THIS_MODULE, .pm = SMSC911X_PM_OPS, + .of_match_table = smsc911x_dt_ids, }, };