brintos

brintos / linux-shallow public Read only

0
0
Text · 21.2 KiB · 001857c Raw
714 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 MediaTek Inc.4 */5#include <linux/bitfield.h>6#include <linux/io.h>7#include <linux/mfd/syscon.h>8#include <linux/module.h>9#include <linux/of.h>10#include <linux/of_net.h>11#include <linux/platform_device.h>12#include <linux/regmap.h>13#include <linux/stmmac.h>14 15#include "stmmac.h"16#include "stmmac_platform.h"17 18/* Peri Configuration register for mt2712 */19#define PERI_ETH_PHY_INTF_SEL	0x41820#define PHY_INTF_MII		021#define PHY_INTF_RGMII		122#define PHY_INTF_RMII		423#define RMII_CLK_SRC_RXC	BIT(4)24#define RMII_CLK_SRC_INTERNAL	BIT(5)25 26#define PERI_ETH_DLY	0x42827#define ETH_DLY_GTXC_INV	BIT(6)28#define ETH_DLY_GTXC_ENABLE	BIT(5)29#define ETH_DLY_GTXC_STAGES	GENMASK(4, 0)30#define ETH_DLY_TXC_INV		BIT(20)31#define ETH_DLY_TXC_ENABLE	BIT(19)32#define ETH_DLY_TXC_STAGES	GENMASK(18, 14)33#define ETH_DLY_RXC_INV		BIT(13)34#define ETH_DLY_RXC_ENABLE	BIT(12)35#define ETH_DLY_RXC_STAGES	GENMASK(11, 7)36 37#define PERI_ETH_DLY_FINE	0x80038#define ETH_RMII_DLY_TX_INV	BIT(2)39#define ETH_FINE_DLY_GTXC	BIT(1)40#define ETH_FINE_DLY_RXC	BIT(0)41 42/* Peri Configuration register for mt8195 */43#define MT8195_PERI_ETH_CTRL0		0xFD044#define MT8195_RMII_CLK_SRC_INTERNAL	BIT(28)45#define MT8195_RMII_CLK_SRC_RXC		BIT(27)46#define MT8195_ETH_INTF_SEL		GENMASK(26, 24)47#define MT8195_RGMII_TXC_PHASE_CTRL	BIT(22)48#define MT8195_EXT_PHY_MODE		BIT(21)49#define MT8195_DLY_GTXC_INV		BIT(12)50#define MT8195_DLY_GTXC_ENABLE		BIT(5)51#define MT8195_DLY_GTXC_STAGES		GENMASK(4, 0)52 53#define MT8195_PERI_ETH_CTRL1		0xFD454#define MT8195_DLY_RXC_INV		BIT(25)55#define MT8195_DLY_RXC_ENABLE		BIT(18)56#define MT8195_DLY_RXC_STAGES		GENMASK(17, 13)57#define MT8195_DLY_TXC_INV		BIT(12)58#define MT8195_DLY_TXC_ENABLE		BIT(5)59#define MT8195_DLY_TXC_STAGES		GENMASK(4, 0)60 61#define MT8195_PERI_ETH_CTRL2		0xFD862#define MT8195_DLY_RMII_RXC_INV		BIT(25)63#define MT8195_DLY_RMII_RXC_ENABLE	BIT(18)64#define MT8195_DLY_RMII_RXC_STAGES	GENMASK(17, 13)65#define MT8195_DLY_RMII_TXC_INV		BIT(12)66#define MT8195_DLY_RMII_TXC_ENABLE	BIT(5)67#define MT8195_DLY_RMII_TXC_STAGES	GENMASK(4, 0)68 69struct mac_delay_struct {70	u32 tx_delay;71	u32 rx_delay;72	bool tx_inv;73	bool rx_inv;74};75 76struct mediatek_dwmac_plat_data {77	const struct mediatek_dwmac_variant *variant;78	struct mac_delay_struct mac_delay;79	struct clk *rmii_internal_clk;80	struct clk_bulk_data *clks;81	struct regmap *peri_regmap;82	struct device_node *np;83	struct device *dev;84	phy_interface_t phy_mode;85	bool rmii_clk_from_mac;86	bool rmii_rxc;87	bool mac_wol;88};89 90struct mediatek_dwmac_variant {91	int (*dwmac_set_phy_interface)(struct mediatek_dwmac_plat_data *plat);92	int (*dwmac_set_delay)(struct mediatek_dwmac_plat_data *plat);93 94	/* clock ids to be requested */95	const char * const *clk_list;96	int num_clks;97 98	u32 dma_bit_mask;99	u32 rx_delay_max;100	u32 tx_delay_max;101};102 103/* list of clocks required for mac */104static const char * const mt2712_dwmac_clk_l[] = {105	"axi", "apb", "mac_main", "ptp_ref"106};107 108static const char * const mt8195_dwmac_clk_l[] = {109	"axi", "apb", "mac_cg", "mac_main", "ptp_ref"110};111 112static int mt2712_set_interface(struct mediatek_dwmac_plat_data *plat)113{114	int rmii_clk_from_mac = plat->rmii_clk_from_mac ? RMII_CLK_SRC_INTERNAL : 0;115	int rmii_rxc = plat->rmii_rxc ? RMII_CLK_SRC_RXC : 0;116	u32 intf_val = 0;117 118	/* select phy interface in top control domain */119	switch (plat->phy_mode) {120	case PHY_INTERFACE_MODE_MII:121		intf_val |= PHY_INTF_MII;122		break;123	case PHY_INTERFACE_MODE_RMII:124		intf_val |= (PHY_INTF_RMII | rmii_rxc | rmii_clk_from_mac);125		break;126	case PHY_INTERFACE_MODE_RGMII:127	case PHY_INTERFACE_MODE_RGMII_TXID:128	case PHY_INTERFACE_MODE_RGMII_RXID:129	case PHY_INTERFACE_MODE_RGMII_ID:130		intf_val |= PHY_INTF_RGMII;131		break;132	default:133		dev_err(plat->dev, "phy interface not supported\n");134		return -EINVAL;135	}136 137	regmap_write(plat->peri_regmap, PERI_ETH_PHY_INTF_SEL, intf_val);138 139	return 0;140}141 142static void mt2712_delay_ps2stage(struct mediatek_dwmac_plat_data *plat)143{144	struct mac_delay_struct *mac_delay = &plat->mac_delay;145 146	switch (plat->phy_mode) {147	case PHY_INTERFACE_MODE_MII:148	case PHY_INTERFACE_MODE_RMII:149		/* 550ps per stage for MII/RMII */150		mac_delay->tx_delay /= 550;151		mac_delay->rx_delay /= 550;152		break;153	case PHY_INTERFACE_MODE_RGMII:154	case PHY_INTERFACE_MODE_RGMII_TXID:155	case PHY_INTERFACE_MODE_RGMII_RXID:156	case PHY_INTERFACE_MODE_RGMII_ID:157		/* 170ps per stage for RGMII */158		mac_delay->tx_delay /= 170;159		mac_delay->rx_delay /= 170;160		break;161	default:162		dev_err(plat->dev, "phy interface not supported\n");163		break;164	}165}166 167static void mt2712_delay_stage2ps(struct mediatek_dwmac_plat_data *plat)168{169	struct mac_delay_struct *mac_delay = &plat->mac_delay;170 171	switch (plat->phy_mode) {172	case PHY_INTERFACE_MODE_MII:173	case PHY_INTERFACE_MODE_RMII:174		/* 550ps per stage for MII/RMII */175		mac_delay->tx_delay *= 550;176		mac_delay->rx_delay *= 550;177		break;178	case PHY_INTERFACE_MODE_RGMII:179	case PHY_INTERFACE_MODE_RGMII_TXID:180	case PHY_INTERFACE_MODE_RGMII_RXID:181	case PHY_INTERFACE_MODE_RGMII_ID:182		/* 170ps per stage for RGMII */183		mac_delay->tx_delay *= 170;184		mac_delay->rx_delay *= 170;185		break;186	default:187		dev_err(plat->dev, "phy interface not supported\n");188		break;189	}190}191 192static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat)193{194	struct mac_delay_struct *mac_delay = &plat->mac_delay;195	u32 delay_val = 0, fine_val = 0;196 197	mt2712_delay_ps2stage(plat);198 199	switch (plat->phy_mode) {200	case PHY_INTERFACE_MODE_MII:201		delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE, !!mac_delay->tx_delay);202		delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES, mac_delay->tx_delay);203		delay_val |= FIELD_PREP(ETH_DLY_TXC_INV, mac_delay->tx_inv);204 205		delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE, !!mac_delay->rx_delay);206		delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES, mac_delay->rx_delay);207		delay_val |= FIELD_PREP(ETH_DLY_RXC_INV, mac_delay->rx_inv);208		break;209	case PHY_INTERFACE_MODE_RMII:210		if (plat->rmii_clk_from_mac) {211			/* case 1: mac provides the rmii reference clock,212			 * and the clock output to TXC pin.213			 * The egress timing can be adjusted by GTXC delay macro circuit.214			 * The ingress timing can be adjusted by TXC delay macro circuit.215			 */216			delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE, !!mac_delay->rx_delay);217			delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES, mac_delay->rx_delay);218			delay_val |= FIELD_PREP(ETH_DLY_TXC_INV, mac_delay->rx_inv);219 220			delay_val |= FIELD_PREP(ETH_DLY_GTXC_ENABLE, !!mac_delay->tx_delay);221			delay_val |= FIELD_PREP(ETH_DLY_GTXC_STAGES, mac_delay->tx_delay);222			delay_val |= FIELD_PREP(ETH_DLY_GTXC_INV, mac_delay->tx_inv);223		} else {224			/* case 2: the rmii reference clock is from external phy,225			 * and the property "rmii_rxc" indicates which pin(TXC/RXC)226			 * the reference clk is connected to. The reference clock is a227			 * received signal, so rx_delay/rx_inv are used to indicate228			 * the reference clock timing adjustment229			 */230			if (plat->rmii_rxc) {231				/* the rmii reference clock from outside is connected232				 * to RXC pin, the reference clock will be adjusted233				 * by RXC delay macro circuit.234				 */235				delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE, !!mac_delay->rx_delay);236				delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES, mac_delay->rx_delay);237				delay_val |= FIELD_PREP(ETH_DLY_RXC_INV, mac_delay->rx_inv);238			} else {239				/* the rmii reference clock from outside is connected240				 * to TXC pin, the reference clock will be adjusted241				 * by TXC delay macro circuit.242				 */243				delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE, !!mac_delay->rx_delay);244				delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES, mac_delay->rx_delay);245				delay_val |= FIELD_PREP(ETH_DLY_TXC_INV, mac_delay->rx_inv);246			}247			/* tx_inv will inverse the tx clock inside mac relateive to248			 * reference clock from external phy,249			 * and this bit is located in the same register with fine-tune250			 */251			if (mac_delay->tx_inv)252				fine_val = ETH_RMII_DLY_TX_INV;253		}254		break;255	case PHY_INTERFACE_MODE_RGMII:256	case PHY_INTERFACE_MODE_RGMII_TXID:257	case PHY_INTERFACE_MODE_RGMII_RXID:258	case PHY_INTERFACE_MODE_RGMII_ID:259		fine_val = ETH_FINE_DLY_GTXC | ETH_FINE_DLY_RXC;260 261		delay_val |= FIELD_PREP(ETH_DLY_GTXC_ENABLE, !!mac_delay->tx_delay);262		delay_val |= FIELD_PREP(ETH_DLY_GTXC_STAGES, mac_delay->tx_delay);263		delay_val |= FIELD_PREP(ETH_DLY_GTXC_INV, mac_delay->tx_inv);264 265		delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE, !!mac_delay->rx_delay);266		delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES, mac_delay->rx_delay);267		delay_val |= FIELD_PREP(ETH_DLY_RXC_INV, mac_delay->rx_inv);268		break;269	default:270		dev_err(plat->dev, "phy interface not supported\n");271		return -EINVAL;272	}273	regmap_write(plat->peri_regmap, PERI_ETH_DLY, delay_val);274	regmap_write(plat->peri_regmap, PERI_ETH_DLY_FINE, fine_val);275 276	mt2712_delay_stage2ps(plat);277 278	return 0;279}280 281static const struct mediatek_dwmac_variant mt2712_gmac_variant = {282		.dwmac_set_phy_interface = mt2712_set_interface,283		.dwmac_set_delay = mt2712_set_delay,284		.clk_list = mt2712_dwmac_clk_l,285		.num_clks = ARRAY_SIZE(mt2712_dwmac_clk_l),286		.dma_bit_mask = 33,287		.rx_delay_max = 17600,288		.tx_delay_max = 17600,289};290 291static int mt8195_set_interface(struct mediatek_dwmac_plat_data *plat)292{293	int rmii_clk_from_mac = plat->rmii_clk_from_mac ? MT8195_RMII_CLK_SRC_INTERNAL : 0;294	int rmii_rxc = plat->rmii_rxc ? MT8195_RMII_CLK_SRC_RXC : 0;295	u32 intf_val = 0;296 297	/* select phy interface in top control domain */298	switch (plat->phy_mode) {299	case PHY_INTERFACE_MODE_MII:300		intf_val |= FIELD_PREP(MT8195_ETH_INTF_SEL, PHY_INTF_MII);301		break;302	case PHY_INTERFACE_MODE_RMII:303		intf_val |= (rmii_rxc | rmii_clk_from_mac);304		intf_val |= FIELD_PREP(MT8195_ETH_INTF_SEL, PHY_INTF_RMII);305		break;306	case PHY_INTERFACE_MODE_RGMII:307	case PHY_INTERFACE_MODE_RGMII_TXID:308	case PHY_INTERFACE_MODE_RGMII_RXID:309	case PHY_INTERFACE_MODE_RGMII_ID:310		intf_val |= FIELD_PREP(MT8195_ETH_INTF_SEL, PHY_INTF_RGMII);311		break;312	default:313		dev_err(plat->dev, "phy interface not supported\n");314		return -EINVAL;315	}316 317	/* MT8195 only support external PHY */318	intf_val |= MT8195_EXT_PHY_MODE;319 320	regmap_write(plat->peri_regmap, MT8195_PERI_ETH_CTRL0, intf_val);321 322	return 0;323}324 325static void mt8195_delay_ps2stage(struct mediatek_dwmac_plat_data *plat)326{327	struct mac_delay_struct *mac_delay = &plat->mac_delay;328 329	/* 290ps per stage */330	mac_delay->tx_delay /= 290;331	mac_delay->rx_delay /= 290;332}333 334static void mt8195_delay_stage2ps(struct mediatek_dwmac_plat_data *plat)335{336	struct mac_delay_struct *mac_delay = &plat->mac_delay;337 338	/* 290ps per stage */339	mac_delay->tx_delay *= 290;340	mac_delay->rx_delay *= 290;341}342 343static int mt8195_set_delay(struct mediatek_dwmac_plat_data *plat)344{345	struct mac_delay_struct *mac_delay = &plat->mac_delay;346	u32 gtxc_delay_val = 0, delay_val = 0, rmii_delay_val = 0;347 348	mt8195_delay_ps2stage(plat);349 350	switch (plat->phy_mode) {351	case PHY_INTERFACE_MODE_MII:352		delay_val |= FIELD_PREP(MT8195_DLY_TXC_ENABLE, !!mac_delay->tx_delay);353		delay_val |= FIELD_PREP(MT8195_DLY_TXC_STAGES, mac_delay->tx_delay);354		delay_val |= FIELD_PREP(MT8195_DLY_TXC_INV, mac_delay->tx_inv);355 356		delay_val |= FIELD_PREP(MT8195_DLY_RXC_ENABLE, !!mac_delay->rx_delay);357		delay_val |= FIELD_PREP(MT8195_DLY_RXC_STAGES, mac_delay->rx_delay);358		delay_val |= FIELD_PREP(MT8195_DLY_RXC_INV, mac_delay->rx_inv);359		break;360	case PHY_INTERFACE_MODE_RMII:361		if (plat->rmii_clk_from_mac) {362			/* case 1: mac provides the rmii reference clock,363			 * and the clock output to TXC pin.364			 * The egress timing can be adjusted by RMII_TXC delay macro circuit.365			 * The ingress timing can be adjusted by RMII_RXC delay macro circuit.366			 */367			rmii_delay_val |= FIELD_PREP(MT8195_DLY_RMII_TXC_ENABLE,368						     !!mac_delay->tx_delay);369			rmii_delay_val |= FIELD_PREP(MT8195_DLY_RMII_TXC_STAGES,370						     mac_delay->tx_delay);371			rmii_delay_val |= FIELD_PREP(MT8195_DLY_RMII_TXC_INV,372						     mac_delay->tx_inv);373 374			rmii_delay_val |= FIELD_PREP(MT8195_DLY_RMII_RXC_ENABLE,375						     !!mac_delay->rx_delay);376			rmii_delay_val |= FIELD_PREP(MT8195_DLY_RMII_RXC_STAGES,377						     mac_delay->rx_delay);378			rmii_delay_val |= FIELD_PREP(MT8195_DLY_RMII_RXC_INV,379						     mac_delay->rx_inv);380		} else {381			/* case 2: the rmii reference clock is from external phy,382			 * and the property "rmii_rxc" indicates which pin(TXC/RXC)383			 * the reference clk is connected to. The reference clock is a384			 * received signal, so rx_delay/rx_inv are used to indicate385			 * the reference clock timing adjustment386			 */387			if (plat->rmii_rxc) {388				/* the rmii reference clock from outside is connected389				 * to RXC pin, the reference clock will be adjusted390				 * by RXC delay macro circuit.391				 */392				delay_val |= FIELD_PREP(MT8195_DLY_RXC_ENABLE,393							!!mac_delay->rx_delay);394				delay_val |= FIELD_PREP(MT8195_DLY_RXC_STAGES,395							mac_delay->rx_delay);396				delay_val |= FIELD_PREP(MT8195_DLY_RXC_INV,397							mac_delay->rx_inv);398			} else {399				/* the rmii reference clock from outside is connected400				 * to TXC pin, the reference clock will be adjusted401				 * by TXC delay macro circuit.402				 */403				delay_val |= FIELD_PREP(MT8195_DLY_TXC_ENABLE,404							!!mac_delay->rx_delay);405				delay_val |= FIELD_PREP(MT8195_DLY_TXC_STAGES,406							mac_delay->rx_delay);407				delay_val |= FIELD_PREP(MT8195_DLY_TXC_INV,408							mac_delay->rx_inv);409			}410		}411		break;412	case PHY_INTERFACE_MODE_RGMII:413	case PHY_INTERFACE_MODE_RGMII_TXID:414	case PHY_INTERFACE_MODE_RGMII_RXID:415	case PHY_INTERFACE_MODE_RGMII_ID:416		gtxc_delay_val |= FIELD_PREP(MT8195_DLY_GTXC_ENABLE, !!mac_delay->tx_delay);417		gtxc_delay_val |= FIELD_PREP(MT8195_DLY_GTXC_STAGES, mac_delay->tx_delay);418		gtxc_delay_val |= FIELD_PREP(MT8195_DLY_GTXC_INV, mac_delay->tx_inv);419 420		delay_val |= FIELD_PREP(MT8195_DLY_RXC_ENABLE, !!mac_delay->rx_delay);421		delay_val |= FIELD_PREP(MT8195_DLY_RXC_STAGES, mac_delay->rx_delay);422		delay_val |= FIELD_PREP(MT8195_DLY_RXC_INV, mac_delay->rx_inv);423 424		break;425	default:426		dev_err(plat->dev, "phy interface not supported\n");427		return -EINVAL;428	}429 430	regmap_update_bits(plat->peri_regmap,431			   MT8195_PERI_ETH_CTRL0,432			   MT8195_RGMII_TXC_PHASE_CTRL |433			   MT8195_DLY_GTXC_INV |434			   MT8195_DLY_GTXC_ENABLE |435			   MT8195_DLY_GTXC_STAGES,436			   gtxc_delay_val);437	regmap_write(plat->peri_regmap, MT8195_PERI_ETH_CTRL1, delay_val);438	regmap_write(plat->peri_regmap, MT8195_PERI_ETH_CTRL2, rmii_delay_val);439 440	mt8195_delay_stage2ps(plat);441 442	return 0;443}444 445static const struct mediatek_dwmac_variant mt8195_gmac_variant = {446	.dwmac_set_phy_interface = mt8195_set_interface,447	.dwmac_set_delay = mt8195_set_delay,448	.clk_list = mt8195_dwmac_clk_l,449	.num_clks = ARRAY_SIZE(mt8195_dwmac_clk_l),450	.dma_bit_mask = 35,451	.rx_delay_max = 9280,452	.tx_delay_max = 9280,453};454 455static int mediatek_dwmac_config_dt(struct mediatek_dwmac_plat_data *plat)456{457	struct mac_delay_struct *mac_delay = &plat->mac_delay;458	u32 tx_delay_ps, rx_delay_ps;459	int err;460 461	plat->peri_regmap = syscon_regmap_lookup_by_phandle(plat->np, "mediatek,pericfg");462	if (IS_ERR(plat->peri_regmap)) {463		dev_err(plat->dev, "Failed to get pericfg syscon\n");464		return PTR_ERR(plat->peri_regmap);465	}466 467	err = of_get_phy_mode(plat->np, &plat->phy_mode);468	if (err) {469		dev_err(plat->dev, "not find phy-mode\n");470		return err;471	}472 473	if (!of_property_read_u32(plat->np, "mediatek,tx-delay-ps", &tx_delay_ps)) {474		if (tx_delay_ps < plat->variant->tx_delay_max) {475			mac_delay->tx_delay = tx_delay_ps;476		} else {477			dev_err(plat->dev, "Invalid TX clock delay: %dps\n", tx_delay_ps);478			return -EINVAL;479		}480	}481 482	if (!of_property_read_u32(plat->np, "mediatek,rx-delay-ps", &rx_delay_ps)) {483		if (rx_delay_ps < plat->variant->rx_delay_max) {484			mac_delay->rx_delay = rx_delay_ps;485		} else {486			dev_err(plat->dev, "Invalid RX clock delay: %dps\n", rx_delay_ps);487			return -EINVAL;488		}489	}490 491	mac_delay->tx_inv = of_property_read_bool(plat->np, "mediatek,txc-inverse");492	mac_delay->rx_inv = of_property_read_bool(plat->np, "mediatek,rxc-inverse");493	plat->rmii_rxc = of_property_read_bool(plat->np, "mediatek,rmii-rxc");494	plat->rmii_clk_from_mac = of_property_read_bool(plat->np, "mediatek,rmii-clk-from-mac");495	plat->mac_wol = of_property_read_bool(plat->np, "mediatek,mac-wol");496 497	return 0;498}499 500static int mediatek_dwmac_clk_init(struct mediatek_dwmac_plat_data *plat)501{502	const struct mediatek_dwmac_variant *variant = plat->variant;503	int i, ret;504 505	plat->clks = devm_kcalloc(plat->dev, variant->num_clks, sizeof(*plat->clks), GFP_KERNEL);506	if (!plat->clks)507		return -ENOMEM;508 509	for (i = 0; i < variant->num_clks; i++)510		plat->clks[i].id = variant->clk_list[i];511 512	ret = devm_clk_bulk_get(plat->dev, variant->num_clks, plat->clks);513	if (ret)514		return ret;515 516	/* The clock labeled as "rmii_internal" is needed only in RMII(when517	 * MAC provides the reference clock), and useless for RGMII/MII or518	 * RMII(when PHY provides the reference clock).519	 * So, "rmii_internal" clock is got and configured only when520	 * reference clock of RMII is from MAC.521	 */522	if (plat->rmii_clk_from_mac) {523		plat->rmii_internal_clk = devm_clk_get(plat->dev, "rmii_internal");524		if (IS_ERR(plat->rmii_internal_clk))525			ret = PTR_ERR(plat->rmii_internal_clk);526	} else {527		plat->rmii_internal_clk = NULL;528	}529 530	return ret;531}532 533static int mediatek_dwmac_init(struct platform_device *pdev, void *priv)534{535	struct mediatek_dwmac_plat_data *plat = priv;536	const struct mediatek_dwmac_variant *variant = plat->variant;537	int ret;538 539	if (variant->dwmac_set_phy_interface) {540		ret = variant->dwmac_set_phy_interface(plat);541		if (ret) {542			dev_err(plat->dev, "failed to set phy interface, err = %d\n", ret);543			return ret;544		}545	}546 547	if (variant->dwmac_set_delay) {548		ret = variant->dwmac_set_delay(plat);549		if (ret) {550			dev_err(plat->dev, "failed to set delay value, err = %d\n", ret);551			return ret;552		}553	}554 555	return 0;556}557 558static int mediatek_dwmac_clks_config(void *priv, bool enabled)559{560	struct mediatek_dwmac_plat_data *plat = priv;561	const struct mediatek_dwmac_variant *variant = plat->variant;562	int ret = 0;563 564	if (enabled) {565		ret = clk_bulk_prepare_enable(variant->num_clks, plat->clks);566		if (ret) {567			dev_err(plat->dev, "failed to enable clks, err = %d\n", ret);568			return ret;569		}570 571		ret = clk_prepare_enable(plat->rmii_internal_clk);572		if (ret) {573			dev_err(plat->dev, "failed to enable rmii internal clk, err = %d\n", ret);574			return ret;575		}576	} else {577		clk_disable_unprepare(plat->rmii_internal_clk);578		clk_bulk_disable_unprepare(variant->num_clks, plat->clks);579	}580 581	return ret;582}583 584static int mediatek_dwmac_common_data(struct platform_device *pdev,585				      struct plat_stmmacenet_data *plat,586				      struct mediatek_dwmac_plat_data *priv_plat)587{588	int i;589 590	plat->mac_interface = priv_plat->phy_mode;591	if (priv_plat->mac_wol)592		plat->flags &= ~STMMAC_FLAG_USE_PHY_WOL;593	else594		plat->flags |= STMMAC_FLAG_USE_PHY_WOL;595	plat->riwt_off = 1;596	plat->maxmtu = ETH_DATA_LEN;597	plat->host_dma_width = priv_plat->variant->dma_bit_mask;598	plat->bsp_priv = priv_plat;599	plat->init = mediatek_dwmac_init;600	plat->clks_config = mediatek_dwmac_clks_config;601 602	plat->safety_feat_cfg = devm_kzalloc(&pdev->dev,603					     sizeof(*plat->safety_feat_cfg),604					     GFP_KERNEL);605	if (!plat->safety_feat_cfg)606		return -ENOMEM;607 608	plat->safety_feat_cfg->tsoee = 1;609	plat->safety_feat_cfg->mrxpee = 0;610	plat->safety_feat_cfg->mestee = 1;611	plat->safety_feat_cfg->mrxee = 1;612	plat->safety_feat_cfg->mtxee = 1;613	plat->safety_feat_cfg->epsi = 0;614	plat->safety_feat_cfg->edpp = 1;615	plat->safety_feat_cfg->prtyen = 1;616	plat->safety_feat_cfg->tmouten = 1;617 618	for (i = 0; i < plat->tx_queues_to_use; i++) {619		/* Default TX Q0 to use TSO and rest TXQ for TBS */620		if (i > 0)621			plat->tx_queues_cfg[i].tbs_en = 1;622	}623 624	return 0;625}626 627static int mediatek_dwmac_probe(struct platform_device *pdev)628{629	struct mediatek_dwmac_plat_data *priv_plat;630	struct plat_stmmacenet_data *plat_dat;631	struct stmmac_resources stmmac_res;632	int ret;633 634	priv_plat = devm_kzalloc(&pdev->dev, sizeof(*priv_plat), GFP_KERNEL);635	if (!priv_plat)636		return -ENOMEM;637 638	priv_plat->variant = of_device_get_match_data(&pdev->dev);639	if (!priv_plat->variant) {640		dev_err(&pdev->dev, "Missing dwmac-mediatek variant\n");641		return -EINVAL;642	}643 644	priv_plat->dev = &pdev->dev;645	priv_plat->np = pdev->dev.of_node;646 647	ret = mediatek_dwmac_config_dt(priv_plat);648	if (ret)649		return ret;650 651	ret = mediatek_dwmac_clk_init(priv_plat);652	if (ret)653		return ret;654 655	ret = stmmac_get_platform_resources(pdev, &stmmac_res);656	if (ret)657		return ret;658 659	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);660	if (IS_ERR(plat_dat))661		return PTR_ERR(plat_dat);662 663	mediatek_dwmac_common_data(pdev, plat_dat, priv_plat);664	mediatek_dwmac_init(pdev, priv_plat);665 666	ret = mediatek_dwmac_clks_config(priv_plat, true);667	if (ret)668		return ret;669 670	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);671	if (ret)672		goto err_drv_probe;673 674	return 0;675 676err_drv_probe:677	mediatek_dwmac_clks_config(priv_plat, false);678 679	return ret;680}681 682static void mediatek_dwmac_remove(struct platform_device *pdev)683{684	struct mediatek_dwmac_plat_data *priv_plat = get_stmmac_bsp_priv(&pdev->dev);685 686	stmmac_pltfr_remove(pdev);687	mediatek_dwmac_clks_config(priv_plat, false);688}689 690static const struct of_device_id mediatek_dwmac_match[] = {691	{ .compatible = "mediatek,mt2712-gmac",692	  .data = &mt2712_gmac_variant },693	{ .compatible = "mediatek,mt8195-gmac",694	  .data = &mt8195_gmac_variant },695	{ }696};697 698MODULE_DEVICE_TABLE(of, mediatek_dwmac_match);699 700static struct platform_driver mediatek_dwmac_driver = {701	.probe  = mediatek_dwmac_probe,702	.remove_new = mediatek_dwmac_remove,703	.driver = {704		.name           = "dwmac-mediatek",705		.pm		= &stmmac_pltfr_pm_ops,706		.of_match_table = mediatek_dwmac_match,707	},708};709module_platform_driver(mediatek_dwmac_driver);710 711MODULE_AUTHOR("Biao Huang <biao.huang@mediatek.com>");712MODULE_DESCRIPTION("MediaTek DWMAC specific glue layer");713MODULE_LICENSE("GPL v2");714