From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001 From: James <> Date: Wed, 4 Nov 2015 11:49:21 +0000 Subject: trunk-47381 --- .../net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 172 +++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c (limited to 'target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c') 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 0000000..07f9f44 --- /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"); -- cgit v1.2.3