From 6944a9509118a3f48b3b5b4a585dee718aa75d52 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 19 Oct 2015 10:09:36 +0000 Subject: [PATCH] oxnas: move gmac soc glue from mach to stmmac driver Still a lot of kernel-version ifdef'ery, but imho that's easy to remove once obsoleted and avoids duplicate code in the meantime. Signed-off-by: Daniel Golle SVN-Revision: 47218 --- .../files/arch/arm/mach-oxnas/mach-ox820.c | 101 ---------- .../net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 172 ++++++++++++++++++ .../oxnas/patches-4.1/700-oxnas-dwmac.patch | 25 +++ 3 files changed, 197 insertions(+), 101 deletions(-) create mode 100644 target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c create mode 100644 target/linux/oxnas/patches-4.1/700-oxnas-dwmac.patch diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c b/target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c index 4b247b6b56..718bad7194 100644 --- a/target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -57,102 +56,6 @@ void __init ox820_map_common_io(void) iotable_init(ox820_io_desc, ARRAY_SIZE(ox820_io_desc)); } -struct plat_gmac_data { - struct plat_stmmacenet_data stmmac; - struct clk *clk; -}; - -void *ox820_gmac_setup(struct platform_device *pdev) -{ - struct plat_gmac_data *pdata = pdev->dev.platform_data; - - pdata->clk = clk_get(&pdev->dev, "gmac"); - return (void *) pdata->clk; -}; - -int ox820_gmac_init(struct platform_device *pdev, void *priv) -{ - int ret; - unsigned value; - - ret = device_reset(&pdev->dev); - if (ret) - return ret; - - if (IS_ERR(priv)) - return PTR_ERR(priv); - clk_prepare_enable(priv); - - value = readl(SYS_CTRL_GMAC_CTRL); - - /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ - value |= BIT(SYS_CTRL_GMAC_CKEN_GTX); - /* Use simple mux for 25/125 Mhz clock switching */ - value |= BIT(SYS_CTRL_GMAC_SIMPLE_MUX); - /* set auto switch tx clock source */ - value |= BIT(SYS_CTRL_GMAC_AUTO_TX_SOURCE); - /* enable tx & rx vardelay */ - value |= BIT(SYS_CTRL_GMAC_CKEN_TX_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_TXN_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_TX_IN); - value |= BIT(SYS_CTRL_GMAC_CKEN_RX_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_RXN_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_RX_IN); - writel(value, SYS_CTRL_GMAC_CTRL); - - /* set tx & rx vardelay */ - value = 0; - value |= SYS_CTRL_GMAC_TX_VARDELAY(4); - value |= SYS_CTRL_GMAC_TXN_VARDELAY(2); - value |= SYS_CTRL_GMAC_RX_VARDELAY(10); - value |= SYS_CTRL_GMAC_RXN_VARDELAY(8); - writel(value, SYS_CTRL_GMAC_DELAY_CTRL); - - return 0; -} - -void ox820_gmac_exit(struct platform_device *pdev, void *priv) -{ - struct reset_control *rstc; - - clk_disable_unprepare(priv); - clk_put(priv); - - rstc = reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(rstc)) { - reset_control_assert(rstc); - reset_control_put(rstc); - } -} - -static int __init ox820_ether_init(void) -{ - struct device_node *node; - struct platform_device *pdev; - struct plat_gmac_data *pdata; - - node = of_find_compatible_node(NULL, NULL, "plxtech,nas782x-gmac"); - if (!node) - return -ENOENT; - - pdev = of_find_device_by_node(node); - of_node_put(node); - - if (!pdev) - return -EINVAL; - - pdata = kzalloc(sizeof(struct plat_gmac_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - pdata->stmmac.setup = ox820_gmac_setup; - pdata->stmmac.init = ox820_gmac_init; - pdata->stmmac.exit = ox820_gmac_exit; - pdev->dev.platform_data = pdata; - - return 0; -} - static void __init ox820_dt_init(void) { int ret; @@ -165,10 +68,6 @@ static void __init ox820_dt_init(void) BUG(); } - ret = ox820_ether_init(); - - if (ret) - pr_info("ox820_ether_init failed: %d\n", ret); } static void __init ox820_timer_init(void) diff --git a/target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c new file mode 100644 index 0000000000..07f9f44497 --- /dev/null +++ b/target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c @@ -0,0 +1,172 @@ +/* Copyright OpenWrt.org (C) 2015. + * Copyright Altera Corporation (C) 2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Adopted from dwmac-socfpga.c + * Based on code found in mach-oxnas.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "stmmac.h" +#include "stmmac_platform.h" + +struct oxnas_gmac { + struct clk *clk; +}; + +static int oxnas_gmac_init(struct platform_device *pdev, void *priv) +{ + struct oxnas_gmac *bsp_priv = priv; + int ret = 0; + unsigned value; + + ret = device_reset(&pdev->dev); + if (ret) + return ret; + + if (IS_ERR(bsp_priv->clk)) + return PTR_ERR(bsp_priv->clk); + clk_prepare_enable(bsp_priv->clk); + + value = readl(SYS_CTRL_GMAC_CTRL); + + /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ + value |= BIT(SYS_CTRL_GMAC_CKEN_GTX); + /* Use simple mux for 25/125 Mhz clock switching */ + value |= BIT(SYS_CTRL_GMAC_SIMPLE_MUX); + /* set auto switch tx clock source */ + value |= BIT(SYS_CTRL_GMAC_AUTO_TX_SOURCE); + /* enable tx & rx vardelay */ + value |= BIT(SYS_CTRL_GMAC_CKEN_TX_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_TXN_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_TX_IN); + value |= BIT(SYS_CTRL_GMAC_CKEN_RX_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_RXN_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_RX_IN); + writel(value, SYS_CTRL_GMAC_CTRL); + + /* set tx & rx vardelay */ + value = 0; + value |= SYS_CTRL_GMAC_TX_VARDELAY(4); + value |= SYS_CTRL_GMAC_TXN_VARDELAY(2); + value |= SYS_CTRL_GMAC_RX_VARDELAY(10); + value |= SYS_CTRL_GMAC_RXN_VARDELAY(8); + writel(value, SYS_CTRL_GMAC_DELAY_CTRL); + + return 0; +} + +static void oxnas_gmac_exit(struct platform_device *pdev, void *priv) +{ + struct reset_control *rstc; + + clk_disable_unprepare(priv); + devm_clk_put(&pdev->dev, priv); + + rstc = reset_control_get(&pdev->dev, NULL); + if (!IS_ERR(rstc)) { + reset_control_assert(rstc); + reset_control_put(rstc); + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) +static void *oxnas_gmac_probe(struct platform_device *pdev) +{ +#else +static int oxnas_gmac_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + int ret; +#endif + struct device *dev = &pdev->dev; + struct oxnas_gmac *bsp_priv; + + bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL); + if (!bsp_priv) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) + return ERR_PTR(-ENOMEM); +#else + return -ENOMEM; +#endif + bsp_priv->clk = devm_clk_get(dev, "gmac"); + if (IS_ERR(bsp_priv->clk)) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) + return bsp_priv->clk; +#else + return PTR_ERR(bsp_priv->clk); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) + return bsp_priv; +#else + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + plat_dat->bsp_priv = bsp_priv; + plat_dat->init = oxnas_gmac_init; + plat_dat->exit = oxnas_gmac_exit; + + ret = oxnas_gmac_init(pdev, bsp_priv); + if (ret) + return ret; + + return stmmac_dvr_probe(dev, plat_dat, &stmmac_res); +#endif +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) +const struct stmmac_of_data oxnas_gmac_data = { + .has_gmac = 1, + .setup = oxnas_gmac_probe, + .init = oxnas_gmac_init, + .exit = oxnas_gmac_exit, +}; +#else +static const struct of_device_id oxnas_gmac_match[] = { + { .compatible = "plxtech,nas782x-gmac" }, + { } +}; +MODULE_DEVICE_TABLE(of, oxnas_gmac_match); + +static struct platform_driver oxnas_gmac_driver = { + .probe = oxnas_gmac_probe, + .remove = stmmac_pltfr_remove, + .driver = { + .name = "oxnas-gmac", + .pm = &stmmac_pltfr_pm_ops, + .of_match_table = oxnas_gmac_match, + }, +}; +module_platform_driver(oxnas_gmac_driver); +#endif + +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/oxnas/patches-4.1/700-oxnas-dwmac.patch b/target/linux/oxnas/patches-4.1/700-oxnas-dwmac.patch new file mode 100644 index 0000000000..dde3140a1f --- /dev/null +++ b/target/linux/oxnas/patches-4.1/700-oxnas-dwmac.patch @@ -0,0 +1,25 @@ +--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig ++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig +@@ -20,7 +20,7 @@ config STMMAC_PLATFORM + ---help--- + This selects the platform specific bus support for the stmmac driver. + This is the driver used on several SoCs: +- STi, Allwinner, Amlogic Meson, Altera SOCFPGA. ++ STi, Allwinner, Amlogic Meson, Altera SOCFPGA and Oxnas. + + If you have a controller with this interface, say Y or M here. + +--- a/drivers/net/ethernet/stmicro/stmmac/Makefile ++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile +@@ -5,8 +5,9 @@ stmmac-objs:= stmmac_main.o stmmac_ethto + mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y) + + obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o +-stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o \ +- dwmac-sti.o dwmac-socfpga.o dwmac-rk.o ++stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-oxnas.o \ ++ dwmac-sunxi.o dwmac-sti.o dwmac-socfpga.o \ ++ dwmac-rk.o + + obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o + stmmac-pci-objs:= stmmac_pci.o