From patchwork Mon Jul 25 09:44:00 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Guo X-Patchwork-Id: 3067 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 57B5423F18 for ; Mon, 25 Jul 2011 09:37:21 +0000 (UTC) Received: from mail-qw0-f52.google.com (mail-qw0-f52.google.com [209.85.216.52]) by fiordland.canonical.com (Postfix) with ESMTP id F1B6AA1807A for ; Mon, 25 Jul 2011 09:37:20 +0000 (UTC) Received: by qwb8 with SMTP id 8so2870814qwb.11 for ; Mon, 25 Jul 2011 02:37:20 -0700 (PDT) Received: by 10.229.25.212 with SMTP id a20mr3261180qcc.148.1311586640284; Mon, 25 Jul 2011 02:37:20 -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.217.78 with SMTP id hl14cs72507qcb; Mon, 25 Jul 2011 02:37:19 -0700 (PDT) Received: by 10.68.22.103 with SMTP id c7mr7297397pbf.149.1311586639241; Mon, 25 Jul 2011 02:37:19 -0700 (PDT) Received: from TX2EHSOBE002.bigfish.com (tx2ehsobe001.messaging.microsoft.com [65.55.88.11]) by mx.google.com with ESMTPS id h10si3189679pbk.54.2011.07.25.02.37.17 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 25 Jul 2011 02:37:18 -0700 (PDT) Received-SPF: neutral (google.com: 65.55.88.11 is neither permitted nor denied by best guess record for domain of shawn.guo@linaro.org) client-ip=65.55.88.11; Authentication-Results: mx.google.com; spf=neutral (google.com: 65.55.88.11 is neither permitted nor denied by best guess record for domain of shawn.guo@linaro.org) smtp.mail=shawn.guo@linaro.org Received: from mail41-tx2-R.bigfish.com (10.9.14.244) by TX2EHSOBE002.bigfish.com (10.9.40.22) with Microsoft SMTP Server id 14.1.225.22; Mon, 25 Jul 2011 09:37:16 +0000 Received: from mail41-tx2 (localhost.localdomain [127.0.0.1]) by mail41-tx2-R.bigfish.com (Postfix) with ESMTP id AA254C60422; Mon, 25 Jul 2011 09:37:16 +0000 (UTC) X-SpamScore: 0 X-BigFish: VS0(zzzz1202hzz8275ch8275bh8275dhz2dh87h2a8h668h839h66h) X-Spam-TCS-SCL: 5:0 X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPVD:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-FB-DOMAIN-IP-MATCH: fail Received: from mail41-tx2 (localhost.localdomain [127.0.0.1]) by mail41-tx2 (MessageSwitch) id 1311586612836426_22893; Mon, 25 Jul 2011 09:36:52 +0000 (UTC) Received: from TX2EHSMHS007.bigfish.com (unknown [10.9.14.247]) by mail41-tx2.bigfish.com (Postfix) with ESMTP id B1FB192004B; Mon, 25 Jul 2011 09:36:52 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by TX2EHSMHS007.bigfish.com (10.9.99.107) with Microsoft SMTP Server (TLS) id 14.1.225.22; Mon, 25 Jul 2011 09:36:49 +0000 Received: from az33smr01.freescale.net (10.64.34.199) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server id 14.1.289.8; Mon, 25 Jul 2011 04:36:48 -0500 Received: from S2100-06.ap.freescale.net (S2100-06.ap.freescale.net [10.192.242.125]) by az33smr01.freescale.net (8.13.1/8.13.0) with ESMTP id p6P9aihl015384; Mon, 25 Jul 2011 04:36:45 -0500 (CDT) From: Shawn Guo To: CC: , , , Shawn Guo , Grant Likely , Steve Glendinning , "David S. Miller" Subject: [PATCH] net/smsc911x: add device tree probe support Date: Mon, 25 Jul 2011 17:44:00 +0800 Message-ID: <1311587040-8988-1-git-send-email-shawn.guo@linaro.org> X-Mailer: git-send-email 1.7.4.1 MIME-Version: 1.0 X-OriginatorOrg: sigmatel.com It adds device tree probe support for smsc911x driver. Signed-off-by: Shawn Guo Cc: Grant Likely Cc: Steve Glendinning Cc: David S. Miller --- Documentation/devicetree/bindings/net/smsc.txt | 34 +++++++ drivers/net/smsc911x.c | 123 +++++++++++++++++++----- 2 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/smsc.txt diff --git a/Documentation/devicetree/bindings/net/smsc.txt b/Documentation/devicetree/bindings/net/smsc.txt new file mode 100644 index 0000000..1920695 --- /dev/null +++ b/Documentation/devicetree/bindings/net/smsc.txt @@ -0,0 +1,34 @@ +* Smart Mixed-Signal Connectivity (SMSC) LAN Controller + +Required properties: +- compatible : Should be "smsc,lan""smsc,lan" +- reg : Address and length of the io space for SMSC LAN +- smsc-int-gpios : Should specify the GPIO for SMSC LAN interrupt line +- 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: +- smsc,irq-active-high : Indicates the IRQ polarity is active-low +- smsc,irq-push-pull : Indicates the IRQ type is push-pull +- smsc,register-needs-shift : Indicates the register access needs shift +- smsc,access-in-32bit : Indicates the access to controller is in 32-bit + mode +- 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,lan"; + reg = <0xf4000000 0x2000000>; + phy-mode = "mii"; + smsc-int-gpios = <&gpio1 31 0>; /* GPIO2_31 */ + smsc,irq-push-pull; + smsc,access-in-32bit; +}; diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index b9016a3..0097048 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,25 +2099,67 @@ 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; + + 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); + + 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,register-needs-shift", NULL)) + config->shift = 1; + + if (of_get_property(np, "smsc,access-in-32bit", NULL)) + config->flags |= SMSC911X_USE_32BIT; + + 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; struct resource *res, *irq_res; unsigned int intcfg = 0; - int res_size, irq_flags; - int retval; + int irq_gpio, res_size, irq_flags = 0; + int retval = 0; 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) @@ -2125,13 +2171,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) } res_size = resource_size(res); - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq_res) { - pr_warn("Could not allocate irq resource\n"); - retval = -ENODEV; - goto out_0; - } - if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) { retval = -EBUSY; goto out_0; @@ -2148,26 +2187,53 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) pdata = netdev_priv(dev); - dev->irq = irq_res->start; - 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)); + if (np) { + irq_gpio = of_get_named_gpio(np, "smsc-int-gpios", 0); + retval = gpio_request_one(irq_gpio, GPIOF_IN, "smsc-int-gpio"); + if (!retval) + dev->irq = gpio_to_irq(irq_gpio); + } else { + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (irq_res) { + dev->irq = irq_res->start; + irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; + } else { + retval = -ENODEV; + } + } - pdata->dev = dev; - pdata->msg_enable = ((1 << debug) - 1); + if (retval) { + SMSC_WARN(pdata, probe, "Error smsc911x irq not found"); + retval = -EINVAL; + goto out_free_netdev_2; + } + pdata->ioaddr = ioremap_nocache(res->start, res_size); if (pdata->ioaddr == NULL) { SMSC_WARN(pdata, probe, "Error smsc911x base address invalid"); retval = -ENOMEM; goto out_free_netdev_2; } + pdata->dev = dev; + pdata->msg_enable = ((1 << debug) - 1); + + 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 +2380,12 @@ static const struct dev_pm_ops smsc911x_pm_ops = { #define SMSC911X_PM_OPS NULL #endif +static const struct of_device_id smsc_dt_ids[] = { + { .compatible = "smsc,lan", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, smsc_dt_ids); + static struct platform_driver smsc911x_driver = { .probe = smsc911x_drv_probe, .remove = __devexit_p(smsc911x_drv_remove), @@ -2321,6 +2393,7 @@ static struct platform_driver smsc911x_driver = { .name = SMSC_CHIPNAME, .owner = THIS_MODULE, .pm = SMSC911X_PM_OPS, + .of_match_table = smsc_dt_ids, }, };