From patchwork Tue Mar 18 08:40:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhangfei Gao X-Patchwork-Id: 3847771 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 873FCBF540 for ; Tue, 18 Mar 2014 08:43:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6349720383 for ; Tue, 18 Mar 2014 08:43:19 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9E97120380 for ; Tue, 18 Mar 2014 08:43:17 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WPpb0-0003Ng-G5; Tue, 18 Mar 2014 08:42:03 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WPpad-0002Q6-7u; Tue, 18 Mar 2014 08:41:39 +0000 Received: from mail-pa0-f48.google.com ([209.85.220.48]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WPpaN-0002MQ-FV for linux-arm-kernel@lists.infradead.org; Tue, 18 Mar 2014 08:41:26 +0000 Received: by mail-pa0-f48.google.com with SMTP id hz1so6968047pad.7 for ; Tue, 18 Mar 2014 01:40:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=h8OWKw9eJLhhaMHeC1qpPfVP2w/rS/U+SAsXxmtVNBI=; b=B+IWrsSRStzOwd0mGdG9wmdoaSOGrtI0LssfPX+rcfnqT6gAx5hkW5M6ljkZil9IPa 5ABuLs9mNHTcJJgfbLemLKTTIbKXy52DKV1PEhb0IUkZUk6WIIa/XOLz7/1Gd9wFCJfJ IIkoMg0Zovdqkg/Qjokm99dcADcRnpNoy0pfIO3vmy2yWH9PurfR57rWHx562nG+TD8n Fxrm2eg6D8P3gPGN3LoVqKetXQhXtjpr8UcfVf6j29CBJKCJ3bGa0O6PPiAN0DLvDdOU gayveYpFbQw86GffxXaMRJaaw7ayQi+jdpHt0cMZ2d4iE8nIijXJJDgPNAxa0WQ42aT+ 5SlQ== X-Gm-Message-State: ALoCoQmSP6HMiAcIaKrpzCQYjVuYofJseLlf1ruKAISoiv+4MdnpaxBajSDK9pwxmBW7gZv3v8Ys X-Received: by 10.66.163.2 with SMTP id ye2mr31397254pab.110.1395132059746; Tue, 18 Mar 2014 01:40:59 -0700 (PDT) Received: from localhost.localdomain ([180.150.157.4]) by mx.google.com with ESMTPSA id aj7sm84314764pad.29.2014.03.18.01.40.34 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Mar 2014 01:40:38 -0700 (PDT) From: Zhangfei Gao To: "David S. Miller" Subject: [PATCH 2/3] net: hisilicon: new hip04 MDIO driver Date: Tue, 18 Mar 2014 16:40:16 +0800 Message-Id: <1395132017-15928-3-git-send-email-zhangfei.gao@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1395132017-15928-1-git-send-email-zhangfei.gao@linaro.org> References: <1395132017-15928-1-git-send-email-zhangfei.gao@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140318_044123_740757_66F51E1C X-CRM114-Status: GOOD ( 24.12 ) X-Spam-Score: -2.6 (--) Cc: netdev@vger.kernel.org, Zhangfei Gao , linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hisilicon hip04 platform mdio driver Reuse Marvell phy drivers/net/phy/marvell.c Signed-off-by: Zhangfei Gao --- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/hisilicon/Kconfig | 31 +++++ drivers/net/ethernet/hisilicon/Makefile | 5 + drivers/net/ethernet/hisilicon/hip04_mdio.c | 190 +++++++++++++++++++++++++++ 5 files changed, 228 insertions(+) create mode 100644 drivers/net/ethernet/hisilicon/Kconfig create mode 100644 drivers/net/ethernet/hisilicon/Makefile create mode 100644 drivers/net/ethernet/hisilicon/hip04_mdio.c diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 39484b5..cef103d 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -55,6 +55,7 @@ source "drivers/net/ethernet/neterion/Kconfig" source "drivers/net/ethernet/faraday/Kconfig" source "drivers/net/ethernet/freescale/Kconfig" source "drivers/net/ethernet/fujitsu/Kconfig" +source "drivers/net/ethernet/hisilicon/Kconfig" source "drivers/net/ethernet/hp/Kconfig" source "drivers/net/ethernet/ibm/Kconfig" source "drivers/net/ethernet/intel/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index adf61af..f70b166 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_NET_VENDOR_EXAR) += neterion/ obj-$(CONFIG_NET_VENDOR_FARADAY) += faraday/ obj-$(CONFIG_NET_VENDOR_FREESCALE) += freescale/ obj-$(CONFIG_NET_VENDOR_FUJITSU) += fujitsu/ +obj-$(CONFIG_NET_VENDOR_HISILICON) += hisilicon/ obj-$(CONFIG_NET_VENDOR_HP) += hp/ obj-$(CONFIG_NET_VENDOR_IBM) += ibm/ obj-$(CONFIG_NET_VENDOR_INTEL) += intel/ diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig new file mode 100644 index 0000000..4b1c065 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -0,0 +1,31 @@ +# +# HISILICON device configuration +# + +config NET_VENDOR_HISILICON + bool "Hisilicon devices" + default y + depends on ARM + ---help--- + If you have a network (Ethernet) card belonging to this class, say Y + and read the Ethernet-HOWTO, available from + . + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about MOXA ART devices. If you say Y, you will be asked + for your specific card in the following questions. + +if NET_VENDOR_HISILICON + +config HIP04_ETH + tristate "HISILICON P04 Ethernet support" + select NET_CORE + select PHYLIB + select MARVELL_PHY + ---help--- + If you wish to compile a kernel for a hardware with hisilicon p04 SoC and + want to use the internal ethernet then you should answer Y to this. + + +endif # NET_VENDOR_HISILICON diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile new file mode 100644 index 0000000..1d6eb6e --- /dev/null +++ b/drivers/net/ethernet/hisilicon/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the HISILICON network device drivers. +# + +obj-$(CONFIG_HIP04_ETH) += hip04_mdio.o diff --git a/drivers/net/ethernet/hisilicon/hip04_mdio.c b/drivers/net/ethernet/hisilicon/hip04_mdio.c new file mode 100644 index 0000000..960adc2 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hip04_mdio.c @@ -0,0 +1,190 @@ + +/* Copyright (c) 2014 Linaro Ltd. + * Copyright (c) 2014 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 + +#define MDIO_CMD_REG 0x0 +#define MDIO_ADDR_REG 0x4 +#define MDIO_WDATA_REG 0x8 +#define MDIO_RDATA_REG 0xc +#define MDIO_STA_REG 0x10 + +#define MDIO_START BIT(14) +#define MDIO_R_VALID BIT(1) +#define MDIO_READ (BIT(12) | BIT(11) | MDIO_START) +#define MDIO_WRITE (BIT(12) | BIT(10) | MDIO_START) + +struct hip04_mdio_priv { + void __iomem *base; +}; + +#define WAIT_TIMEOUT 10 +static int hip04_mdio_wait_ready(struct mii_bus *bus) +{ + struct hip04_mdio_priv *priv = bus->priv; + int i; + + for (i = 0; readl_relaxed(priv->base + MDIO_CMD_REG) & MDIO_START; i++) { + if (i == WAIT_TIMEOUT) + return -ETIMEDOUT; + msleep(20); + } + + return 0; +} + +static int hip04_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct hip04_mdio_priv *priv = bus->priv; + u32 val; + int ret; + + ret = hip04_mdio_wait_ready(bus); + if (ret < 0) + goto out; + + val = regnum | (mii_id << 5) | MDIO_READ; + writel_relaxed(val, priv->base + MDIO_CMD_REG); + + ret = hip04_mdio_wait_ready(bus); + if (ret < 0) + goto out; + val = readl_relaxed(priv->base + MDIO_STA_REG); + if (val & MDIO_R_VALID) { + dev_err(bus->parent, "SMI bus read not valid\n"); + ret = -ENODEV; + goto out; + } + val = readl_relaxed(priv->base + MDIO_RDATA_REG); + ret = val & 0xFFFF; +out: + return ret; +} + +static int hip04_mdio_write(struct mii_bus *bus, int mii_id, + int regnum, u16 value) +{ + struct hip04_mdio_priv *priv = bus->priv; + u32 val; + int ret; + + ret = hip04_mdio_wait_ready(bus); + if (ret < 0) + goto out; + + writel_relaxed(value, priv->base + MDIO_WDATA_REG); + val = regnum | (mii_id << 5) | MDIO_WRITE; + writel_relaxed(val, priv->base + MDIO_CMD_REG); +out: + return ret; +} + + +static int hip04_mdio_reset(struct mii_bus *bus) +{ + int temp, err, i; + + for (i = 0; i < 2; i++) { + hip04_mdio_write(bus, i, 22, 0); + temp = hip04_mdio_read(bus, i, MII_BMCR); + temp |= BMCR_RESET; + err = hip04_mdio_write(bus, i, MII_BMCR, temp); + if (err < 0) + return err; + } + + mdelay(500); + return 0; +} + +static int hip04_mdio_probe(struct platform_device *pdev) +{ + struct resource *r; + struct mii_bus *bus; + struct hip04_mdio_priv *priv; + int ret; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "No SMI register address given\n"); + return -ENODEV; + } + + bus = mdiobus_alloc_size(sizeof(struct hip04_mdio_priv)); + if (!bus) { + dev_err(&pdev->dev, "Cannot allocate MDIO bus\n"); + return -ENOMEM; + } + + bus->name = "hip04_mdio_bus"; + bus->read = hip04_mdio_read; + bus->write = hip04_mdio_write; + bus->reset = hip04_mdio_reset; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", + dev_name(&pdev->dev)); + bus->parent = &pdev->dev; + priv = bus->priv; + priv->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); + if (!priv->base) { + dev_err(&pdev->dev, "Unable to remap SMI register\n"); + ret = -ENODEV; + goto out_mdio; + } + + ret = of_mdiobus_register(bus, pdev->dev.of_node); + if (ret < 0) { + dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); + goto out_mdio; + } + + platform_set_drvdata(pdev, bus); + + return 0; + +out_mdio: + mdiobus_free(bus); + return ret; +} + +static int hip04_mdio_remove(struct platform_device *pdev) +{ + struct mii_bus *bus = platform_get_drvdata(pdev); + + mdiobus_unregister(bus); + mdiobus_free(bus); + + return 0; +} + +static const struct of_device_id hip04_mdio_match[] = { + { .compatible = "hisilicon,hip04-mdio" }, + { } +}; +MODULE_DEVICE_TABLE(of, hip04_mdio_match); + +static struct platform_driver hip04_mdio_driver = { + .probe = hip04_mdio_probe, + .remove = hip04_mdio_remove, + .driver = { + .name = "hip04-mdio", + .owner = THIS_MODULE, + .of_match_table = hip04_mdio_match, + }, +}; + +module_platform_driver(hip04_mdio_driver); + +MODULE_DESCRIPTION("HISILICON P04 MDIO interface driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:hip04-mdio");