18c7bd5a4SBartosz Golaszewski // SPDX-License-Identifier: GPL-2.0-only 28c7bd5a4SBartosz Golaszewski /* 38c7bd5a4SBartosz Golaszewski * Copyright (c) 2020 MediaTek Corporation 48c7bd5a4SBartosz Golaszewski * Copyright (c) 2020 BayLibre SAS 58c7bd5a4SBartosz Golaszewski * 68c7bd5a4SBartosz Golaszewski * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> 78c7bd5a4SBartosz Golaszewski */ 88c7bd5a4SBartosz Golaszewski 98c7bd5a4SBartosz Golaszewski #include <linux/bits.h> 108c7bd5a4SBartosz Golaszewski #include <linux/clk.h> 118c7bd5a4SBartosz Golaszewski #include <linux/compiler.h> 128c7bd5a4SBartosz Golaszewski #include <linux/dma-mapping.h> 138c7bd5a4SBartosz Golaszewski #include <linux/etherdevice.h> 148c7bd5a4SBartosz Golaszewski #include <linux/kernel.h> 158c7bd5a4SBartosz Golaszewski #include <linux/mfd/syscon.h> 168c7bd5a4SBartosz Golaszewski #include <linux/mii.h> 178c7bd5a4SBartosz Golaszewski #include <linux/module.h> 188c7bd5a4SBartosz Golaszewski #include <linux/netdevice.h> 198c7bd5a4SBartosz Golaszewski #include <linux/of.h> 208c7bd5a4SBartosz Golaszewski #include <linux/of_mdio.h> 218c7bd5a4SBartosz Golaszewski #include <linux/of_net.h> 228c7bd5a4SBartosz Golaszewski #include <linux/platform_device.h> 238c7bd5a4SBartosz Golaszewski #include <linux/pm.h> 248c7bd5a4SBartosz Golaszewski #include <linux/regmap.h> 258c7bd5a4SBartosz Golaszewski #include <linux/skbuff.h> 268c7bd5a4SBartosz Golaszewski #include <linux/spinlock.h> 278c7bd5a4SBartosz Golaszewski 288c7bd5a4SBartosz Golaszewski #define MTK_STAR_DRVNAME "mtk_star_emac" 298c7bd5a4SBartosz Golaszewski 308c7bd5a4SBartosz Golaszewski #define MTK_STAR_WAIT_TIMEOUT 300 318c7bd5a4SBartosz Golaszewski #define MTK_STAR_MAX_FRAME_SIZE 1514 328c7bd5a4SBartosz Golaszewski #define MTK_STAR_SKB_ALIGNMENT 16 338c7bd5a4SBartosz Golaszewski #define MTK_STAR_NAPI_WEIGHT 64 348c7bd5a4SBartosz Golaszewski #define MTK_STAR_HASHTABLE_MC_LIMIT 256 358c7bd5a4SBartosz Golaszewski #define MTK_STAR_HASHTABLE_SIZE_MAX 512 368c7bd5a4SBartosz Golaszewski 378c7bd5a4SBartosz Golaszewski /* Normally we'd use NET_IP_ALIGN but on arm64 its value is 0 and it doesn't 388c7bd5a4SBartosz Golaszewski * work for this controller. 398c7bd5a4SBartosz Golaszewski */ 408c7bd5a4SBartosz Golaszewski #define MTK_STAR_IP_ALIGN 2 418c7bd5a4SBartosz Golaszewski 428c7bd5a4SBartosz Golaszewski static const char *const mtk_star_clk_names[] = { "core", "reg", "trans" }; 438c7bd5a4SBartosz Golaszewski #define MTK_STAR_NCLKS ARRAY_SIZE(mtk_star_clk_names) 448c7bd5a4SBartosz Golaszewski 458c7bd5a4SBartosz Golaszewski /* PHY Control Register 0 */ 468c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_PHY_CTRL0 0x0000 478c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL0_WTCMD BIT(13) 488c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL0_RDCMD BIT(14) 498c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL0_RWOK BIT(15) 508c7bd5a4SBartosz Golaszewski #define MTK_STAR_MSK_PHY_CTRL0_PREG GENMASK(12, 8) 518c7bd5a4SBartosz Golaszewski #define MTK_STAR_OFF_PHY_CTRL0_PREG 8 528c7bd5a4SBartosz Golaszewski #define MTK_STAR_MSK_PHY_CTRL0_RWDATA GENMASK(31, 16) 538c7bd5a4SBartosz Golaszewski #define MTK_STAR_OFF_PHY_CTRL0_RWDATA 16 548c7bd5a4SBartosz Golaszewski 558c7bd5a4SBartosz Golaszewski /* PHY Control Register 1 */ 568c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_PHY_CTRL1 0x0004 578c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL1_LINK_ST BIT(0) 588c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL1_AN_EN BIT(8) 598c7bd5a4SBartosz Golaszewski #define MTK_STAR_OFF_PHY_CTRL1_FORCE_SPD 9 608c7bd5a4SBartosz Golaszewski #define MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_10M 0x00 618c7bd5a4SBartosz Golaszewski #define MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_100M 0x01 628c7bd5a4SBartosz Golaszewski #define MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_1000M 0x02 638c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL1_FORCE_DPX BIT(11) 648c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_RX BIT(12) 658c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_TX BIT(13) 668c7bd5a4SBartosz Golaszewski 678c7bd5a4SBartosz Golaszewski /* MAC Configuration Register */ 688c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_MAC_CFG 0x0008 698c7bd5a4SBartosz Golaszewski #define MTK_STAR_OFF_MAC_CFG_IPG 10 708c7bd5a4SBartosz Golaszewski #define MTK_STAR_VAL_MAC_CFG_IPG_96BIT GENMASK(4, 0) 718c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_MAC_CFG_MAXLEN_1522 BIT(16) 728c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_MAC_CFG_AUTO_PAD BIT(19) 738c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_MAC_CFG_CRC_STRIP BIT(20) 748c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_MAC_CFG_VLAN_STRIP BIT(22) 758c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_MAC_CFG_NIC_PD BIT(31) 768c7bd5a4SBartosz Golaszewski 778c7bd5a4SBartosz Golaszewski /* Flow-Control Configuration Register */ 788c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_FC_CFG 0x000c 798c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_FC_CFG_BP_EN BIT(7) 808c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_FC_CFG_UC_PAUSE_DIR BIT(8) 818c7bd5a4SBartosz Golaszewski #define MTK_STAR_OFF_FC_CFG_SEND_PAUSE_TH 16 828c7bd5a4SBartosz Golaszewski #define MTK_STAR_MSK_FC_CFG_SEND_PAUSE_TH GENMASK(27, 16) 838c7bd5a4SBartosz Golaszewski #define MTK_STAR_VAL_FC_CFG_SEND_PAUSE_TH_2K 0x800 848c7bd5a4SBartosz Golaszewski 858c7bd5a4SBartosz Golaszewski /* ARL Configuration Register */ 868c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_ARL_CFG 0x0010 878c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_ARL_CFG_HASH_ALG BIT(0) 888c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_ARL_CFG_MISC_MODE BIT(4) 898c7bd5a4SBartosz Golaszewski 908c7bd5a4SBartosz Golaszewski /* MAC High and Low Bytes Registers */ 918c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_MY_MAC_H 0x0014 928c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_MY_MAC_L 0x0018 938c7bd5a4SBartosz Golaszewski 948c7bd5a4SBartosz Golaszewski /* Hash Table Control Register */ 958c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_HASH_CTRL 0x001c 968c7bd5a4SBartosz Golaszewski #define MTK_STAR_MSK_HASH_CTRL_HASH_BIT_ADDR GENMASK(8, 0) 978c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_HASH_CTRL_HASH_BIT_DATA BIT(12) 988c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_HASH_CTRL_ACC_CMD BIT(13) 998c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_HASH_CTRL_CMD_START BIT(14) 1008c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_HASH_CTRL_BIST_OK BIT(16) 1018c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_HASH_CTRL_BIST_DONE BIT(17) 1028c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_HASH_CTRL_BIST_EN BIT(31) 1038c7bd5a4SBartosz Golaszewski 1048c7bd5a4SBartosz Golaszewski /* TX DMA Control Register */ 1058c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_TX_DMA_CTRL 0x0034 1068c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_TX_DMA_CTRL_START BIT(0) 1078c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_TX_DMA_CTRL_STOP BIT(1) 1088c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_TX_DMA_CTRL_RESUME BIT(2) 1098c7bd5a4SBartosz Golaszewski 1108c7bd5a4SBartosz Golaszewski /* RX DMA Control Register */ 1118c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_RX_DMA_CTRL 0x0038 1128c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_RX_DMA_CTRL_START BIT(0) 1138c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_RX_DMA_CTRL_STOP BIT(1) 1148c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_RX_DMA_CTRL_RESUME BIT(2) 1158c7bd5a4SBartosz Golaszewski 1168c7bd5a4SBartosz Golaszewski /* DMA Address Registers */ 1178c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_TX_DPTR 0x003c 1188c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_RX_DPTR 0x0040 1198c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_TX_BASE_ADDR 0x0044 1208c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_RX_BASE_ADDR 0x0048 1218c7bd5a4SBartosz Golaszewski 1228c7bd5a4SBartosz Golaszewski /* Interrupt Status Register */ 1238c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_INT_STS 0x0050 1248c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_INT_STS_PORT_STS_CHG BIT(2) 1258c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_INT_STS_MIB_CNT_TH BIT(3) 1268c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_INT_STS_FNRC BIT(6) 1278c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_INT_STS_TNTC BIT(8) 1288c7bd5a4SBartosz Golaszewski 1298c7bd5a4SBartosz Golaszewski /* Interrupt Mask Register */ 1308c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_INT_MASK 0x0054 1318c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_INT_MASK_FNRC BIT(6) 1328c7bd5a4SBartosz Golaszewski 1338c7bd5a4SBartosz Golaszewski /* Misc. Config Register */ 1348c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_TEST1 0x005c 1358c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_TEST1_RST_HASH_MBIST BIT(31) 1368c7bd5a4SBartosz Golaszewski 1378c7bd5a4SBartosz Golaszewski /* Extended Configuration Register */ 1388c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_EXT_CFG 0x0060 1398c7bd5a4SBartosz Golaszewski #define MTK_STAR_OFF_EXT_CFG_SND_PAUSE_RLS 16 1408c7bd5a4SBartosz Golaszewski #define MTK_STAR_MSK_EXT_CFG_SND_PAUSE_RLS GENMASK(26, 16) 1418c7bd5a4SBartosz Golaszewski #define MTK_STAR_VAL_EXT_CFG_SND_PAUSE_RLS_1K 0x400 1428c7bd5a4SBartosz Golaszewski 1438c7bd5a4SBartosz Golaszewski /* EthSys Configuration Register */ 1448c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_SYS_CONF 0x0094 1458c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_MII_PAD_OUT_ENABLE BIT(0) 1468c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_EXT_MDC_MODE BIT(1) 1478c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_SWC_MII_MODE BIT(2) 1488c7bd5a4SBartosz Golaszewski 1498c7bd5a4SBartosz Golaszewski /* MAC Clock Configuration Register */ 1508c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_MAC_CLK_CONF 0x00ac 1518c7bd5a4SBartosz Golaszewski #define MTK_STAR_MSK_MAC_CLK_CONF GENMASK(7, 0) 1528c7bd5a4SBartosz Golaszewski #define MTK_STAR_BIT_CLK_DIV_10 0x0a 1538c7bd5a4SBartosz Golaszewski 1548c7bd5a4SBartosz Golaszewski /* Counter registers. */ 1558c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXOKPKT 0x0100 1568c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXOKBYTE 0x0104 1578c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXRUNT 0x0108 1588c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXLONG 0x010c 1598c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXDROP 0x0110 1608c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXCRC 0x0114 1618c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXARLDROP 0x0118 1628c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXVLANDROP 0x011c 1638c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXCSERR 0x0120 1648c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXPAUSE 0x0124 1658c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXOKPKT 0x0128 1668c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXOKBYTE 0x012c 1678c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXPAUSECOL 0x0130 1688c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXRTY 0x0134 1698c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXSKIP 0x0138 1708c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_ARP 0x013c 1718c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_RERR 0x01d8 1728c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_UNI 0x01dc 1738c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_MULTI 0x01e0 1748c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_BROAD 0x01e4 1758c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_ALIGNERR 0x01e8 1768c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_UNI 0x01ec 1778c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_MULTI 0x01f0 1788c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_BROAD 0x01f4 1798c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_TIMEOUT 0x01f8 1808c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_LATECOL 0x01fc 1818c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_LENGTHERR 0x0214 1828c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_TWIST 0x0218 1838c7bd5a4SBartosz Golaszewski 1848c7bd5a4SBartosz Golaszewski /* Ethernet CFG Control */ 1858c7bd5a4SBartosz Golaszewski #define MTK_PERICFG_REG_NIC_CFG_CON 0x03c4 1868c7bd5a4SBartosz Golaszewski #define MTK_PERICFG_MSK_NIC_CFG_CON_CFG_MII GENMASK(3, 0) 1878c7bd5a4SBartosz Golaszewski #define MTK_PERICFG_BIT_NIC_CFG_CON_RMII BIT(0) 1888c7bd5a4SBartosz Golaszewski 1898c7bd5a4SBartosz Golaszewski /* Represents the actual structure of descriptors used by the MAC. We can 1908c7bd5a4SBartosz Golaszewski * reuse the same structure for both TX and RX - the layout is the same, only 1918c7bd5a4SBartosz Golaszewski * the flags differ slightly. 1928c7bd5a4SBartosz Golaszewski */ 1938c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc { 1948c7bd5a4SBartosz Golaszewski /* Contains both the status flags as well as packet length. */ 1958c7bd5a4SBartosz Golaszewski u32 status; 1968c7bd5a4SBartosz Golaszewski u32 data_ptr; 1978c7bd5a4SBartosz Golaszewski u32 vtag; 1988c7bd5a4SBartosz Golaszewski u32 reserved; 1998c7bd5a4SBartosz Golaszewski }; 2008c7bd5a4SBartosz Golaszewski 2018c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_MSK_LEN GENMASK(15, 0) 2028c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_RX_CRCE BIT(24) 2038c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_RX_OSIZE BIT(25) 2048c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_INT BIT(27) 2058c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_LS BIT(28) 2068c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_FS BIT(29) 2078c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_EOR BIT(30) 2088c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_COWN BIT(31) 2098c7bd5a4SBartosz Golaszewski 2108c7bd5a4SBartosz Golaszewski /* Helper structure for storing data read from/written to descriptors in order 2118c7bd5a4SBartosz Golaszewski * to limit reads from/writes to DMA memory. 2128c7bd5a4SBartosz Golaszewski */ 2138c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data { 2148c7bd5a4SBartosz Golaszewski unsigned int len; 2158c7bd5a4SBartosz Golaszewski unsigned int flags; 2168c7bd5a4SBartosz Golaszewski dma_addr_t dma_addr; 2178c7bd5a4SBartosz Golaszewski struct sk_buff *skb; 2188c7bd5a4SBartosz Golaszewski }; 2198c7bd5a4SBartosz Golaszewski 2208c7bd5a4SBartosz Golaszewski #define MTK_STAR_RING_NUM_DESCS 128 2218c7bd5a4SBartosz Golaszewski #define MTK_STAR_NUM_TX_DESCS MTK_STAR_RING_NUM_DESCS 2228c7bd5a4SBartosz Golaszewski #define MTK_STAR_NUM_RX_DESCS MTK_STAR_RING_NUM_DESCS 2238c7bd5a4SBartosz Golaszewski #define MTK_STAR_NUM_DESCS_TOTAL (MTK_STAR_RING_NUM_DESCS * 2) 2248c7bd5a4SBartosz Golaszewski #define MTK_STAR_DMA_SIZE \ 2258c7bd5a4SBartosz Golaszewski (MTK_STAR_NUM_DESCS_TOTAL * sizeof(struct mtk_star_ring_desc)) 2268c7bd5a4SBartosz Golaszewski 2278c7bd5a4SBartosz Golaszewski struct mtk_star_ring { 2288c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *descs; 2298c7bd5a4SBartosz Golaszewski struct sk_buff *skbs[MTK_STAR_RING_NUM_DESCS]; 2308c7bd5a4SBartosz Golaszewski dma_addr_t dma_addrs[MTK_STAR_RING_NUM_DESCS]; 2318c7bd5a4SBartosz Golaszewski unsigned int head; 2328c7bd5a4SBartosz Golaszewski unsigned int tail; 2338c7bd5a4SBartosz Golaszewski }; 2348c7bd5a4SBartosz Golaszewski 2358c7bd5a4SBartosz Golaszewski struct mtk_star_priv { 2368c7bd5a4SBartosz Golaszewski struct net_device *ndev; 2378c7bd5a4SBartosz Golaszewski 2388c7bd5a4SBartosz Golaszewski struct regmap *regs; 2398c7bd5a4SBartosz Golaszewski struct regmap *pericfg; 2408c7bd5a4SBartosz Golaszewski 2418c7bd5a4SBartosz Golaszewski struct clk_bulk_data clks[MTK_STAR_NCLKS]; 2428c7bd5a4SBartosz Golaszewski 2438c7bd5a4SBartosz Golaszewski void *ring_base; 2448c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *descs_base; 2458c7bd5a4SBartosz Golaszewski dma_addr_t dma_addr; 2468c7bd5a4SBartosz Golaszewski struct mtk_star_ring tx_ring; 2478c7bd5a4SBartosz Golaszewski struct mtk_star_ring rx_ring; 2488c7bd5a4SBartosz Golaszewski 2498c7bd5a4SBartosz Golaszewski struct mii_bus *mii; 2508c7bd5a4SBartosz Golaszewski struct napi_struct napi; 2518c7bd5a4SBartosz Golaszewski 2528c7bd5a4SBartosz Golaszewski struct device_node *phy_node; 2538c7bd5a4SBartosz Golaszewski phy_interface_t phy_intf; 2548c7bd5a4SBartosz Golaszewski struct phy_device *phydev; 2558c7bd5a4SBartosz Golaszewski unsigned int link; 2568c7bd5a4SBartosz Golaszewski int speed; 2578c7bd5a4SBartosz Golaszewski int duplex; 2588c7bd5a4SBartosz Golaszewski int pause; 2598c7bd5a4SBartosz Golaszewski 2608c7bd5a4SBartosz Golaszewski /* Protects against concurrent descriptor access. */ 2618c7bd5a4SBartosz Golaszewski spinlock_t lock; 2628c7bd5a4SBartosz Golaszewski 2638c7bd5a4SBartosz Golaszewski struct rtnl_link_stats64 stats; 2648c7bd5a4SBartosz Golaszewski }; 2658c7bd5a4SBartosz Golaszewski 2668c7bd5a4SBartosz Golaszewski static struct device *mtk_star_get_dev(struct mtk_star_priv *priv) 2678c7bd5a4SBartosz Golaszewski { 2688c7bd5a4SBartosz Golaszewski return priv->ndev->dev.parent; 2698c7bd5a4SBartosz Golaszewski } 2708c7bd5a4SBartosz Golaszewski 2718c7bd5a4SBartosz Golaszewski static const struct regmap_config mtk_star_regmap_config = { 2728c7bd5a4SBartosz Golaszewski .reg_bits = 32, 2738c7bd5a4SBartosz Golaszewski .val_bits = 32, 2748c7bd5a4SBartosz Golaszewski .reg_stride = 4, 2758c7bd5a4SBartosz Golaszewski .disable_locking = true, 2768c7bd5a4SBartosz Golaszewski }; 2778c7bd5a4SBartosz Golaszewski 2788c7bd5a4SBartosz Golaszewski static void mtk_star_ring_init(struct mtk_star_ring *ring, 2798c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *descs) 2808c7bd5a4SBartosz Golaszewski { 2818c7bd5a4SBartosz Golaszewski memset(ring, 0, sizeof(*ring)); 2828c7bd5a4SBartosz Golaszewski ring->descs = descs; 2838c7bd5a4SBartosz Golaszewski ring->head = 0; 2848c7bd5a4SBartosz Golaszewski ring->tail = 0; 2858c7bd5a4SBartosz Golaszewski } 2868c7bd5a4SBartosz Golaszewski 2878c7bd5a4SBartosz Golaszewski static int mtk_star_ring_pop_tail(struct mtk_star_ring *ring, 2888c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 2898c7bd5a4SBartosz Golaszewski { 2908c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc = &ring->descs[ring->tail]; 2918c7bd5a4SBartosz Golaszewski unsigned int status; 2928c7bd5a4SBartosz Golaszewski 2938c7bd5a4SBartosz Golaszewski status = READ_ONCE(desc->status); 2948c7bd5a4SBartosz Golaszewski dma_rmb(); /* Make sure we read the status bits before checking it. */ 2958c7bd5a4SBartosz Golaszewski 2968c7bd5a4SBartosz Golaszewski if (!(status & MTK_STAR_DESC_BIT_COWN)) 2978c7bd5a4SBartosz Golaszewski return -1; 2988c7bd5a4SBartosz Golaszewski 2998c7bd5a4SBartosz Golaszewski desc_data->len = status & MTK_STAR_DESC_MSK_LEN; 3008c7bd5a4SBartosz Golaszewski desc_data->flags = status & ~MTK_STAR_DESC_MSK_LEN; 3018c7bd5a4SBartosz Golaszewski desc_data->dma_addr = ring->dma_addrs[ring->tail]; 3028c7bd5a4SBartosz Golaszewski desc_data->skb = ring->skbs[ring->tail]; 3038c7bd5a4SBartosz Golaszewski 3048c7bd5a4SBartosz Golaszewski ring->dma_addrs[ring->tail] = 0; 3058c7bd5a4SBartosz Golaszewski ring->skbs[ring->tail] = NULL; 3068c7bd5a4SBartosz Golaszewski 3078c7bd5a4SBartosz Golaszewski status &= MTK_STAR_DESC_BIT_COWN | MTK_STAR_DESC_BIT_EOR; 3088c7bd5a4SBartosz Golaszewski 3098c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->data_ptr, 0); 3108c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->status, status); 3118c7bd5a4SBartosz Golaszewski 3128c7bd5a4SBartosz Golaszewski ring->tail = (ring->tail + 1) % MTK_STAR_RING_NUM_DESCS; 3138c7bd5a4SBartosz Golaszewski 3148c7bd5a4SBartosz Golaszewski return 0; 3158c7bd5a4SBartosz Golaszewski } 3168c7bd5a4SBartosz Golaszewski 3178c7bd5a4SBartosz Golaszewski static void mtk_star_ring_push_head(struct mtk_star_ring *ring, 3188c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data, 3198c7bd5a4SBartosz Golaszewski unsigned int flags) 3208c7bd5a4SBartosz Golaszewski { 3218c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc = &ring->descs[ring->head]; 3228c7bd5a4SBartosz Golaszewski unsigned int status; 3238c7bd5a4SBartosz Golaszewski 3248c7bd5a4SBartosz Golaszewski status = READ_ONCE(desc->status); 3258c7bd5a4SBartosz Golaszewski 3268c7bd5a4SBartosz Golaszewski ring->skbs[ring->head] = desc_data->skb; 3278c7bd5a4SBartosz Golaszewski ring->dma_addrs[ring->head] = desc_data->dma_addr; 3288c7bd5a4SBartosz Golaszewski 3298c7bd5a4SBartosz Golaszewski status |= desc_data->len; 3308c7bd5a4SBartosz Golaszewski if (flags) 3318c7bd5a4SBartosz Golaszewski status |= flags; 3328c7bd5a4SBartosz Golaszewski 3338c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->data_ptr, desc_data->dma_addr); 3348c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->status, status); 3358c7bd5a4SBartosz Golaszewski status &= ~MTK_STAR_DESC_BIT_COWN; 3368c7bd5a4SBartosz Golaszewski /* Flush previous modifications before ownership change. */ 3378c7bd5a4SBartosz Golaszewski dma_wmb(); 3388c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->status, status); 3398c7bd5a4SBartosz Golaszewski 3408c7bd5a4SBartosz Golaszewski ring->head = (ring->head + 1) % MTK_STAR_RING_NUM_DESCS; 3418c7bd5a4SBartosz Golaszewski } 3428c7bd5a4SBartosz Golaszewski 3438c7bd5a4SBartosz Golaszewski static void 3448c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_rx(struct mtk_star_ring *ring, 3458c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 3468c7bd5a4SBartosz Golaszewski { 3478c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head(ring, desc_data, 0); 3488c7bd5a4SBartosz Golaszewski } 3498c7bd5a4SBartosz Golaszewski 3508c7bd5a4SBartosz Golaszewski static void 3518c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_tx(struct mtk_star_ring *ring, 3528c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 3538c7bd5a4SBartosz Golaszewski { 3548c7bd5a4SBartosz Golaszewski static const unsigned int flags = MTK_STAR_DESC_BIT_FS | 3558c7bd5a4SBartosz Golaszewski MTK_STAR_DESC_BIT_LS | 3568c7bd5a4SBartosz Golaszewski MTK_STAR_DESC_BIT_INT; 3578c7bd5a4SBartosz Golaszewski 3588c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head(ring, desc_data, flags); 3598c7bd5a4SBartosz Golaszewski } 3608c7bd5a4SBartosz Golaszewski 3618c7bd5a4SBartosz Golaszewski static unsigned int mtk_star_ring_num_used_descs(struct mtk_star_ring *ring) 3628c7bd5a4SBartosz Golaszewski { 3638c7bd5a4SBartosz Golaszewski return abs(ring->head - ring->tail); 3648c7bd5a4SBartosz Golaszewski } 3658c7bd5a4SBartosz Golaszewski 3668c7bd5a4SBartosz Golaszewski static bool mtk_star_ring_full(struct mtk_star_ring *ring) 3678c7bd5a4SBartosz Golaszewski { 3688c7bd5a4SBartosz Golaszewski return mtk_star_ring_num_used_descs(ring) == MTK_STAR_RING_NUM_DESCS; 3698c7bd5a4SBartosz Golaszewski } 3708c7bd5a4SBartosz Golaszewski 3718c7bd5a4SBartosz Golaszewski static bool mtk_star_ring_descs_available(struct mtk_star_ring *ring) 3728c7bd5a4SBartosz Golaszewski { 3738c7bd5a4SBartosz Golaszewski return mtk_star_ring_num_used_descs(ring) > 0; 3748c7bd5a4SBartosz Golaszewski } 3758c7bd5a4SBartosz Golaszewski 3768c7bd5a4SBartosz Golaszewski static dma_addr_t mtk_star_dma_map_rx(struct mtk_star_priv *priv, 3778c7bd5a4SBartosz Golaszewski struct sk_buff *skb) 3788c7bd5a4SBartosz Golaszewski { 3798c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 3808c7bd5a4SBartosz Golaszewski 3818c7bd5a4SBartosz Golaszewski /* Data pointer for the RX DMA descriptor must be aligned to 4N + 2. */ 3828c7bd5a4SBartosz Golaszewski return dma_map_single(dev, skb_tail_pointer(skb) - 2, 3838c7bd5a4SBartosz Golaszewski skb_tailroom(skb), DMA_FROM_DEVICE); 3848c7bd5a4SBartosz Golaszewski } 3858c7bd5a4SBartosz Golaszewski 3868c7bd5a4SBartosz Golaszewski static void mtk_star_dma_unmap_rx(struct mtk_star_priv *priv, 3878c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 3888c7bd5a4SBartosz Golaszewski { 3898c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 3908c7bd5a4SBartosz Golaszewski 3918c7bd5a4SBartosz Golaszewski dma_unmap_single(dev, desc_data->dma_addr, 3928c7bd5a4SBartosz Golaszewski skb_tailroom(desc_data->skb), DMA_FROM_DEVICE); 3938c7bd5a4SBartosz Golaszewski } 3948c7bd5a4SBartosz Golaszewski 3958c7bd5a4SBartosz Golaszewski static dma_addr_t mtk_star_dma_map_tx(struct mtk_star_priv *priv, 3968c7bd5a4SBartosz Golaszewski struct sk_buff *skb) 3978c7bd5a4SBartosz Golaszewski { 3988c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 3998c7bd5a4SBartosz Golaszewski 4008c7bd5a4SBartosz Golaszewski return dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); 4018c7bd5a4SBartosz Golaszewski } 4028c7bd5a4SBartosz Golaszewski 4038c7bd5a4SBartosz Golaszewski static void mtk_star_dma_unmap_tx(struct mtk_star_priv *priv, 4048c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 4058c7bd5a4SBartosz Golaszewski { 4068c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 4078c7bd5a4SBartosz Golaszewski 4088c7bd5a4SBartosz Golaszewski return dma_unmap_single(dev, desc_data->dma_addr, 4098c7bd5a4SBartosz Golaszewski skb_headlen(desc_data->skb), DMA_TO_DEVICE); 4108c7bd5a4SBartosz Golaszewski } 4118c7bd5a4SBartosz Golaszewski 4128c7bd5a4SBartosz Golaszewski static void mtk_star_nic_disable_pd(struct mtk_star_priv *priv) 4138c7bd5a4SBartosz Golaszewski { 414240f1ae4SBartosz Golaszewski regmap_clear_bits(priv->regs, MTK_STAR_REG_MAC_CFG, 415240f1ae4SBartosz Golaszewski MTK_STAR_BIT_MAC_CFG_NIC_PD); 4168c7bd5a4SBartosz Golaszewski } 4178c7bd5a4SBartosz Golaszewski 4188c7bd5a4SBartosz Golaszewski /* Unmask the three interrupts we care about, mask all others. */ 4198c7bd5a4SBartosz Golaszewski static void mtk_star_intr_enable(struct mtk_star_priv *priv) 4208c7bd5a4SBartosz Golaszewski { 4218c7bd5a4SBartosz Golaszewski unsigned int val = MTK_STAR_BIT_INT_STS_TNTC | 4228c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_INT_STS_FNRC | 4238c7bd5a4SBartosz Golaszewski MTK_STAR_REG_INT_STS_MIB_CNT_TH; 4248c7bd5a4SBartosz Golaszewski 4258c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_INT_MASK, ~val); 4268c7bd5a4SBartosz Golaszewski } 4278c7bd5a4SBartosz Golaszewski 4288c7bd5a4SBartosz Golaszewski static void mtk_star_intr_disable(struct mtk_star_priv *priv) 4298c7bd5a4SBartosz Golaszewski { 4308c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_INT_MASK, ~0); 4318c7bd5a4SBartosz Golaszewski } 4328c7bd5a4SBartosz Golaszewski 4338c7bd5a4SBartosz Golaszewski static unsigned int mtk_star_intr_read(struct mtk_star_priv *priv) 4348c7bd5a4SBartosz Golaszewski { 4358c7bd5a4SBartosz Golaszewski unsigned int val; 4368c7bd5a4SBartosz Golaszewski 4378c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, MTK_STAR_REG_INT_STS, &val); 4388c7bd5a4SBartosz Golaszewski 4398c7bd5a4SBartosz Golaszewski return val; 4408c7bd5a4SBartosz Golaszewski } 4418c7bd5a4SBartosz Golaszewski 4428c7bd5a4SBartosz Golaszewski static unsigned int mtk_star_intr_ack_all(struct mtk_star_priv *priv) 4438c7bd5a4SBartosz Golaszewski { 4448c7bd5a4SBartosz Golaszewski unsigned int val; 4458c7bd5a4SBartosz Golaszewski 4468c7bd5a4SBartosz Golaszewski val = mtk_star_intr_read(priv); 4478c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_INT_STS, val); 4488c7bd5a4SBartosz Golaszewski 4498c7bd5a4SBartosz Golaszewski return val; 4508c7bd5a4SBartosz Golaszewski } 4518c7bd5a4SBartosz Golaszewski 4528c7bd5a4SBartosz Golaszewski static void mtk_star_dma_init(struct mtk_star_priv *priv) 4538c7bd5a4SBartosz Golaszewski { 4548c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc; 4558c7bd5a4SBartosz Golaszewski unsigned int val; 4568c7bd5a4SBartosz Golaszewski int i; 4578c7bd5a4SBartosz Golaszewski 4588c7bd5a4SBartosz Golaszewski priv->descs_base = (struct mtk_star_ring_desc *)priv->ring_base; 4598c7bd5a4SBartosz Golaszewski 4608c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NUM_DESCS_TOTAL; i++) { 4618c7bd5a4SBartosz Golaszewski desc = &priv->descs_base[i]; 4628c7bd5a4SBartosz Golaszewski 4638c7bd5a4SBartosz Golaszewski memset(desc, 0, sizeof(*desc)); 4648c7bd5a4SBartosz Golaszewski desc->status = MTK_STAR_DESC_BIT_COWN; 4658c7bd5a4SBartosz Golaszewski if ((i == MTK_STAR_NUM_TX_DESCS - 1) || 4668c7bd5a4SBartosz Golaszewski (i == MTK_STAR_NUM_DESCS_TOTAL - 1)) 4678c7bd5a4SBartosz Golaszewski desc->status |= MTK_STAR_DESC_BIT_EOR; 4688c7bd5a4SBartosz Golaszewski } 4698c7bd5a4SBartosz Golaszewski 4708c7bd5a4SBartosz Golaszewski mtk_star_ring_init(&priv->tx_ring, priv->descs_base); 4718c7bd5a4SBartosz Golaszewski mtk_star_ring_init(&priv->rx_ring, 4728c7bd5a4SBartosz Golaszewski priv->descs_base + MTK_STAR_NUM_TX_DESCS); 4738c7bd5a4SBartosz Golaszewski 4748c7bd5a4SBartosz Golaszewski /* Set DMA pointers. */ 4758c7bd5a4SBartosz Golaszewski val = (unsigned int)priv->dma_addr; 4768c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_TX_BASE_ADDR, val); 4778c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_TX_DPTR, val); 4788c7bd5a4SBartosz Golaszewski 4798c7bd5a4SBartosz Golaszewski val += sizeof(struct mtk_star_ring_desc) * MTK_STAR_NUM_TX_DESCS; 4808c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_RX_BASE_ADDR, val); 4818c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_RX_DPTR, val); 4828c7bd5a4SBartosz Golaszewski } 4838c7bd5a4SBartosz Golaszewski 4848c7bd5a4SBartosz Golaszewski static void mtk_star_dma_start(struct mtk_star_priv *priv) 4858c7bd5a4SBartosz Golaszewski { 486240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_TX_DMA_CTRL, 4878c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TX_DMA_CTRL_START); 488240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_RX_DMA_CTRL, 4898c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_RX_DMA_CTRL_START); 4908c7bd5a4SBartosz Golaszewski } 4918c7bd5a4SBartosz Golaszewski 4928c7bd5a4SBartosz Golaszewski static void mtk_star_dma_stop(struct mtk_star_priv *priv) 4938c7bd5a4SBartosz Golaszewski { 4948c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_TX_DMA_CTRL, 4958c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TX_DMA_CTRL_STOP); 4968c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_RX_DMA_CTRL, 4978c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_RX_DMA_CTRL_STOP); 4988c7bd5a4SBartosz Golaszewski } 4998c7bd5a4SBartosz Golaszewski 5008c7bd5a4SBartosz Golaszewski static void mtk_star_dma_disable(struct mtk_star_priv *priv) 5018c7bd5a4SBartosz Golaszewski { 5028c7bd5a4SBartosz Golaszewski int i; 5038c7bd5a4SBartosz Golaszewski 5048c7bd5a4SBartosz Golaszewski mtk_star_dma_stop(priv); 5058c7bd5a4SBartosz Golaszewski 5068c7bd5a4SBartosz Golaszewski /* Take back all descriptors. */ 5078c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NUM_DESCS_TOTAL; i++) 5088c7bd5a4SBartosz Golaszewski priv->descs_base[i].status |= MTK_STAR_DESC_BIT_COWN; 5098c7bd5a4SBartosz Golaszewski } 5108c7bd5a4SBartosz Golaszewski 5118c7bd5a4SBartosz Golaszewski static void mtk_star_dma_resume_rx(struct mtk_star_priv *priv) 5128c7bd5a4SBartosz Golaszewski { 513240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_RX_DMA_CTRL, 5148c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_RX_DMA_CTRL_RESUME); 5158c7bd5a4SBartosz Golaszewski } 5168c7bd5a4SBartosz Golaszewski 5178c7bd5a4SBartosz Golaszewski static void mtk_star_dma_resume_tx(struct mtk_star_priv *priv) 5188c7bd5a4SBartosz Golaszewski { 519240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_TX_DMA_CTRL, 5208c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TX_DMA_CTRL_RESUME); 5218c7bd5a4SBartosz Golaszewski } 5228c7bd5a4SBartosz Golaszewski 5238c7bd5a4SBartosz Golaszewski static void mtk_star_set_mac_addr(struct net_device *ndev) 5248c7bd5a4SBartosz Golaszewski { 5258c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 5268c7bd5a4SBartosz Golaszewski u8 *mac_addr = ndev->dev_addr; 5278c7bd5a4SBartosz Golaszewski unsigned int high, low; 5288c7bd5a4SBartosz Golaszewski 5298c7bd5a4SBartosz Golaszewski high = mac_addr[0] << 8 | mac_addr[1] << 0; 5308c7bd5a4SBartosz Golaszewski low = mac_addr[2] << 24 | mac_addr[3] << 16 | 5318c7bd5a4SBartosz Golaszewski mac_addr[4] << 8 | mac_addr[5]; 5328c7bd5a4SBartosz Golaszewski 5338c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_MY_MAC_H, high); 5348c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_MY_MAC_L, low); 5358c7bd5a4SBartosz Golaszewski } 5368c7bd5a4SBartosz Golaszewski 5378c7bd5a4SBartosz Golaszewski static void mtk_star_reset_counters(struct mtk_star_priv *priv) 5388c7bd5a4SBartosz Golaszewski { 5398c7bd5a4SBartosz Golaszewski static const unsigned int counter_regs[] = { 5408c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXOKPKT, 5418c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXOKBYTE, 5428c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXRUNT, 5438c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXLONG, 5448c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXDROP, 5458c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXCRC, 5468c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXARLDROP, 5478c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXVLANDROP, 5488c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXCSERR, 5498c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXPAUSE, 5508c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXOKPKT, 5518c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXOKBYTE, 5528c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXPAUSECOL, 5538c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXRTY, 5548c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXSKIP, 5558c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_ARP, 5568c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_RERR, 5578c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_UNI, 5588c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_MULTI, 5598c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_BROAD, 5608c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_ALIGNERR, 5618c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_UNI, 5628c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_MULTI, 5638c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_BROAD, 5648c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_TIMEOUT, 5658c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_LATECOL, 5668c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_LENGTHERR, 5678c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_TWIST, 5688c7bd5a4SBartosz Golaszewski }; 5698c7bd5a4SBartosz Golaszewski 5708c7bd5a4SBartosz Golaszewski unsigned int i, val; 5718c7bd5a4SBartosz Golaszewski 5728c7bd5a4SBartosz Golaszewski for (i = 0; i < ARRAY_SIZE(counter_regs); i++) 5738c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, counter_regs[i], &val); 5748c7bd5a4SBartosz Golaszewski } 5758c7bd5a4SBartosz Golaszewski 5768c7bd5a4SBartosz Golaszewski static void mtk_star_update_stat(struct mtk_star_priv *priv, 5778c7bd5a4SBartosz Golaszewski unsigned int reg, u64 *stat) 5788c7bd5a4SBartosz Golaszewski { 5798c7bd5a4SBartosz Golaszewski unsigned int val; 5808c7bd5a4SBartosz Golaszewski 5818c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, reg, &val); 5828c7bd5a4SBartosz Golaszewski *stat += val; 5838c7bd5a4SBartosz Golaszewski } 5848c7bd5a4SBartosz Golaszewski 5858c7bd5a4SBartosz Golaszewski /* Try to get as many stats as possible from the internal registers instead 5868c7bd5a4SBartosz Golaszewski * of tracking them ourselves. 5878c7bd5a4SBartosz Golaszewski */ 5888c7bd5a4SBartosz Golaszewski static void mtk_star_update_stats(struct mtk_star_priv *priv) 5898c7bd5a4SBartosz Golaszewski { 5908c7bd5a4SBartosz Golaszewski struct rtnl_link_stats64 *stats = &priv->stats; 5918c7bd5a4SBartosz Golaszewski 5928c7bd5a4SBartosz Golaszewski /* OK packets and bytes. */ 5938c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXOKPKT, &stats->rx_packets); 5948c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TXOKPKT, &stats->tx_packets); 5958c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXOKBYTE, &stats->rx_bytes); 5968c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TXOKBYTE, &stats->tx_bytes); 5978c7bd5a4SBartosz Golaszewski 5988c7bd5a4SBartosz Golaszewski /* RX & TX multicast. */ 5998c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_MULTI, &stats->multicast); 6008c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TX_MULTI, &stats->multicast); 6018c7bd5a4SBartosz Golaszewski 6028c7bd5a4SBartosz Golaszewski /* Collisions. */ 6038c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TXPAUSECOL, 6048c7bd5a4SBartosz Golaszewski &stats->collisions); 6058c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TX_LATECOL, 6068c7bd5a4SBartosz Golaszewski &stats->collisions); 6078c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXRUNT, &stats->collisions); 6088c7bd5a4SBartosz Golaszewski 6098c7bd5a4SBartosz Golaszewski /* RX Errors. */ 6108c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_LENGTHERR, 6118c7bd5a4SBartosz Golaszewski &stats->rx_length_errors); 6128c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXLONG, 6138c7bd5a4SBartosz Golaszewski &stats->rx_over_errors); 6148c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXCRC, &stats->rx_crc_errors); 6158c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_ALIGNERR, 6168c7bd5a4SBartosz Golaszewski &stats->rx_frame_errors); 6178c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXDROP, 6188c7bd5a4SBartosz Golaszewski &stats->rx_fifo_errors); 6198c7bd5a4SBartosz Golaszewski /* Sum of the general RX error counter + all of the above. */ 6208c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_RERR, &stats->rx_errors); 6218c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_length_errors; 6228c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_over_errors; 6238c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_crc_errors; 6248c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_frame_errors; 6258c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_fifo_errors; 6268c7bd5a4SBartosz Golaszewski } 6278c7bd5a4SBartosz Golaszewski 6288c7bd5a4SBartosz Golaszewski static struct sk_buff *mtk_star_alloc_skb(struct net_device *ndev) 6298c7bd5a4SBartosz Golaszewski { 6308c7bd5a4SBartosz Golaszewski uintptr_t tail, offset; 6318c7bd5a4SBartosz Golaszewski struct sk_buff *skb; 6328c7bd5a4SBartosz Golaszewski 6338c7bd5a4SBartosz Golaszewski skb = dev_alloc_skb(MTK_STAR_MAX_FRAME_SIZE); 6348c7bd5a4SBartosz Golaszewski if (!skb) 6358c7bd5a4SBartosz Golaszewski return NULL; 6368c7bd5a4SBartosz Golaszewski 6378c7bd5a4SBartosz Golaszewski /* Align to 16 bytes. */ 6388c7bd5a4SBartosz Golaszewski tail = (uintptr_t)skb_tail_pointer(skb); 6398c7bd5a4SBartosz Golaszewski if (tail & (MTK_STAR_SKB_ALIGNMENT - 1)) { 6408c7bd5a4SBartosz Golaszewski offset = tail & (MTK_STAR_SKB_ALIGNMENT - 1); 6418c7bd5a4SBartosz Golaszewski skb_reserve(skb, MTK_STAR_SKB_ALIGNMENT - offset); 6428c7bd5a4SBartosz Golaszewski } 6438c7bd5a4SBartosz Golaszewski 6448c7bd5a4SBartosz Golaszewski /* Ensure 16-byte alignment of the skb pointer: eth_type_trans() will 6458c7bd5a4SBartosz Golaszewski * extract the Ethernet header (14 bytes) so we need two more bytes. 6468c7bd5a4SBartosz Golaszewski */ 6478c7bd5a4SBartosz Golaszewski skb_reserve(skb, MTK_STAR_IP_ALIGN); 6488c7bd5a4SBartosz Golaszewski 6498c7bd5a4SBartosz Golaszewski return skb; 6508c7bd5a4SBartosz Golaszewski } 6518c7bd5a4SBartosz Golaszewski 6528c7bd5a4SBartosz Golaszewski static int mtk_star_prepare_rx_skbs(struct net_device *ndev) 6538c7bd5a4SBartosz Golaszewski { 6548c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 6558c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->rx_ring; 6568c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 6578c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc; 6588c7bd5a4SBartosz Golaszewski struct sk_buff *skb; 6598c7bd5a4SBartosz Golaszewski dma_addr_t dma_addr; 6608c7bd5a4SBartosz Golaszewski int i; 6618c7bd5a4SBartosz Golaszewski 6628c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NUM_RX_DESCS; i++) { 6638c7bd5a4SBartosz Golaszewski skb = mtk_star_alloc_skb(ndev); 6648c7bd5a4SBartosz Golaszewski if (!skb) 6658c7bd5a4SBartosz Golaszewski return -ENOMEM; 6668c7bd5a4SBartosz Golaszewski 6678c7bd5a4SBartosz Golaszewski dma_addr = mtk_star_dma_map_rx(priv, skb); 6688c7bd5a4SBartosz Golaszewski if (dma_mapping_error(dev, dma_addr)) { 6698c7bd5a4SBartosz Golaszewski dev_kfree_skb(skb); 6708c7bd5a4SBartosz Golaszewski return -ENOMEM; 6718c7bd5a4SBartosz Golaszewski } 6728c7bd5a4SBartosz Golaszewski 6738c7bd5a4SBartosz Golaszewski desc = &ring->descs[i]; 6748c7bd5a4SBartosz Golaszewski desc->data_ptr = dma_addr; 6758c7bd5a4SBartosz Golaszewski desc->status |= skb_tailroom(skb) & MTK_STAR_DESC_MSK_LEN; 6768c7bd5a4SBartosz Golaszewski desc->status &= ~MTK_STAR_DESC_BIT_COWN; 6778c7bd5a4SBartosz Golaszewski ring->skbs[i] = skb; 6788c7bd5a4SBartosz Golaszewski ring->dma_addrs[i] = dma_addr; 6798c7bd5a4SBartosz Golaszewski } 6808c7bd5a4SBartosz Golaszewski 6818c7bd5a4SBartosz Golaszewski return 0; 6828c7bd5a4SBartosz Golaszewski } 6838c7bd5a4SBartosz Golaszewski 6848c7bd5a4SBartosz Golaszewski static void 6858c7bd5a4SBartosz Golaszewski mtk_star_ring_free_skbs(struct mtk_star_priv *priv, struct mtk_star_ring *ring, 6868c7bd5a4SBartosz Golaszewski void (*unmap_func)(struct mtk_star_priv *, 6878c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *)) 6888c7bd5a4SBartosz Golaszewski { 6898c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 6908c7bd5a4SBartosz Golaszewski int i; 6918c7bd5a4SBartosz Golaszewski 6928c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_RING_NUM_DESCS; i++) { 6938c7bd5a4SBartosz Golaszewski if (!ring->dma_addrs[i]) 6948c7bd5a4SBartosz Golaszewski continue; 6958c7bd5a4SBartosz Golaszewski 6968c7bd5a4SBartosz Golaszewski desc_data.dma_addr = ring->dma_addrs[i]; 6978c7bd5a4SBartosz Golaszewski desc_data.skb = ring->skbs[i]; 6988c7bd5a4SBartosz Golaszewski 6998c7bd5a4SBartosz Golaszewski unmap_func(priv, &desc_data); 7008c7bd5a4SBartosz Golaszewski dev_kfree_skb(desc_data.skb); 7018c7bd5a4SBartosz Golaszewski } 7028c7bd5a4SBartosz Golaszewski } 7038c7bd5a4SBartosz Golaszewski 7048c7bd5a4SBartosz Golaszewski static void mtk_star_free_rx_skbs(struct mtk_star_priv *priv) 7058c7bd5a4SBartosz Golaszewski { 7068c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->rx_ring; 7078c7bd5a4SBartosz Golaszewski 7088c7bd5a4SBartosz Golaszewski mtk_star_ring_free_skbs(priv, ring, mtk_star_dma_unmap_rx); 7098c7bd5a4SBartosz Golaszewski } 7108c7bd5a4SBartosz Golaszewski 7118c7bd5a4SBartosz Golaszewski static void mtk_star_free_tx_skbs(struct mtk_star_priv *priv) 7128c7bd5a4SBartosz Golaszewski { 7138c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 7148c7bd5a4SBartosz Golaszewski 7158c7bd5a4SBartosz Golaszewski mtk_star_ring_free_skbs(priv, ring, mtk_star_dma_unmap_tx); 7168c7bd5a4SBartosz Golaszewski } 7178c7bd5a4SBartosz Golaszewski 718adaff6d9SBartosz Golaszewski /* All processing for TX and RX happens in the napi poll callback. 719adaff6d9SBartosz Golaszewski * 720adaff6d9SBartosz Golaszewski * FIXME: The interrupt handling should be more fine-grained with each 721adaff6d9SBartosz Golaszewski * interrupt enabled/disabled independently when needed. Unfortunatly this 722adaff6d9SBartosz Golaszewski * turned out to impact the driver's stability and until we have something 723adaff6d9SBartosz Golaszewski * working properly, we're disabling all interrupts during TX & RX processing 724adaff6d9SBartosz Golaszewski * or when resetting the counter registers. 725adaff6d9SBartosz Golaszewski */ 7268c7bd5a4SBartosz Golaszewski static irqreturn_t mtk_star_handle_irq(int irq, void *data) 7278c7bd5a4SBartosz Golaszewski { 7288c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 7298c7bd5a4SBartosz Golaszewski struct net_device *ndev; 7308c7bd5a4SBartosz Golaszewski 7318c7bd5a4SBartosz Golaszewski ndev = data; 7328c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 7338c7bd5a4SBartosz Golaszewski 7348c7bd5a4SBartosz Golaszewski if (netif_running(ndev)) { 735adaff6d9SBartosz Golaszewski mtk_star_intr_disable(priv); 7368c7bd5a4SBartosz Golaszewski napi_schedule(&priv->napi); 7378c7bd5a4SBartosz Golaszewski } 7388c7bd5a4SBartosz Golaszewski 7398c7bd5a4SBartosz Golaszewski return IRQ_HANDLED; 7408c7bd5a4SBartosz Golaszewski } 7418c7bd5a4SBartosz Golaszewski 7428c7bd5a4SBartosz Golaszewski /* Wait for the completion of any previous command - CMD_START bit must be 7438c7bd5a4SBartosz Golaszewski * cleared by hardware. 7448c7bd5a4SBartosz Golaszewski */ 7458c7bd5a4SBartosz Golaszewski static int mtk_star_hash_wait_cmd_start(struct mtk_star_priv *priv) 7468c7bd5a4SBartosz Golaszewski { 7478c7bd5a4SBartosz Golaszewski unsigned int val; 7488c7bd5a4SBartosz Golaszewski 7498c7bd5a4SBartosz Golaszewski return regmap_read_poll_timeout_atomic(priv->regs, 7508c7bd5a4SBartosz Golaszewski MTK_STAR_REG_HASH_CTRL, val, 7518c7bd5a4SBartosz Golaszewski !(val & MTK_STAR_BIT_HASH_CTRL_CMD_START), 7528c7bd5a4SBartosz Golaszewski 10, MTK_STAR_WAIT_TIMEOUT); 7538c7bd5a4SBartosz Golaszewski } 7548c7bd5a4SBartosz Golaszewski 7558c7bd5a4SBartosz Golaszewski static int mtk_star_hash_wait_ok(struct mtk_star_priv *priv) 7568c7bd5a4SBartosz Golaszewski { 7578c7bd5a4SBartosz Golaszewski unsigned int val; 7588c7bd5a4SBartosz Golaszewski int ret; 7598c7bd5a4SBartosz Golaszewski 7608c7bd5a4SBartosz Golaszewski /* Wait for BIST_DONE bit. */ 7618c7bd5a4SBartosz Golaszewski ret = regmap_read_poll_timeout_atomic(priv->regs, 7628c7bd5a4SBartosz Golaszewski MTK_STAR_REG_HASH_CTRL, val, 7638c7bd5a4SBartosz Golaszewski val & MTK_STAR_BIT_HASH_CTRL_BIST_DONE, 7648c7bd5a4SBartosz Golaszewski 10, MTK_STAR_WAIT_TIMEOUT); 7658c7bd5a4SBartosz Golaszewski if (ret) 7668c7bd5a4SBartosz Golaszewski return ret; 7678c7bd5a4SBartosz Golaszewski 7688c7bd5a4SBartosz Golaszewski /* Check the BIST_OK bit. */ 769240f1ae4SBartosz Golaszewski if (!regmap_test_bits(priv->regs, MTK_STAR_REG_HASH_CTRL, 770240f1ae4SBartosz Golaszewski MTK_STAR_BIT_HASH_CTRL_BIST_OK)) 7718c7bd5a4SBartosz Golaszewski return -EIO; 7728c7bd5a4SBartosz Golaszewski 7738c7bd5a4SBartosz Golaszewski return 0; 7748c7bd5a4SBartosz Golaszewski } 7758c7bd5a4SBartosz Golaszewski 7768c7bd5a4SBartosz Golaszewski static int mtk_star_set_hashbit(struct mtk_star_priv *priv, 7778c7bd5a4SBartosz Golaszewski unsigned int hash_addr) 7788c7bd5a4SBartosz Golaszewski { 7798c7bd5a4SBartosz Golaszewski unsigned int val; 7808c7bd5a4SBartosz Golaszewski int ret; 7818c7bd5a4SBartosz Golaszewski 7828c7bd5a4SBartosz Golaszewski ret = mtk_star_hash_wait_cmd_start(priv); 7838c7bd5a4SBartosz Golaszewski if (ret) 7848c7bd5a4SBartosz Golaszewski return ret; 7858c7bd5a4SBartosz Golaszewski 7868c7bd5a4SBartosz Golaszewski val = hash_addr & MTK_STAR_MSK_HASH_CTRL_HASH_BIT_ADDR; 7878c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_ACC_CMD; 7888c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_CMD_START; 7898c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_BIST_EN; 7908c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_HASH_BIT_DATA; 7918c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_HASH_CTRL, val); 7928c7bd5a4SBartosz Golaszewski 7938c7bd5a4SBartosz Golaszewski return mtk_star_hash_wait_ok(priv); 7948c7bd5a4SBartosz Golaszewski } 7958c7bd5a4SBartosz Golaszewski 7968c7bd5a4SBartosz Golaszewski static int mtk_star_reset_hash_table(struct mtk_star_priv *priv) 7978c7bd5a4SBartosz Golaszewski { 7988c7bd5a4SBartosz Golaszewski int ret; 7998c7bd5a4SBartosz Golaszewski 8008c7bd5a4SBartosz Golaszewski ret = mtk_star_hash_wait_cmd_start(priv); 8018c7bd5a4SBartosz Golaszewski if (ret) 8028c7bd5a4SBartosz Golaszewski return ret; 8038c7bd5a4SBartosz Golaszewski 804240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_HASH_CTRL, 8058c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_HASH_CTRL_BIST_EN); 806240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_TEST1, 8078c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TEST1_RST_HASH_MBIST); 8088c7bd5a4SBartosz Golaszewski 8098c7bd5a4SBartosz Golaszewski return mtk_star_hash_wait_ok(priv); 8108c7bd5a4SBartosz Golaszewski } 8118c7bd5a4SBartosz Golaszewski 8128c7bd5a4SBartosz Golaszewski static void mtk_star_phy_config(struct mtk_star_priv *priv) 8138c7bd5a4SBartosz Golaszewski { 8148c7bd5a4SBartosz Golaszewski unsigned int val; 8158c7bd5a4SBartosz Golaszewski 8168c7bd5a4SBartosz Golaszewski if (priv->speed == SPEED_1000) 8178c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_1000M; 8188c7bd5a4SBartosz Golaszewski else if (priv->speed == SPEED_100) 8198c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_100M; 8208c7bd5a4SBartosz Golaszewski else 8218c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_10M; 8228c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_PHY_CTRL1_FORCE_SPD; 8238c7bd5a4SBartosz Golaszewski 8248c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_AN_EN; 8258c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_RX; 8268c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_TX; 8278c7bd5a4SBartosz Golaszewski /* Only full-duplex supported for now. */ 8288c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_FORCE_DPX; 8298c7bd5a4SBartosz Golaszewski 8308c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL1, val); 8318c7bd5a4SBartosz Golaszewski 8328c7bd5a4SBartosz Golaszewski if (priv->pause) { 8338c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_FC_CFG_SEND_PAUSE_TH_2K; 8348c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_FC_CFG_SEND_PAUSE_TH; 8358c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_FC_CFG_UC_PAUSE_DIR; 8368c7bd5a4SBartosz Golaszewski } else { 8378c7bd5a4SBartosz Golaszewski val = 0; 8388c7bd5a4SBartosz Golaszewski } 8398c7bd5a4SBartosz Golaszewski 8408c7bd5a4SBartosz Golaszewski regmap_update_bits(priv->regs, MTK_STAR_REG_FC_CFG, 8418c7bd5a4SBartosz Golaszewski MTK_STAR_MSK_FC_CFG_SEND_PAUSE_TH | 8428c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_FC_CFG_UC_PAUSE_DIR, val); 8438c7bd5a4SBartosz Golaszewski 8448c7bd5a4SBartosz Golaszewski if (priv->pause) { 8458c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_EXT_CFG_SND_PAUSE_RLS_1K; 8468c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_EXT_CFG_SND_PAUSE_RLS; 8478c7bd5a4SBartosz Golaszewski } else { 8488c7bd5a4SBartosz Golaszewski val = 0; 8498c7bd5a4SBartosz Golaszewski } 8508c7bd5a4SBartosz Golaszewski 8518c7bd5a4SBartosz Golaszewski regmap_update_bits(priv->regs, MTK_STAR_REG_EXT_CFG, 8528c7bd5a4SBartosz Golaszewski MTK_STAR_MSK_EXT_CFG_SND_PAUSE_RLS, val); 8538c7bd5a4SBartosz Golaszewski } 8548c7bd5a4SBartosz Golaszewski 8558c7bd5a4SBartosz Golaszewski static void mtk_star_adjust_link(struct net_device *ndev) 8568c7bd5a4SBartosz Golaszewski { 8578c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 8588c7bd5a4SBartosz Golaszewski struct phy_device *phydev = priv->phydev; 8598c7bd5a4SBartosz Golaszewski bool new_state = false; 8608c7bd5a4SBartosz Golaszewski 8618c7bd5a4SBartosz Golaszewski if (phydev->link) { 8628c7bd5a4SBartosz Golaszewski if (!priv->link) { 8638c7bd5a4SBartosz Golaszewski priv->link = phydev->link; 8648c7bd5a4SBartosz Golaszewski new_state = true; 8658c7bd5a4SBartosz Golaszewski } 8668c7bd5a4SBartosz Golaszewski 8678c7bd5a4SBartosz Golaszewski if (priv->speed != phydev->speed) { 8688c7bd5a4SBartosz Golaszewski priv->speed = phydev->speed; 8698c7bd5a4SBartosz Golaszewski new_state = true; 8708c7bd5a4SBartosz Golaszewski } 8718c7bd5a4SBartosz Golaszewski 8728c7bd5a4SBartosz Golaszewski if (priv->pause != phydev->pause) { 8738c7bd5a4SBartosz Golaszewski priv->pause = phydev->pause; 8748c7bd5a4SBartosz Golaszewski new_state = true; 8758c7bd5a4SBartosz Golaszewski } 8768c7bd5a4SBartosz Golaszewski } else { 8778c7bd5a4SBartosz Golaszewski if (priv->link) { 8788c7bd5a4SBartosz Golaszewski priv->link = phydev->link; 8798c7bd5a4SBartosz Golaszewski new_state = true; 8808c7bd5a4SBartosz Golaszewski } 8818c7bd5a4SBartosz Golaszewski } 8828c7bd5a4SBartosz Golaszewski 8838c7bd5a4SBartosz Golaszewski if (new_state) { 8848c7bd5a4SBartosz Golaszewski if (phydev->link) 8858c7bd5a4SBartosz Golaszewski mtk_star_phy_config(priv); 8868c7bd5a4SBartosz Golaszewski 8878c7bd5a4SBartosz Golaszewski phy_print_status(ndev->phydev); 8888c7bd5a4SBartosz Golaszewski } 8898c7bd5a4SBartosz Golaszewski } 8908c7bd5a4SBartosz Golaszewski 8918c7bd5a4SBartosz Golaszewski static void mtk_star_init_config(struct mtk_star_priv *priv) 8928c7bd5a4SBartosz Golaszewski { 8938c7bd5a4SBartosz Golaszewski unsigned int val; 8948c7bd5a4SBartosz Golaszewski 8958c7bd5a4SBartosz Golaszewski val = (MTK_STAR_BIT_MII_PAD_OUT_ENABLE | 8968c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_EXT_MDC_MODE | 8978c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_SWC_MII_MODE); 8988c7bd5a4SBartosz Golaszewski 8998c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_SYS_CONF, val); 9008c7bd5a4SBartosz Golaszewski regmap_update_bits(priv->regs, MTK_STAR_REG_MAC_CLK_CONF, 9018c7bd5a4SBartosz Golaszewski MTK_STAR_MSK_MAC_CLK_CONF, 9028c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_CLK_DIV_10); 9038c7bd5a4SBartosz Golaszewski } 9048c7bd5a4SBartosz Golaszewski 9058c7bd5a4SBartosz Golaszewski static void mtk_star_set_mode_rmii(struct mtk_star_priv *priv) 9068c7bd5a4SBartosz Golaszewski { 9078c7bd5a4SBartosz Golaszewski regmap_update_bits(priv->pericfg, MTK_PERICFG_REG_NIC_CFG_CON, 9088c7bd5a4SBartosz Golaszewski MTK_PERICFG_MSK_NIC_CFG_CON_CFG_MII, 9098c7bd5a4SBartosz Golaszewski MTK_PERICFG_BIT_NIC_CFG_CON_RMII); 9108c7bd5a4SBartosz Golaszewski } 9118c7bd5a4SBartosz Golaszewski 9128c7bd5a4SBartosz Golaszewski static int mtk_star_enable(struct net_device *ndev) 9138c7bd5a4SBartosz Golaszewski { 9148c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 9158c7bd5a4SBartosz Golaszewski unsigned int val; 9168c7bd5a4SBartosz Golaszewski int ret; 9178c7bd5a4SBartosz Golaszewski 9188c7bd5a4SBartosz Golaszewski mtk_star_nic_disable_pd(priv); 9198c7bd5a4SBartosz Golaszewski mtk_star_intr_disable(priv); 9208c7bd5a4SBartosz Golaszewski mtk_star_dma_stop(priv); 9218c7bd5a4SBartosz Golaszewski 9228c7bd5a4SBartosz Golaszewski mtk_star_set_mac_addr(ndev); 9238c7bd5a4SBartosz Golaszewski 9248c7bd5a4SBartosz Golaszewski /* Configure the MAC */ 9258c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_MAC_CFG_IPG_96BIT; 9268c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_MAC_CFG_IPG; 9278c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_MAC_CFG_MAXLEN_1522; 9288c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_MAC_CFG_AUTO_PAD; 9298c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_MAC_CFG_CRC_STRIP; 9308c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_MAC_CFG, val); 9318c7bd5a4SBartosz Golaszewski 9328c7bd5a4SBartosz Golaszewski /* Enable Hash Table BIST and reset it */ 9338c7bd5a4SBartosz Golaszewski ret = mtk_star_reset_hash_table(priv); 9348c7bd5a4SBartosz Golaszewski if (ret) 9358c7bd5a4SBartosz Golaszewski return ret; 9368c7bd5a4SBartosz Golaszewski 9378c7bd5a4SBartosz Golaszewski /* Setup the hashing algorithm */ 938240f1ae4SBartosz Golaszewski regmap_clear_bits(priv->regs, MTK_STAR_REG_ARL_CFG, 9398c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_ARL_CFG_HASH_ALG | 940240f1ae4SBartosz Golaszewski MTK_STAR_BIT_ARL_CFG_MISC_MODE); 9418c7bd5a4SBartosz Golaszewski 9428c7bd5a4SBartosz Golaszewski /* Don't strip VLAN tags */ 943240f1ae4SBartosz Golaszewski regmap_clear_bits(priv->regs, MTK_STAR_REG_MAC_CFG, 944240f1ae4SBartosz Golaszewski MTK_STAR_BIT_MAC_CFG_VLAN_STRIP); 9458c7bd5a4SBartosz Golaszewski 9468c7bd5a4SBartosz Golaszewski /* Setup DMA */ 9478c7bd5a4SBartosz Golaszewski mtk_star_dma_init(priv); 9488c7bd5a4SBartosz Golaszewski 9498c7bd5a4SBartosz Golaszewski ret = mtk_star_prepare_rx_skbs(ndev); 9508c7bd5a4SBartosz Golaszewski if (ret) 9518c7bd5a4SBartosz Golaszewski goto err_out; 9528c7bd5a4SBartosz Golaszewski 9538c7bd5a4SBartosz Golaszewski /* Request the interrupt */ 9548c7bd5a4SBartosz Golaszewski ret = request_irq(ndev->irq, mtk_star_handle_irq, 9558c7bd5a4SBartosz Golaszewski IRQF_TRIGGER_FALLING, ndev->name, ndev); 9568c7bd5a4SBartosz Golaszewski if (ret) 9578c7bd5a4SBartosz Golaszewski goto err_free_skbs; 9588c7bd5a4SBartosz Golaszewski 9598c7bd5a4SBartosz Golaszewski napi_enable(&priv->napi); 9608c7bd5a4SBartosz Golaszewski 9618c7bd5a4SBartosz Golaszewski mtk_star_intr_ack_all(priv); 9628c7bd5a4SBartosz Golaszewski mtk_star_intr_enable(priv); 9638c7bd5a4SBartosz Golaszewski 9648c7bd5a4SBartosz Golaszewski /* Connect to and start PHY */ 9658c7bd5a4SBartosz Golaszewski priv->phydev = of_phy_connect(ndev, priv->phy_node, 9668c7bd5a4SBartosz Golaszewski mtk_star_adjust_link, 0, priv->phy_intf); 9678c7bd5a4SBartosz Golaszewski if (!priv->phydev) { 9688c7bd5a4SBartosz Golaszewski netdev_err(ndev, "failed to connect to PHY\n"); 969baee1991SZhang Changzhong ret = -ENODEV; 9708c7bd5a4SBartosz Golaszewski goto err_free_irq; 9718c7bd5a4SBartosz Golaszewski } 9728c7bd5a4SBartosz Golaszewski 9738c7bd5a4SBartosz Golaszewski mtk_star_dma_start(priv); 9748c7bd5a4SBartosz Golaszewski phy_start(priv->phydev); 9758c7bd5a4SBartosz Golaszewski netif_start_queue(ndev); 9768c7bd5a4SBartosz Golaszewski 9778c7bd5a4SBartosz Golaszewski return 0; 9788c7bd5a4SBartosz Golaszewski 9798c7bd5a4SBartosz Golaszewski err_free_irq: 9808c7bd5a4SBartosz Golaszewski free_irq(ndev->irq, ndev); 9818c7bd5a4SBartosz Golaszewski err_free_skbs: 9828c7bd5a4SBartosz Golaszewski mtk_star_free_rx_skbs(priv); 9838c7bd5a4SBartosz Golaszewski err_out: 9848c7bd5a4SBartosz Golaszewski return ret; 9858c7bd5a4SBartosz Golaszewski } 9868c7bd5a4SBartosz Golaszewski 9878c7bd5a4SBartosz Golaszewski static void mtk_star_disable(struct net_device *ndev) 9888c7bd5a4SBartosz Golaszewski { 9898c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 9908c7bd5a4SBartosz Golaszewski 9918c7bd5a4SBartosz Golaszewski netif_stop_queue(ndev); 9928c7bd5a4SBartosz Golaszewski napi_disable(&priv->napi); 9938c7bd5a4SBartosz Golaszewski mtk_star_intr_disable(priv); 9948c7bd5a4SBartosz Golaszewski mtk_star_dma_disable(priv); 9958c7bd5a4SBartosz Golaszewski mtk_star_intr_ack_all(priv); 9968c7bd5a4SBartosz Golaszewski phy_stop(priv->phydev); 9978c7bd5a4SBartosz Golaszewski phy_disconnect(priv->phydev); 9988c7bd5a4SBartosz Golaszewski free_irq(ndev->irq, ndev); 9998c7bd5a4SBartosz Golaszewski mtk_star_free_rx_skbs(priv); 10008c7bd5a4SBartosz Golaszewski mtk_star_free_tx_skbs(priv); 10018c7bd5a4SBartosz Golaszewski } 10028c7bd5a4SBartosz Golaszewski 10038c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_open(struct net_device *ndev) 10048c7bd5a4SBartosz Golaszewski { 10058c7bd5a4SBartosz Golaszewski return mtk_star_enable(ndev); 10068c7bd5a4SBartosz Golaszewski } 10078c7bd5a4SBartosz Golaszewski 10088c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_stop(struct net_device *ndev) 10098c7bd5a4SBartosz Golaszewski { 10108c7bd5a4SBartosz Golaszewski mtk_star_disable(ndev); 10118c7bd5a4SBartosz Golaszewski 10128c7bd5a4SBartosz Golaszewski return 0; 10138c7bd5a4SBartosz Golaszewski } 10148c7bd5a4SBartosz Golaszewski 10158c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_ioctl(struct net_device *ndev, 10168c7bd5a4SBartosz Golaszewski struct ifreq *req, int cmd) 10178c7bd5a4SBartosz Golaszewski { 10188c7bd5a4SBartosz Golaszewski if (!netif_running(ndev)) 10198c7bd5a4SBartosz Golaszewski return -EINVAL; 10208c7bd5a4SBartosz Golaszewski 10218c7bd5a4SBartosz Golaszewski return phy_mii_ioctl(ndev->phydev, req, cmd); 10228c7bd5a4SBartosz Golaszewski } 10238c7bd5a4SBartosz Golaszewski 10248c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_start_xmit(struct sk_buff *skb, 10258c7bd5a4SBartosz Golaszewski struct net_device *ndev) 10268c7bd5a4SBartosz Golaszewski { 10278c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 10288c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 10298c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 10308c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 10318c7bd5a4SBartosz Golaszewski 10328c7bd5a4SBartosz Golaszewski desc_data.dma_addr = mtk_star_dma_map_tx(priv, skb); 10338c7bd5a4SBartosz Golaszewski if (dma_mapping_error(dev, desc_data.dma_addr)) 10348c7bd5a4SBartosz Golaszewski goto err_drop_packet; 10358c7bd5a4SBartosz Golaszewski 10368c7bd5a4SBartosz Golaszewski desc_data.skb = skb; 10378c7bd5a4SBartosz Golaszewski desc_data.len = skb->len; 10388c7bd5a4SBartosz Golaszewski 10398c7bd5a4SBartosz Golaszewski spin_lock_bh(&priv->lock); 10408c7bd5a4SBartosz Golaszewski 10418c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_tx(ring, &desc_data); 10428c7bd5a4SBartosz Golaszewski 10438c7bd5a4SBartosz Golaszewski netdev_sent_queue(ndev, skb->len); 10448c7bd5a4SBartosz Golaszewski 10458c7bd5a4SBartosz Golaszewski if (mtk_star_ring_full(ring)) 10468c7bd5a4SBartosz Golaszewski netif_stop_queue(ndev); 10478c7bd5a4SBartosz Golaszewski 10488c7bd5a4SBartosz Golaszewski spin_unlock_bh(&priv->lock); 10498c7bd5a4SBartosz Golaszewski 10508c7bd5a4SBartosz Golaszewski mtk_star_dma_resume_tx(priv); 10518c7bd5a4SBartosz Golaszewski 10528c7bd5a4SBartosz Golaszewski return NETDEV_TX_OK; 10538c7bd5a4SBartosz Golaszewski 10548c7bd5a4SBartosz Golaszewski err_drop_packet: 10558c7bd5a4SBartosz Golaszewski dev_kfree_skb(skb); 10568c7bd5a4SBartosz Golaszewski ndev->stats.tx_dropped++; 1057e8aa6d52SVincent Stehlé return NETDEV_TX_OK; 10588c7bd5a4SBartosz Golaszewski } 10598c7bd5a4SBartosz Golaszewski 10608c7bd5a4SBartosz Golaszewski /* Returns the number of bytes sent or a negative number on the first 10618c7bd5a4SBartosz Golaszewski * descriptor owned by DMA. 10628c7bd5a4SBartosz Golaszewski */ 10638c7bd5a4SBartosz Golaszewski static int mtk_star_tx_complete_one(struct mtk_star_priv *priv) 10648c7bd5a4SBartosz Golaszewski { 10658c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 10668c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 10678c7bd5a4SBartosz Golaszewski int ret; 10688c7bd5a4SBartosz Golaszewski 10698c7bd5a4SBartosz Golaszewski ret = mtk_star_ring_pop_tail(ring, &desc_data); 10708c7bd5a4SBartosz Golaszewski if (ret) 10718c7bd5a4SBartosz Golaszewski return ret; 10728c7bd5a4SBartosz Golaszewski 10738c7bd5a4SBartosz Golaszewski mtk_star_dma_unmap_tx(priv, &desc_data); 10748c7bd5a4SBartosz Golaszewski ret = desc_data.skb->len; 10758c7bd5a4SBartosz Golaszewski dev_kfree_skb_irq(desc_data.skb); 10768c7bd5a4SBartosz Golaszewski 10778c7bd5a4SBartosz Golaszewski return ret; 10788c7bd5a4SBartosz Golaszewski } 10798c7bd5a4SBartosz Golaszewski 10808c7bd5a4SBartosz Golaszewski static void mtk_star_tx_complete_all(struct mtk_star_priv *priv) 10818c7bd5a4SBartosz Golaszewski { 10828c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 10838c7bd5a4SBartosz Golaszewski struct net_device *ndev = priv->ndev; 10848c7bd5a4SBartosz Golaszewski int ret, pkts_compl, bytes_compl; 10858c7bd5a4SBartosz Golaszewski bool wake = false; 10868c7bd5a4SBartosz Golaszewski 10878c7bd5a4SBartosz Golaszewski spin_lock(&priv->lock); 10888c7bd5a4SBartosz Golaszewski 10898c7bd5a4SBartosz Golaszewski for (pkts_compl = 0, bytes_compl = 0;; 10908c7bd5a4SBartosz Golaszewski pkts_compl++, bytes_compl += ret, wake = true) { 10918c7bd5a4SBartosz Golaszewski if (!mtk_star_ring_descs_available(ring)) 10928c7bd5a4SBartosz Golaszewski break; 10938c7bd5a4SBartosz Golaszewski 10948c7bd5a4SBartosz Golaszewski ret = mtk_star_tx_complete_one(priv); 10958c7bd5a4SBartosz Golaszewski if (ret < 0) 10968c7bd5a4SBartosz Golaszewski break; 10978c7bd5a4SBartosz Golaszewski } 10988c7bd5a4SBartosz Golaszewski 10998c7bd5a4SBartosz Golaszewski netdev_completed_queue(ndev, pkts_compl, bytes_compl); 11008c7bd5a4SBartosz Golaszewski 11018c7bd5a4SBartosz Golaszewski if (wake && netif_queue_stopped(ndev)) 11028c7bd5a4SBartosz Golaszewski netif_wake_queue(ndev); 11038c7bd5a4SBartosz Golaszewski 11048c7bd5a4SBartosz Golaszewski spin_unlock(&priv->lock); 11058c7bd5a4SBartosz Golaszewski } 11068c7bd5a4SBartosz Golaszewski 11078c7bd5a4SBartosz Golaszewski static void mtk_star_netdev_get_stats64(struct net_device *ndev, 11088c7bd5a4SBartosz Golaszewski struct rtnl_link_stats64 *stats) 11098c7bd5a4SBartosz Golaszewski { 11108c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 11118c7bd5a4SBartosz Golaszewski 11128c7bd5a4SBartosz Golaszewski mtk_star_update_stats(priv); 11138c7bd5a4SBartosz Golaszewski 11148c7bd5a4SBartosz Golaszewski memcpy(stats, &priv->stats, sizeof(*stats)); 11158c7bd5a4SBartosz Golaszewski } 11168c7bd5a4SBartosz Golaszewski 11178c7bd5a4SBartosz Golaszewski static void mtk_star_set_rx_mode(struct net_device *ndev) 11188c7bd5a4SBartosz Golaszewski { 11198c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 11208c7bd5a4SBartosz Golaszewski struct netdev_hw_addr *hw_addr; 11218c7bd5a4SBartosz Golaszewski unsigned int hash_addr, i; 11228c7bd5a4SBartosz Golaszewski int ret; 11238c7bd5a4SBartosz Golaszewski 11248c7bd5a4SBartosz Golaszewski if (ndev->flags & IFF_PROMISC) { 1125240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_ARL_CFG, 11268c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_ARL_CFG_MISC_MODE); 11278c7bd5a4SBartosz Golaszewski } else if (netdev_mc_count(ndev) > MTK_STAR_HASHTABLE_MC_LIMIT || 11288c7bd5a4SBartosz Golaszewski ndev->flags & IFF_ALLMULTI) { 11298c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_HASHTABLE_SIZE_MAX; i++) { 11308c7bd5a4SBartosz Golaszewski ret = mtk_star_set_hashbit(priv, i); 11318c7bd5a4SBartosz Golaszewski if (ret) 11328c7bd5a4SBartosz Golaszewski goto hash_fail; 11338c7bd5a4SBartosz Golaszewski } 11348c7bd5a4SBartosz Golaszewski } else { 11358c7bd5a4SBartosz Golaszewski /* Clear previous settings. */ 11368c7bd5a4SBartosz Golaszewski ret = mtk_star_reset_hash_table(priv); 11378c7bd5a4SBartosz Golaszewski if (ret) 11388c7bd5a4SBartosz Golaszewski goto hash_fail; 11398c7bd5a4SBartosz Golaszewski 11408c7bd5a4SBartosz Golaszewski netdev_for_each_mc_addr(hw_addr, ndev) { 11418c7bd5a4SBartosz Golaszewski hash_addr = (hw_addr->addr[0] & 0x01) << 8; 11428c7bd5a4SBartosz Golaszewski hash_addr += hw_addr->addr[5]; 11438c7bd5a4SBartosz Golaszewski ret = mtk_star_set_hashbit(priv, hash_addr); 11448c7bd5a4SBartosz Golaszewski if (ret) 11458c7bd5a4SBartosz Golaszewski goto hash_fail; 11468c7bd5a4SBartosz Golaszewski } 11478c7bd5a4SBartosz Golaszewski } 11488c7bd5a4SBartosz Golaszewski 11498c7bd5a4SBartosz Golaszewski return; 11508c7bd5a4SBartosz Golaszewski 11518c7bd5a4SBartosz Golaszewski hash_fail: 11528c7bd5a4SBartosz Golaszewski if (ret == -ETIMEDOUT) 11538c7bd5a4SBartosz Golaszewski netdev_err(ndev, "setting hash bit timed out\n"); 11548c7bd5a4SBartosz Golaszewski else 11558c7bd5a4SBartosz Golaszewski /* Should be -EIO */ 11568c7bd5a4SBartosz Golaszewski netdev_err(ndev, "unable to set hash bit"); 11578c7bd5a4SBartosz Golaszewski } 11588c7bd5a4SBartosz Golaszewski 11598c7bd5a4SBartosz Golaszewski static const struct net_device_ops mtk_star_netdev_ops = { 11608c7bd5a4SBartosz Golaszewski .ndo_open = mtk_star_netdev_open, 11618c7bd5a4SBartosz Golaszewski .ndo_stop = mtk_star_netdev_stop, 11628c7bd5a4SBartosz Golaszewski .ndo_start_xmit = mtk_star_netdev_start_xmit, 11638c7bd5a4SBartosz Golaszewski .ndo_get_stats64 = mtk_star_netdev_get_stats64, 11648c7bd5a4SBartosz Golaszewski .ndo_set_rx_mode = mtk_star_set_rx_mode, 1165a7605370SArnd Bergmann .ndo_eth_ioctl = mtk_star_netdev_ioctl, 11668c7bd5a4SBartosz Golaszewski .ndo_set_mac_address = eth_mac_addr, 11678c7bd5a4SBartosz Golaszewski .ndo_validate_addr = eth_validate_addr, 11688c7bd5a4SBartosz Golaszewski }; 11698c7bd5a4SBartosz Golaszewski 11708c7bd5a4SBartosz Golaszewski static void mtk_star_get_drvinfo(struct net_device *dev, 11718c7bd5a4SBartosz Golaszewski struct ethtool_drvinfo *info) 11728c7bd5a4SBartosz Golaszewski { 11738c7bd5a4SBartosz Golaszewski strlcpy(info->driver, MTK_STAR_DRVNAME, sizeof(info->driver)); 11748c7bd5a4SBartosz Golaszewski } 11758c7bd5a4SBartosz Golaszewski 11768c7bd5a4SBartosz Golaszewski /* TODO Add ethtool stats. */ 11778c7bd5a4SBartosz Golaszewski static const struct ethtool_ops mtk_star_ethtool_ops = { 11788c7bd5a4SBartosz Golaszewski .get_drvinfo = mtk_star_get_drvinfo, 11798c7bd5a4SBartosz Golaszewski .get_link = ethtool_op_get_link, 11808c7bd5a4SBartosz Golaszewski .get_link_ksettings = phy_ethtool_get_link_ksettings, 11818c7bd5a4SBartosz Golaszewski .set_link_ksettings = phy_ethtool_set_link_ksettings, 11828c7bd5a4SBartosz Golaszewski }; 11838c7bd5a4SBartosz Golaszewski 11848c7bd5a4SBartosz Golaszewski static int mtk_star_receive_packet(struct mtk_star_priv *priv) 11858c7bd5a4SBartosz Golaszewski { 11868c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->rx_ring; 11878c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 11888c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 11898c7bd5a4SBartosz Golaszewski struct net_device *ndev = priv->ndev; 11908c7bd5a4SBartosz Golaszewski struct sk_buff *curr_skb, *new_skb; 11918c7bd5a4SBartosz Golaszewski dma_addr_t new_dma_addr; 11928c7bd5a4SBartosz Golaszewski int ret; 11938c7bd5a4SBartosz Golaszewski 11948c7bd5a4SBartosz Golaszewski spin_lock(&priv->lock); 11958c7bd5a4SBartosz Golaszewski ret = mtk_star_ring_pop_tail(ring, &desc_data); 11968c7bd5a4SBartosz Golaszewski spin_unlock(&priv->lock); 11978c7bd5a4SBartosz Golaszewski if (ret) 11988c7bd5a4SBartosz Golaszewski return -1; 11998c7bd5a4SBartosz Golaszewski 12008c7bd5a4SBartosz Golaszewski curr_skb = desc_data.skb; 12018c7bd5a4SBartosz Golaszewski 12028c7bd5a4SBartosz Golaszewski if ((desc_data.flags & MTK_STAR_DESC_BIT_RX_CRCE) || 12038c7bd5a4SBartosz Golaszewski (desc_data.flags & MTK_STAR_DESC_BIT_RX_OSIZE)) { 12048c7bd5a4SBartosz Golaszewski /* Error packet -> drop and reuse skb. */ 12058c7bd5a4SBartosz Golaszewski new_skb = curr_skb; 12068c7bd5a4SBartosz Golaszewski goto push_new_skb; 12078c7bd5a4SBartosz Golaszewski } 12088c7bd5a4SBartosz Golaszewski 12098c7bd5a4SBartosz Golaszewski /* Prepare new skb before receiving the current one. Reuse the current 12108c7bd5a4SBartosz Golaszewski * skb if we fail at any point. 12118c7bd5a4SBartosz Golaszewski */ 12128c7bd5a4SBartosz Golaszewski new_skb = mtk_star_alloc_skb(ndev); 12138c7bd5a4SBartosz Golaszewski if (!new_skb) { 12148c7bd5a4SBartosz Golaszewski ndev->stats.rx_dropped++; 12158c7bd5a4SBartosz Golaszewski new_skb = curr_skb; 12168c7bd5a4SBartosz Golaszewski goto push_new_skb; 12178c7bd5a4SBartosz Golaszewski } 12188c7bd5a4SBartosz Golaszewski 12198c7bd5a4SBartosz Golaszewski new_dma_addr = mtk_star_dma_map_rx(priv, new_skb); 12208c7bd5a4SBartosz Golaszewski if (dma_mapping_error(dev, new_dma_addr)) { 12218c7bd5a4SBartosz Golaszewski ndev->stats.rx_dropped++; 12228c7bd5a4SBartosz Golaszewski dev_kfree_skb(new_skb); 12238c7bd5a4SBartosz Golaszewski new_skb = curr_skb; 12248c7bd5a4SBartosz Golaszewski netdev_err(ndev, "DMA mapping error of RX descriptor\n"); 12258c7bd5a4SBartosz Golaszewski goto push_new_skb; 12268c7bd5a4SBartosz Golaszewski } 12278c7bd5a4SBartosz Golaszewski 12288c7bd5a4SBartosz Golaszewski /* We can't fail anymore at this point: it's safe to unmap the skb. */ 12298c7bd5a4SBartosz Golaszewski mtk_star_dma_unmap_rx(priv, &desc_data); 12308c7bd5a4SBartosz Golaszewski 12318c7bd5a4SBartosz Golaszewski skb_put(desc_data.skb, desc_data.len); 12328c7bd5a4SBartosz Golaszewski desc_data.skb->ip_summed = CHECKSUM_NONE; 12338c7bd5a4SBartosz Golaszewski desc_data.skb->protocol = eth_type_trans(desc_data.skb, ndev); 12348c7bd5a4SBartosz Golaszewski desc_data.skb->dev = ndev; 12358c7bd5a4SBartosz Golaszewski netif_receive_skb(desc_data.skb); 12368c7bd5a4SBartosz Golaszewski 123795b39f07SBiao Huang /* update dma_addr for new skb */ 123895b39f07SBiao Huang desc_data.dma_addr = new_dma_addr; 123995b39f07SBiao Huang 12408c7bd5a4SBartosz Golaszewski push_new_skb: 12418c7bd5a4SBartosz Golaszewski desc_data.len = skb_tailroom(new_skb); 12428c7bd5a4SBartosz Golaszewski desc_data.skb = new_skb; 12438c7bd5a4SBartosz Golaszewski 12448c7bd5a4SBartosz Golaszewski spin_lock(&priv->lock); 12458c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_rx(ring, &desc_data); 12468c7bd5a4SBartosz Golaszewski spin_unlock(&priv->lock); 12478c7bd5a4SBartosz Golaszewski 12488c7bd5a4SBartosz Golaszewski return 0; 12498c7bd5a4SBartosz Golaszewski } 12508c7bd5a4SBartosz Golaszewski 12518c7bd5a4SBartosz Golaszewski static int mtk_star_process_rx(struct mtk_star_priv *priv, int budget) 12528c7bd5a4SBartosz Golaszewski { 12538c7bd5a4SBartosz Golaszewski int received, ret; 12548c7bd5a4SBartosz Golaszewski 12558c7bd5a4SBartosz Golaszewski for (received = 0, ret = 0; received < budget && ret == 0; received++) 12568c7bd5a4SBartosz Golaszewski ret = mtk_star_receive_packet(priv); 12578c7bd5a4SBartosz Golaszewski 12588c7bd5a4SBartosz Golaszewski mtk_star_dma_resume_rx(priv); 12598c7bd5a4SBartosz Golaszewski 12608c7bd5a4SBartosz Golaszewski return received; 12618c7bd5a4SBartosz Golaszewski } 12628c7bd5a4SBartosz Golaszewski 12638c7bd5a4SBartosz Golaszewski static int mtk_star_poll(struct napi_struct *napi, int budget) 12648c7bd5a4SBartosz Golaszewski { 12658c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 1266adaff6d9SBartosz Golaszewski unsigned int status; 12678c7bd5a4SBartosz Golaszewski int received = 0; 12688c7bd5a4SBartosz Golaszewski 12698c7bd5a4SBartosz Golaszewski priv = container_of(napi, struct mtk_star_priv, napi); 12708c7bd5a4SBartosz Golaszewski 1271adaff6d9SBartosz Golaszewski status = mtk_star_intr_read(priv); 1272adaff6d9SBartosz Golaszewski mtk_star_intr_ack_all(priv); 1273adaff6d9SBartosz Golaszewski 1274adaff6d9SBartosz Golaszewski if (status & MTK_STAR_BIT_INT_STS_TNTC) 12758c7bd5a4SBartosz Golaszewski /* Clean-up all TX descriptors. */ 12768c7bd5a4SBartosz Golaszewski mtk_star_tx_complete_all(priv); 1277adaff6d9SBartosz Golaszewski 1278adaff6d9SBartosz Golaszewski if (status & MTK_STAR_BIT_INT_STS_FNRC) 12798c7bd5a4SBartosz Golaszewski /* Receive up to $budget packets. */ 12808c7bd5a4SBartosz Golaszewski received = mtk_star_process_rx(priv, budget); 12818c7bd5a4SBartosz Golaszewski 1282adaff6d9SBartosz Golaszewski if (unlikely(status & MTK_STAR_REG_INT_STS_MIB_CNT_TH)) { 1283adaff6d9SBartosz Golaszewski mtk_star_update_stats(priv); 1284adaff6d9SBartosz Golaszewski mtk_star_reset_counters(priv); 12858c7bd5a4SBartosz Golaszewski } 12868c7bd5a4SBartosz Golaszewski 1287adaff6d9SBartosz Golaszewski if (received < budget) 1288adaff6d9SBartosz Golaszewski napi_complete_done(napi, received); 1289adaff6d9SBartosz Golaszewski 1290adaff6d9SBartosz Golaszewski mtk_star_intr_enable(priv); 1291adaff6d9SBartosz Golaszewski 12928c7bd5a4SBartosz Golaszewski return received; 12938c7bd5a4SBartosz Golaszewski } 12948c7bd5a4SBartosz Golaszewski 12958c7bd5a4SBartosz Golaszewski static void mtk_star_mdio_rwok_clear(struct mtk_star_priv *priv) 12968c7bd5a4SBartosz Golaszewski { 12978c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL0, 12988c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_PHY_CTRL0_RWOK); 12998c7bd5a4SBartosz Golaszewski } 13008c7bd5a4SBartosz Golaszewski 13018c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_rwok_wait(struct mtk_star_priv *priv) 13028c7bd5a4SBartosz Golaszewski { 13038c7bd5a4SBartosz Golaszewski unsigned int val; 13048c7bd5a4SBartosz Golaszewski 13058c7bd5a4SBartosz Golaszewski return regmap_read_poll_timeout(priv->regs, MTK_STAR_REG_PHY_CTRL0, 13068c7bd5a4SBartosz Golaszewski val, val & MTK_STAR_BIT_PHY_CTRL0_RWOK, 13078c7bd5a4SBartosz Golaszewski 10, MTK_STAR_WAIT_TIMEOUT); 13088c7bd5a4SBartosz Golaszewski } 13098c7bd5a4SBartosz Golaszewski 13108c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_read(struct mii_bus *mii, int phy_id, int regnum) 13118c7bd5a4SBartosz Golaszewski { 13128c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = mii->priv; 13138c7bd5a4SBartosz Golaszewski unsigned int val, data; 13148c7bd5a4SBartosz Golaszewski int ret; 13158c7bd5a4SBartosz Golaszewski 13168c7bd5a4SBartosz Golaszewski if (regnum & MII_ADDR_C45) 13178c7bd5a4SBartosz Golaszewski return -EOPNOTSUPP; 13188c7bd5a4SBartosz Golaszewski 13198c7bd5a4SBartosz Golaszewski mtk_star_mdio_rwok_clear(priv); 13208c7bd5a4SBartosz Golaszewski 13218c7bd5a4SBartosz Golaszewski val = (regnum << MTK_STAR_OFF_PHY_CTRL0_PREG); 13228c7bd5a4SBartosz Golaszewski val &= MTK_STAR_MSK_PHY_CTRL0_PREG; 13238c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL0_RDCMD; 13248c7bd5a4SBartosz Golaszewski 13258c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL0, val); 13268c7bd5a4SBartosz Golaszewski 13278c7bd5a4SBartosz Golaszewski ret = mtk_star_mdio_rwok_wait(priv); 13288c7bd5a4SBartosz Golaszewski if (ret) 13298c7bd5a4SBartosz Golaszewski return ret; 13308c7bd5a4SBartosz Golaszewski 13318c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, MTK_STAR_REG_PHY_CTRL0, &data); 13328c7bd5a4SBartosz Golaszewski 13338c7bd5a4SBartosz Golaszewski data &= MTK_STAR_MSK_PHY_CTRL0_RWDATA; 13348c7bd5a4SBartosz Golaszewski data >>= MTK_STAR_OFF_PHY_CTRL0_RWDATA; 13358c7bd5a4SBartosz Golaszewski 13368c7bd5a4SBartosz Golaszewski return data; 13378c7bd5a4SBartosz Golaszewski } 13388c7bd5a4SBartosz Golaszewski 13398c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_write(struct mii_bus *mii, int phy_id, 13408c7bd5a4SBartosz Golaszewski int regnum, u16 data) 13418c7bd5a4SBartosz Golaszewski { 13428c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = mii->priv; 13438c7bd5a4SBartosz Golaszewski unsigned int val; 13448c7bd5a4SBartosz Golaszewski 13458c7bd5a4SBartosz Golaszewski if (regnum & MII_ADDR_C45) 13468c7bd5a4SBartosz Golaszewski return -EOPNOTSUPP; 13478c7bd5a4SBartosz Golaszewski 13488c7bd5a4SBartosz Golaszewski mtk_star_mdio_rwok_clear(priv); 13498c7bd5a4SBartosz Golaszewski 13508c7bd5a4SBartosz Golaszewski val = data; 13518c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_PHY_CTRL0_RWDATA; 13528c7bd5a4SBartosz Golaszewski val &= MTK_STAR_MSK_PHY_CTRL0_RWDATA; 13538c7bd5a4SBartosz Golaszewski regnum <<= MTK_STAR_OFF_PHY_CTRL0_PREG; 13548c7bd5a4SBartosz Golaszewski regnum &= MTK_STAR_MSK_PHY_CTRL0_PREG; 13558c7bd5a4SBartosz Golaszewski val |= regnum; 13568c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL0_WTCMD; 13578c7bd5a4SBartosz Golaszewski 13588c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL0, val); 13598c7bd5a4SBartosz Golaszewski 13608c7bd5a4SBartosz Golaszewski return mtk_star_mdio_rwok_wait(priv); 13618c7bd5a4SBartosz Golaszewski } 13628c7bd5a4SBartosz Golaszewski 13638c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_init(struct net_device *ndev) 13648c7bd5a4SBartosz Golaszewski { 13658c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 13668c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 13678c7bd5a4SBartosz Golaszewski struct device_node *of_node, *mdio_node; 13688c7bd5a4SBartosz Golaszewski int ret; 13698c7bd5a4SBartosz Golaszewski 13708c7bd5a4SBartosz Golaszewski of_node = dev->of_node; 13718c7bd5a4SBartosz Golaszewski 13728c7bd5a4SBartosz Golaszewski mdio_node = of_get_child_by_name(of_node, "mdio"); 13738c7bd5a4SBartosz Golaszewski if (!mdio_node) 13748c7bd5a4SBartosz Golaszewski return -ENODEV; 13758c7bd5a4SBartosz Golaszewski 13768c7bd5a4SBartosz Golaszewski if (!of_device_is_available(mdio_node)) { 13778c7bd5a4SBartosz Golaszewski ret = -ENODEV; 13788c7bd5a4SBartosz Golaszewski goto out_put_node; 13798c7bd5a4SBartosz Golaszewski } 13808c7bd5a4SBartosz Golaszewski 13818c7bd5a4SBartosz Golaszewski priv->mii = devm_mdiobus_alloc(dev); 13828c7bd5a4SBartosz Golaszewski if (!priv->mii) { 13838c7bd5a4SBartosz Golaszewski ret = -ENOMEM; 13848c7bd5a4SBartosz Golaszewski goto out_put_node; 13858c7bd5a4SBartosz Golaszewski } 13868c7bd5a4SBartosz Golaszewski 13878c7bd5a4SBartosz Golaszewski snprintf(priv->mii->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); 13888c7bd5a4SBartosz Golaszewski priv->mii->name = "mtk-mac-mdio"; 13898c7bd5a4SBartosz Golaszewski priv->mii->parent = dev; 13908c7bd5a4SBartosz Golaszewski priv->mii->read = mtk_star_mdio_read; 13918c7bd5a4SBartosz Golaszewski priv->mii->write = mtk_star_mdio_write; 13928c7bd5a4SBartosz Golaszewski priv->mii->priv = priv; 13938c7bd5a4SBartosz Golaszewski 13949ed0a3faSBartosz Golaszewski ret = devm_of_mdiobus_register(dev, priv->mii, mdio_node); 13958c7bd5a4SBartosz Golaszewski 13968c7bd5a4SBartosz Golaszewski out_put_node: 13978c7bd5a4SBartosz Golaszewski of_node_put(mdio_node); 13988c7bd5a4SBartosz Golaszewski return ret; 13998c7bd5a4SBartosz Golaszewski } 14008c7bd5a4SBartosz Golaszewski 1401f99c0646SArnd Bergmann static __maybe_unused int mtk_star_suspend(struct device *dev) 14028c7bd5a4SBartosz Golaszewski { 14038c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 14048c7bd5a4SBartosz Golaszewski struct net_device *ndev; 14058c7bd5a4SBartosz Golaszewski 14068c7bd5a4SBartosz Golaszewski ndev = dev_get_drvdata(dev); 14078c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 14088c7bd5a4SBartosz Golaszewski 14098c7bd5a4SBartosz Golaszewski if (netif_running(ndev)) 14108c7bd5a4SBartosz Golaszewski mtk_star_disable(ndev); 14118c7bd5a4SBartosz Golaszewski 14128c7bd5a4SBartosz Golaszewski clk_bulk_disable_unprepare(MTK_STAR_NCLKS, priv->clks); 14138c7bd5a4SBartosz Golaszewski 14148c7bd5a4SBartosz Golaszewski return 0; 14158c7bd5a4SBartosz Golaszewski } 14168c7bd5a4SBartosz Golaszewski 1417f99c0646SArnd Bergmann static __maybe_unused int mtk_star_resume(struct device *dev) 14188c7bd5a4SBartosz Golaszewski { 14198c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 14208c7bd5a4SBartosz Golaszewski struct net_device *ndev; 14218c7bd5a4SBartosz Golaszewski int ret; 14228c7bd5a4SBartosz Golaszewski 14238c7bd5a4SBartosz Golaszewski ndev = dev_get_drvdata(dev); 14248c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 14258c7bd5a4SBartosz Golaszewski 14268c7bd5a4SBartosz Golaszewski ret = clk_bulk_prepare_enable(MTK_STAR_NCLKS, priv->clks); 14278c7bd5a4SBartosz Golaszewski if (ret) 14288c7bd5a4SBartosz Golaszewski return ret; 14298c7bd5a4SBartosz Golaszewski 14308c7bd5a4SBartosz Golaszewski if (netif_running(ndev)) { 14318c7bd5a4SBartosz Golaszewski ret = mtk_star_enable(ndev); 14328c7bd5a4SBartosz Golaszewski if (ret) 14338c7bd5a4SBartosz Golaszewski clk_bulk_disable_unprepare(MTK_STAR_NCLKS, priv->clks); 14348c7bd5a4SBartosz Golaszewski } 14358c7bd5a4SBartosz Golaszewski 14368c7bd5a4SBartosz Golaszewski return ret; 14378c7bd5a4SBartosz Golaszewski } 14388c7bd5a4SBartosz Golaszewski 14398c7bd5a4SBartosz Golaszewski static void mtk_star_clk_disable_unprepare(void *data) 14408c7bd5a4SBartosz Golaszewski { 14418c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = data; 14428c7bd5a4SBartosz Golaszewski 14438c7bd5a4SBartosz Golaszewski clk_bulk_disable_unprepare(MTK_STAR_NCLKS, priv->clks); 14448c7bd5a4SBartosz Golaszewski } 14458c7bd5a4SBartosz Golaszewski 14468c7bd5a4SBartosz Golaszewski static int mtk_star_probe(struct platform_device *pdev) 14478c7bd5a4SBartosz Golaszewski { 14488c7bd5a4SBartosz Golaszewski struct device_node *of_node; 14498c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 14508c7bd5a4SBartosz Golaszewski struct net_device *ndev; 14518c7bd5a4SBartosz Golaszewski struct device *dev; 14528c7bd5a4SBartosz Golaszewski void __iomem *base; 14538c7bd5a4SBartosz Golaszewski int ret, i; 14548c7bd5a4SBartosz Golaszewski 14558c7bd5a4SBartosz Golaszewski dev = &pdev->dev; 14568c7bd5a4SBartosz Golaszewski of_node = dev->of_node; 14578c7bd5a4SBartosz Golaszewski 14588c7bd5a4SBartosz Golaszewski ndev = devm_alloc_etherdev(dev, sizeof(*priv)); 14598c7bd5a4SBartosz Golaszewski if (!ndev) 14608c7bd5a4SBartosz Golaszewski return -ENOMEM; 14618c7bd5a4SBartosz Golaszewski 14628c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 14638c7bd5a4SBartosz Golaszewski priv->ndev = ndev; 14648c7bd5a4SBartosz Golaszewski SET_NETDEV_DEV(ndev, dev); 14658c7bd5a4SBartosz Golaszewski platform_set_drvdata(pdev, ndev); 14668c7bd5a4SBartosz Golaszewski 14678c7bd5a4SBartosz Golaszewski ndev->min_mtu = ETH_ZLEN; 14688c7bd5a4SBartosz Golaszewski ndev->max_mtu = MTK_STAR_MAX_FRAME_SIZE; 14698c7bd5a4SBartosz Golaszewski 14708c7bd5a4SBartosz Golaszewski spin_lock_init(&priv->lock); 14718c7bd5a4SBartosz Golaszewski 14728c7bd5a4SBartosz Golaszewski base = devm_platform_ioremap_resource(pdev, 0); 14738c7bd5a4SBartosz Golaszewski if (IS_ERR(base)) 14748c7bd5a4SBartosz Golaszewski return PTR_ERR(base); 14758c7bd5a4SBartosz Golaszewski 14768c7bd5a4SBartosz Golaszewski /* We won't be checking the return values of regmap read & write 14778c7bd5a4SBartosz Golaszewski * functions. They can only fail for mmio if there's a clock attached 14788c7bd5a4SBartosz Golaszewski * to regmap which is not the case here. 14798c7bd5a4SBartosz Golaszewski */ 14808c7bd5a4SBartosz Golaszewski priv->regs = devm_regmap_init_mmio(dev, base, 14818c7bd5a4SBartosz Golaszewski &mtk_star_regmap_config); 14828c7bd5a4SBartosz Golaszewski if (IS_ERR(priv->regs)) 14838c7bd5a4SBartosz Golaszewski return PTR_ERR(priv->regs); 14848c7bd5a4SBartosz Golaszewski 14858c7bd5a4SBartosz Golaszewski priv->pericfg = syscon_regmap_lookup_by_phandle(of_node, 14868c7bd5a4SBartosz Golaszewski "mediatek,pericfg"); 14878c7bd5a4SBartosz Golaszewski if (IS_ERR(priv->pericfg)) { 14888c7bd5a4SBartosz Golaszewski dev_err(dev, "Failed to lookup the PERICFG syscon\n"); 14898c7bd5a4SBartosz Golaszewski return PTR_ERR(priv->pericfg); 14908c7bd5a4SBartosz Golaszewski } 14918c7bd5a4SBartosz Golaszewski 14928c7bd5a4SBartosz Golaszewski ndev->irq = platform_get_irq(pdev, 0); 14938c7bd5a4SBartosz Golaszewski if (ndev->irq < 0) 14948c7bd5a4SBartosz Golaszewski return ndev->irq; 14958c7bd5a4SBartosz Golaszewski 14968c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NCLKS; i++) 14978c7bd5a4SBartosz Golaszewski priv->clks[i].id = mtk_star_clk_names[i]; 14988c7bd5a4SBartosz Golaszewski ret = devm_clk_bulk_get(dev, MTK_STAR_NCLKS, priv->clks); 14998c7bd5a4SBartosz Golaszewski if (ret) 15008c7bd5a4SBartosz Golaszewski return ret; 15018c7bd5a4SBartosz Golaszewski 15028c7bd5a4SBartosz Golaszewski ret = clk_bulk_prepare_enable(MTK_STAR_NCLKS, priv->clks); 15038c7bd5a4SBartosz Golaszewski if (ret) 15048c7bd5a4SBartosz Golaszewski return ret; 15058c7bd5a4SBartosz Golaszewski 15068c7bd5a4SBartosz Golaszewski ret = devm_add_action_or_reset(dev, 15078c7bd5a4SBartosz Golaszewski mtk_star_clk_disable_unprepare, priv); 15088c7bd5a4SBartosz Golaszewski if (ret) 15098c7bd5a4SBartosz Golaszewski return ret; 15108c7bd5a4SBartosz Golaszewski 15118c7bd5a4SBartosz Golaszewski ret = of_get_phy_mode(of_node, &priv->phy_intf); 15128c7bd5a4SBartosz Golaszewski if (ret) { 15138c7bd5a4SBartosz Golaszewski return ret; 15148c7bd5a4SBartosz Golaszewski } else if (priv->phy_intf != PHY_INTERFACE_MODE_RMII) { 15158c7bd5a4SBartosz Golaszewski dev_err(dev, "unsupported phy mode: %s\n", 15168c7bd5a4SBartosz Golaszewski phy_modes(priv->phy_intf)); 15178c7bd5a4SBartosz Golaszewski return -EINVAL; 15188c7bd5a4SBartosz Golaszewski } 15198c7bd5a4SBartosz Golaszewski 15208c7bd5a4SBartosz Golaszewski priv->phy_node = of_parse_phandle(of_node, "phy-handle", 0); 15218c7bd5a4SBartosz Golaszewski if (!priv->phy_node) { 15228c7bd5a4SBartosz Golaszewski dev_err(dev, "failed to retrieve the phy handle from device tree\n"); 15238c7bd5a4SBartosz Golaszewski return -ENODEV; 15248c7bd5a4SBartosz Golaszewski } 15258c7bd5a4SBartosz Golaszewski 15268c7bd5a4SBartosz Golaszewski mtk_star_set_mode_rmii(priv); 15278c7bd5a4SBartosz Golaszewski 15288c7bd5a4SBartosz Golaszewski ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 15298c7bd5a4SBartosz Golaszewski if (ret) { 15308c7bd5a4SBartosz Golaszewski dev_err(dev, "unsupported DMA mask\n"); 15318c7bd5a4SBartosz Golaszewski return ret; 15328c7bd5a4SBartosz Golaszewski } 15338c7bd5a4SBartosz Golaszewski 15348c7bd5a4SBartosz Golaszewski priv->ring_base = dmam_alloc_coherent(dev, MTK_STAR_DMA_SIZE, 15358c7bd5a4SBartosz Golaszewski &priv->dma_addr, 15368c7bd5a4SBartosz Golaszewski GFP_KERNEL | GFP_DMA); 15378c7bd5a4SBartosz Golaszewski if (!priv->ring_base) 15388c7bd5a4SBartosz Golaszewski return -ENOMEM; 15398c7bd5a4SBartosz Golaszewski 15408c7bd5a4SBartosz Golaszewski mtk_star_nic_disable_pd(priv); 15418c7bd5a4SBartosz Golaszewski mtk_star_init_config(priv); 15428c7bd5a4SBartosz Golaszewski 15438c7bd5a4SBartosz Golaszewski ret = mtk_star_mdio_init(ndev); 15448c7bd5a4SBartosz Golaszewski if (ret) 15458c7bd5a4SBartosz Golaszewski return ret; 15468c7bd5a4SBartosz Golaszewski 1547*4d04cdc5SJakub Kicinski ret = platform_get_ethdev_address(dev, ndev); 15488c7bd5a4SBartosz Golaszewski if (ret || !is_valid_ether_addr(ndev->dev_addr)) 15498c7bd5a4SBartosz Golaszewski eth_hw_addr_random(ndev); 15508c7bd5a4SBartosz Golaszewski 15518c7bd5a4SBartosz Golaszewski ndev->netdev_ops = &mtk_star_netdev_ops; 15528c7bd5a4SBartosz Golaszewski ndev->ethtool_ops = &mtk_star_ethtool_ops; 15538c7bd5a4SBartosz Golaszewski 15548c7bd5a4SBartosz Golaszewski netif_napi_add(ndev, &priv->napi, mtk_star_poll, MTK_STAR_NAPI_WEIGHT); 15558c7bd5a4SBartosz Golaszewski 15569250dcccSBartosz Golaszewski return devm_register_netdev(dev, ndev); 15578c7bd5a4SBartosz Golaszewski } 15588c7bd5a4SBartosz Golaszewski 15598c7bd5a4SBartosz Golaszewski static const struct of_device_id mtk_star_of_match[] = { 15608c7bd5a4SBartosz Golaszewski { .compatible = "mediatek,mt8516-eth", }, 15618c7bd5a4SBartosz Golaszewski { .compatible = "mediatek,mt8518-eth", }, 15628c7bd5a4SBartosz Golaszewski { .compatible = "mediatek,mt8175-eth", }, 15638c7bd5a4SBartosz Golaszewski { } 15648c7bd5a4SBartosz Golaszewski }; 15658c7bd5a4SBartosz Golaszewski MODULE_DEVICE_TABLE(of, mtk_star_of_match); 15668c7bd5a4SBartosz Golaszewski 15678c7bd5a4SBartosz Golaszewski static SIMPLE_DEV_PM_OPS(mtk_star_pm_ops, 15688c7bd5a4SBartosz Golaszewski mtk_star_suspend, mtk_star_resume); 15698c7bd5a4SBartosz Golaszewski 15708c7bd5a4SBartosz Golaszewski static struct platform_driver mtk_star_driver = { 15718c7bd5a4SBartosz Golaszewski .driver = { 15728c7bd5a4SBartosz Golaszewski .name = MTK_STAR_DRVNAME, 15738c7bd5a4SBartosz Golaszewski .pm = &mtk_star_pm_ops, 15748c7bd5a4SBartosz Golaszewski .of_match_table = of_match_ptr(mtk_star_of_match), 15758c7bd5a4SBartosz Golaszewski }, 15768c7bd5a4SBartosz Golaszewski .probe = mtk_star_probe, 15778c7bd5a4SBartosz Golaszewski }; 15788c7bd5a4SBartosz Golaszewski module_platform_driver(mtk_star_driver); 15798c7bd5a4SBartosz Golaszewski 15808c7bd5a4SBartosz Golaszewski MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); 15818c7bd5a4SBartosz Golaszewski MODULE_DESCRIPTION("Mediatek STAR Ethernet MAC Driver"); 15828c7bd5a4SBartosz Golaszewski MODULE_LICENSE("GPL"); 1583