>From e63db52f7a2ac7288946a14f725c4547855f951f Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Sun, 26 Sep 2021 23:41:51 +0300 Subject: [PATCH] net: stmmac: Move Loongson1 MAC arch-code to the driver dir Loongson1 SoC is equipped with two GMAC interfaces based on the DW GMAC v3.x. Both of them are exposed on Loongson 1B boards, and just one of them - on Loongson 1C boards. The glue driver has been created purely based on the arch-code implemented earlier with the platform-specific settings. That's why the sloppy mux-switching has been left as is until someone dares to create a driver for the embedded mux. Note after this commit is merged in there won't be any platform_data-based code left using the STMMAC-platform interface. Thus the STMMAC platform_data declarations can be freely moved away from the generic kernel headers set into the driver directory. Signed-off-by: Serge Semin --- Note I don't have a Loongson32 hardware at hand to test it out. I've built-test the change though. So should you have the hardware any tests and bug-reports would be very welcome. --- MAINTAINERS | 1 + arch/mips/loongson32/common/platform.c | 111 +---------- drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++ drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 173 ++++++++++++++++++ 5 files changed, 193 insertions(+), 104 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c diff --git a/MAINTAINERS b/MAINTAINERS index f0ee1d6d8918..a90d5b3de82e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14097,6 +14097,7 @@ L: linux-mips@vger.kernel.org S: Maintained F: arch/mips/include/asm/mach-loongson32/ F: arch/mips/loongson32/ +F: drivers/*/*/*/*/*loongson1* F: drivers/*/*loongson1* MIPS/LOONGSON2EF ARCHITECTURE diff --git a/arch/mips/loongson32/common/platform.c b/arch/mips/loongson32/common/platform.c index 64d7979394e6..85603f531148 100644 --- a/arch/mips/loongson32/common/platform.c +++ b/arch/mips/loongson32/common/platform.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -61,88 +60,7 @@ void __init ls1x_serial_set_uartclk(struct platform_device *pdev) p->uartclk = clk_get_rate(clk); } -/* Synopsys Ethernet GMAC */ -static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { - .phy_mask = 0, -}; - -static struct stmmac_dma_cfg ls1x_eth_dma_cfg = { - .pbl = 1, -}; - -int ls1x_eth_mux_init(struct platform_device *pdev, void *priv) -{ - struct plat_stmmacenet_data *plat_dat = NULL; - u32 val; - - val = __raw_readl(LS1X_MUX_CTRL1); - -#if defined(CONFIG_LOONGSON1_LS1B) - plat_dat = dev_get_platdata(&pdev->dev); - if (plat_dat->bus_id) { - __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 | - GMAC1_USE_UART0, LS1X_MUX_CTRL0); - switch (plat_dat->phy_interface) { - case PHY_INTERFACE_MODE_RGMII: - val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23); - break; - case PHY_INTERFACE_MODE_MII: - val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23); - break; - default: - pr_err("unsupported mii mode %d\n", - plat_dat->phy_interface); - return -ENOTSUPP; - } - val &= ~GMAC1_SHUT; - } else { - switch (plat_dat->phy_interface) { - case PHY_INTERFACE_MODE_RGMII: - val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01); - break; - case PHY_INTERFACE_MODE_MII: - val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01); - break; - default: - pr_err("unsupported mii mode %d\n", - plat_dat->phy_interface); - return -ENOTSUPP; - } - val &= ~GMAC0_SHUT; - } - __raw_writel(val, LS1X_MUX_CTRL1); -#elif defined(CONFIG_LOONGSON1_LS1C) - plat_dat = dev_get_platdata(&pdev->dev); - - val &= ~PHY_INTF_SELI; - if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII) - val |= 0x4 << PHY_INTF_SELI_SHIFT; - __raw_writel(val, LS1X_MUX_CTRL1); - - val = __raw_readl(LS1X_MUX_CTRL0); - __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0); -#endif - - return 0; -} - -static struct plat_stmmacenet_data ls1x_eth0_pdata = { - .bus_id = 0, - .phy_addr = -1, -#if defined(CONFIG_LOONGSON1_LS1B) - .phy_interface = PHY_INTERFACE_MODE_MII, -#elif defined(CONFIG_LOONGSON1_LS1C) - .phy_interface = PHY_INTERFACE_MODE_RMII, -#endif - .mdio_bus_data = &ls1x_mdio_bus_data, - .dma_cfg = &ls1x_eth_dma_cfg, - .has_gmac = 1, - .tx_coe = 1, - .rx_queues_to_use = 1, - .tx_queues_to_use = 1, - .init = ls1x_eth_mux_init, -}; - +/* Ethernet (Synopsys DW GMAC) */ static struct resource ls1x_eth0_resources[] = { [0] = { .start = LS1X_GMAC0_BASE, @@ -157,29 +75,17 @@ static struct resource ls1x_eth0_resources[] = { }; struct platform_device ls1x_eth0_pdev = { - .name = "stmmaceth", +#if defined(CONFIG_LOONGSON1_LS1B) + .name = "ls1b-eth", +#elif defined(CONFIG_LOONGSON1_LS1C) + .name = "ls1c-eth", +#endif .id = 0, .num_resources = ARRAY_SIZE(ls1x_eth0_resources), .resource = ls1x_eth0_resources, - .dev = { - .platform_data = &ls1x_eth0_pdata, - }, }; #ifdef CONFIG_LOONGSON1_LS1B -static struct plat_stmmacenet_data ls1x_eth1_pdata = { - .bus_id = 1, - .phy_addr = -1, - .phy_interface = PHY_INTERFACE_MODE_MII, - .mdio_bus_data = &ls1x_mdio_bus_data, - .dma_cfg = &ls1x_eth_dma_cfg, - .has_gmac = 1, - .tx_coe = 1, - .rx_queues_to_use = 1, - .tx_queues_to_use = 1, - .init = ls1x_eth_mux_init, -}; - static struct resource ls1x_eth1_resources[] = { [0] = { .start = LS1X_GMAC1_BASE, @@ -194,13 +100,10 @@ static struct resource ls1x_eth1_resources[] = { }; struct platform_device ls1x_eth1_pdev = { - .name = "stmmaceth", + .name = "ls1b-eth", .id = 1, .num_resources = ARRAY_SIZE(ls1x_eth1_resources), .resource = ls1x_eth1_resources, - .dev = { - .platform_data = &ls1x_eth1_pdata, - }, }; #endif /* CONFIG_LOONGSON1_LS1B */ diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 5f5a997f21f3..a89ecbd67f21 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -263,6 +263,17 @@ config DWMAC_VISCONTI help Support for ethernet controller on Visconti SoCs. +config DWMAC_LOONGSON1 + tristate "Loongson1 GMAC support" + default LOONGSON1_LS1B || LOONGSON1_LS1C + depends on MACH_LOONGSON32 + help + Support for ethernet controller on Loongson1 SoC. + + This selects Loongson1 SoC glue layer support for the stmmac + device driver. This driver is used for Loongson1-based boards + like Loongson LS1B/LS1C. + endif config DWMAC_INTEL diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 8738fdbb4b2d..a6fb0f773575 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o obj-$(CONFIG_DWMAC_TEGRA) += dwmac-tegra.o obj-$(CONFIG_DWMAC_VISCONTI) += dwmac-visconti.o +obj-$(CONFIG_DWMAC_LOONGSON1) += dwmac-loongson1.o stmmac-platform-objs:= stmmac_platform.o dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c new file mode 100644 index 000000000000..4cf6e763ac41 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2011-2023 Zhang, Keguang + */ + +#include +#include +#include +#include +#include + +#include + +#include "stmmac.h" +#include "stmmac_platform.h" + +struct ls1x_eth_info { + phy_interface_t interface; + int (*init)(struct platform_device *pdev, void *priv); +}; + +/* Note the mux-switching is supposed to be implemented via a dedicated + * driver. Until it's done there is no other choice but live with such + * a sloppy implementation. + */ +static int ls1b_eth_mux_init(struct platform_device *pdev, void *priv) +{ + struct plat_stmmacenet_data *plat = priv; + u32 val; + + val = __raw_readl(LS1X_MUX_CTRL1); + + if (plat->bus_id) { + __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 | + GMAC1_USE_UART0, LS1X_MUX_CTRL0); + switch (plat->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23); + break; + case PHY_INTERFACE_MODE_MII: + val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23); + break; + default: + dev_err(&pdev->dev, "Unsupported PHY-mode %u\n", + plat->phy_interface); + return -ENOTSUPP; + } + val &= ~GMAC1_SHUT; + } else { + switch (plat->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01); + break; + case PHY_INTERFACE_MODE_MII: + val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01); + break; + default: + dev_err(&pdev->dev, "Unsupported PHY-mode %u\n", + plat->phy_interface); + return -ENOTSUPP; + } + val &= ~GMAC0_SHUT; + } + + __raw_writel(val, LS1X_MUX_CTRL1); + + return 0; +} + +static int ls1c_eth_mux_init(struct platform_device *pdev, void *priv) +{ + struct plat_stmmacenet_data *plat = priv; + u32 val; + + val = __raw_readl(LS1X_MUX_CTRL1) & ~PHY_INTF_SELI; + if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) { + val |= 0x4 << PHY_INTF_SELI_SHIFT; + } else { + dev_err(&pdev->dev, "Unsupported PHY-mode %u\n", + plat->phy_interface); + return -ENOTSUPP; + } + __raw_writel(val, LS1X_MUX_CTRL1); + + val = __raw_readl(LS1X_MUX_CTRL0); + __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0); + + return 0; +} + +static int ls1x_eth_probe(struct platform_device *pdev) +{ + const struct platform_device_id *id = platform_get_device_id(pdev); + const struct ls1x_eth_info *info = (struct ls1x_eth_info *)id->driver_data; + struct stmmac_resources stmmac_res; + struct plat_stmmacenet_data *plat; + int ret; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); + if (!plat) + return -ENOMEM; + + plat->mdio_bus_data = devm_kzalloc(&pdev->dev, + sizeof(*plat->mdio_bus_data), + GFP_KERNEL); + if (!plat->mdio_bus_data) + return -ENOMEM; + + plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), + GFP_KERNEL); + if (!plat->dma_cfg) + return -ENOMEM; + + plat->bus_id = pdev->id; + plat->phy_addr = -1; + plat->phy_interface = info->phy_interface; + plat->mdio_bus_data->phy_mask = 0; + plat->dma_cfg->pbl = 1; + plat->has_gmac = 1; + plat->tx_coe = 1; + plat->multicast_filter_bins = 64; + plat->unicast_filter_entries = 1; + plat->rx_queues_to_use = 1; + plat->tx_queues_to_use = 1; + plat->bsp_priv = plat; + plat->init = info->init; + + ret = plat->init(pdev, plat->bsp_priv); + if (ret) + return ret; + + ret = stmmac_dvr_probe(&pdev->dev, plat, &stmmac_res); + if (ret) + goto err_exit; + + return 0; +} + +static const struct ls1x_eth_info ls1b_eth_info = { + .phy_interface = PHY_INTERFACE_MODE_MII, + .init = ls1b_eth_mux_init, +}; + +static const struct ls1x_eth_info ls1c_eth_info = { + .phy_interface = PHY_INTERFACE_MODE_RMII, + .init = ls1c_eth_mux_init, +}; + +static const struct platform_device_id ls1x_eth_id_table[] = { + { "ls1b-eth", (kernel_ulong_t)&ls1b_eth_info }, + { "ls1c-eth", (kernel_ulong_t)&ls1c_eth_info }, + { } +}; +MODULE_DEVICE_TABLE(platform, ls1x_eth_id_table); + +static struct platform_driver ls1x_eth_driver = { + .probe = ls1x_eth_probe, + .remove = stmmac_pltfr_remove, + .id_table = ls1x_eth_id_table, + .driver = { + .name = "ls1x-eth", + }, +}; +module_platform_driver(ls1x_eth_driver); + +MODULE_AUTHOR("Keguang Zhang "); +MODULE_DESCRIPTION("Loongson1 GMAC driver"); +MODULE_LICENSE("GPL"); -- 2.41.0