From patchwork Wed Oct 26 08:05:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 4820 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 873C823DEF for ; Wed, 26 Oct 2011 08:18:17 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id 7699BA18B5F for ; Wed, 26 Oct 2011 08:18:17 +0000 (UTC) Received: by faan26 with SMTP id n26so1850350faa.11 for ; Wed, 26 Oct 2011 01:18:17 -0700 (PDT) Received: by 10.223.85.139 with SMTP id o11mr57512949fal.0.1319617097030; Wed, 26 Oct 2011 01:18:17 -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.152.1.71 with SMTP id 7cs4401lak; Wed, 26 Oct 2011 01:18:16 -0700 (PDT) Received: by 10.213.17.136 with SMTP id s8mr136188eba.106.1319617095128; Wed, 26 Oct 2011 01:18:15 -0700 (PDT) Received: from eu1sys200aog105.obsmtp.com (eu1sys200aog105.obsmtp.com. [207.126.144.119]) by mx.google.com with SMTP id f48si193145eea.160.2011.10.26.01.18.10 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 26 Oct 2011 01:18:15 -0700 (PDT) Received-SPF: neutral (google.com: 207.126.144.119 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) client-ip=207.126.144.119; Authentication-Results: mx.google.com; spf=neutral (google.com: 207.126.144.119 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) smtp.mail=linus.walleij@stericsson.com Received: from beta.dmz-eu.st.com ([164.129.1.35]) (using TLSv1) by eu1sys200aob105.postini.com ([207.126.147.11]) with SMTP; Wed, 26 Oct 2011 08:18:14 UTC Received: from zeta.dmz-us.st.com (ns4.st.com [167.4.16.71]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id F1CB473; Wed, 26 Oct 2011 08:18:03 +0000 (GMT) Received: from relay1.stm.gmessaging.net (unknown [10.230.100.17]) by zeta.dmz-us.st.com (STMicroelectronics) with ESMTP id 9C14F64; Wed, 26 Oct 2011 08:06:00 +0000 (GMT) Received: from exdcvycastm003.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm003", Issuer "exdcvycastm003" (not verified)) by relay1.stm.gmessaging.net (Postfix) with ESMTPS id 9501A24C080; Wed, 26 Oct 2011 10:05:55 +0200 (CEST) Received: from localhost.localdomain (10.230.100.153) by smtp.stericsson.com (10.230.100.1) with Microsoft SMTP Server (TLS) id 8.3.83.0; Wed, 26 Oct 2011 10:05:59 +0200 From: Linus Walleij To: , Steve Glendinning Cc: Mathieu Poirer , Robert Marklund , Mark Brown , Linus Walleij Subject: [PATCH 2/2] net/smsc911x: Add regulator support Date: Wed, 26 Oct 2011 10:05:56 +0200 Message-ID: <1319616356-6391-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.7.3.2 MIME-Version: 1.0 From: Robert Marklund Add some basic regulator support for the power pins, as needed by the ST-Ericsson Snowball platform that powers up the SMSC911 chip using an external regulator. Cc: Mark Brown Signed-off-by: Robert Marklund Signed-off-by: Linus Walleij --- drivers/net/ethernet/smsc/smsc911x.c | 128 +++++++++++++++++++++++++++++++--- 1 files changed, 117 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 8843071..fca01eb 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -138,6 +139,10 @@ struct smsc911x_data { /* register access functions */ const struct smsc911x_ops *ops; + + /* regulators */ + struct regulator *regulator_vddvario; + struct regulator *regulator_vdd33a; }; /* Easy access to information */ @@ -362,6 +367,86 @@ out: spin_unlock_irqrestore(&pdata->dev_lock, flags); } +/* + * Enable or disable resources, currently just regulators. + */ +static int smsc911x_enable_disable_resources(struct platform_device *pdev, + bool enable) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct smsc911x_data *pdata = netdev_priv(ndev); + int err = 0; + + /* enable/disable regulator for vddvario */ + if (pdata->regulator_vddvario) { + if (enable) { + err = regulator_enable(pdata->regulator_vddvario); + if (err < 0) { + netdev_err(ndev, "regulator_enable failed for " + "vddvario"); + } + } else + err = regulator_disable(pdata->regulator_vddvario); + } + + /* enable/disable regulator for vdd33a */ + if (pdata->regulator_vdd33a) { + if (enable) { + err = regulator_enable(pdata->regulator_vdd33a); + if (err < 0) { + netdev_err(ndev, "regulator_enable failed for " + "vdd33a"); + } + } else + err = regulator_disable(pdata->regulator_vdd33a); + } + return err; +} + +/* + * Request or free resources, currently just regulators. + * + * The SMSC911x has two power pins: vddvario and vdd33a, in designs where + * these are not always-on we need to request regulators to be turned on + * before we can try to access the device registers. + */ +static int smsc911x_request_free_resources(struct platform_device *pdev, + bool request) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct smsc911x_data *pdata = netdev_priv(ndev); + int err = 0; + + /* Request regulator for vddvario */ + if (request && !pdata->regulator_vddvario) { + pdata->regulator_vddvario = regulator_get(&pdev->dev, + "vddvario"); + if (IS_ERR(pdata->regulator_vddvario)) { + netdev_err(ndev, "Failed to get regulator vddvario\n"); + err = PTR_ERR(pdata->regulator_vddvario); + pdata->regulator_vddvario = NULL; + } + } else if (!request && pdata->regulator_vddvario) { + regulator_put(pdata->regulator_vddvario); + pdata->regulator_vddvario = NULL; + } + + /* Request regulator for vdd33a */ + if (request && !pdata->regulator_vdd33a) { + pdata->regulator_vdd33a = regulator_get(&pdev->dev, "vdd33a"); + if (IS_ERR(pdata->regulator_vdd33a)) { + netdev_err(ndev, "Failed to get regulator vdd33a\n"); + err = PTR_ERR(pdata->regulator_vdd33a); + pdata->regulator_vdd33a = NULL; + } + } else if (!request && pdata->regulator_vdd33a) { + regulator_put(pdata->regulator_vdd33a); + pdata->regulator_vdd33a = NULL; + } + + return err; +} + /* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read * and smsc911x_mac_write, so assumes mac_lock is held */ static int smsc911x_mac_complete(struct smsc911x_data *pdata) @@ -2065,6 +2150,7 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) struct net_device *dev; struct smsc911x_data *pdata; struct resource *res; + int retval; dev = platform_get_drvdata(pdev); BUG_ON(!dev); @@ -2092,6 +2178,12 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) iounmap(pdata->ioaddr); + if (smsc911x_enable_disable_resources(pdev, false)) + pr_warn("Could not disable resource\n"); + + retval = smsc911x_request_free_resources(pdev, false); + /* ignore not all have regulators */ + free_netdev(dev); return 0; @@ -2218,10 +2310,24 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) pdata->dev = dev; pdata->msg_enable = ((1 << debug) - 1); + platform_set_drvdata(pdev, dev); + + retval = smsc911x_request_free_resources(pdev, true); + if (retval) { + pr_err("Could request regulators needed aborting\n"); + goto out_return_resources; + } + + retval = smsc911x_enable_disable_resources(pdev, true); + if (retval) { + pr_err("Could enable regulators needed aborting\n"); + goto out_disable_resources; + } + if (pdata->ioaddr == NULL) { SMSC_WARN(pdata, probe, "Error smsc911x base address invalid"); retval = -ENOMEM; - goto out_free_netdev_2; + goto out_disable_resources; } retval = smsc911x_probe_config_dt(&pdata->config, np); @@ -2233,7 +2339,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) if (retval) { SMSC_WARN(pdata, probe, "Error smsc911x config not found"); - goto out_unmap_io_3; + goto out_disable_resources; } /* assume standard, non-shifted, access to HW registers */ @@ -2244,7 +2350,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) retval = smsc911x_init(dev); if (retval < 0) - goto out_unmap_io_3; + goto out_disable_resources; /* configure irq polarity and type before connecting isr */ if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH) @@ -2264,15 +2370,13 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) if (retval) { SMSC_WARN(pdata, probe, "Unable to claim requested irq: %d", dev->irq); - goto out_unmap_io_3; + goto out_free_irq; } - platform_set_drvdata(pdev, dev); - retval = register_netdev(dev); if (retval) { SMSC_WARN(pdata, probe, "Error %i registering device", retval); - goto out_unset_drvdata_4; + goto out_free_irq; } else { SMSC_TRACE(pdata, probe, "Network interface: \"%s\"", dev->name); @@ -2321,12 +2425,14 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) out_unregister_netdev_5: unregister_netdev(dev); -out_unset_drvdata_4: - platform_set_drvdata(pdev, NULL); +out_free_irq: free_irq(dev->irq, dev); -out_unmap_io_3: +out_disable_resources: + (void)smsc911x_enable_disable_resources(pdev, false); +out_return_resources: + (void)smsc911x_request_free_resources(pdev, false); + platform_set_drvdata(pdev, NULL); iounmap(pdata->ioaddr); -out_free_netdev_2: free_netdev(dev); out_release_io_1: release_mem_region(res->start, resource_size(res));