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> 20c16cc6a0SBiao Huang #include <linux/of_device.h> 218c7bd5a4SBartosz Golaszewski #include <linux/of_mdio.h> 228c7bd5a4SBartosz Golaszewski #include <linux/of_net.h> 238c7bd5a4SBartosz Golaszewski #include <linux/platform_device.h> 248c7bd5a4SBartosz Golaszewski #include <linux/pm.h> 258c7bd5a4SBartosz Golaszewski #include <linux/regmap.h> 268c7bd5a4SBartosz Golaszewski #include <linux/skbuff.h> 278c7bd5a4SBartosz Golaszewski #include <linux/spinlock.h> 288c7bd5a4SBartosz Golaszewski 298c7bd5a4SBartosz Golaszewski #define MTK_STAR_DRVNAME "mtk_star_emac" 308c7bd5a4SBartosz Golaszewski 318c7bd5a4SBartosz Golaszewski #define MTK_STAR_WAIT_TIMEOUT 300 328c7bd5a4SBartosz Golaszewski #define MTK_STAR_MAX_FRAME_SIZE 1514 338c7bd5a4SBartosz Golaszewski #define MTK_STAR_SKB_ALIGNMENT 16 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 153*6cde23b3SBiao Huang #define MTK_STAR_BIT_CLK_DIV_50 0x32 1548c7bd5a4SBartosz Golaszewski 1558c7bd5a4SBartosz Golaszewski /* Counter registers. */ 1568c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXOKPKT 0x0100 1578c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXOKBYTE 0x0104 1588c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXRUNT 0x0108 1598c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXLONG 0x010c 1608c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXDROP 0x0110 1618c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXCRC 0x0114 1628c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXARLDROP 0x0118 1638c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXVLANDROP 0x011c 1648c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXCSERR 0x0120 1658c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RXPAUSE 0x0124 1668c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXOKPKT 0x0128 1678c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXOKBYTE 0x012c 1688c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXPAUSECOL 0x0130 1698c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXRTY 0x0134 1708c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TXSKIP 0x0138 1718c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_ARP 0x013c 1728c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_RERR 0x01d8 1738c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_UNI 0x01dc 1748c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_MULTI 0x01e0 1758c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_BROAD 0x01e4 1768c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_ALIGNERR 0x01e8 1778c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_UNI 0x01ec 1788c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_MULTI 0x01f0 1798c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_BROAD 0x01f4 1808c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_TIMEOUT 0x01f8 1818c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_TX_LATECOL 0x01fc 1828c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_LENGTHERR 0x0214 1838c7bd5a4SBartosz Golaszewski #define MTK_STAR_REG_C_RX_TWIST 0x0218 1848c7bd5a4SBartosz Golaszewski 1858c7bd5a4SBartosz Golaszewski /* Ethernet CFG Control */ 186*6cde23b3SBiao Huang #define MTK_PERICFG_REG_NIC_CFG0_CON 0x03c4 187*6cde23b3SBiao Huang #define MTK_PERICFG_REG_NIC_CFG1_CON 0x03c8 188*6cde23b3SBiao Huang #define MTK_PERICFG_REG_NIC_CFG_CON_V2 0x0c10 189*6cde23b3SBiao Huang #define MTK_PERICFG_REG_NIC_CFG_CON_CFG_INTF GENMASK(3, 0) 190*6cde23b3SBiao Huang #define MTK_PERICFG_BIT_NIC_CFG_CON_RMII 1 1918c7bd5a4SBartosz Golaszewski 1928c7bd5a4SBartosz Golaszewski /* Represents the actual structure of descriptors used by the MAC. We can 1938c7bd5a4SBartosz Golaszewski * reuse the same structure for both TX and RX - the layout is the same, only 1948c7bd5a4SBartosz Golaszewski * the flags differ slightly. 1958c7bd5a4SBartosz Golaszewski */ 1968c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc { 1978c7bd5a4SBartosz Golaszewski /* Contains both the status flags as well as packet length. */ 1988c7bd5a4SBartosz Golaszewski u32 status; 1998c7bd5a4SBartosz Golaszewski u32 data_ptr; 2008c7bd5a4SBartosz Golaszewski u32 vtag; 2018c7bd5a4SBartosz Golaszewski u32 reserved; 2028c7bd5a4SBartosz Golaszewski }; 2038c7bd5a4SBartosz Golaszewski 2048c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_MSK_LEN GENMASK(15, 0) 2058c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_RX_CRCE BIT(24) 2068c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_RX_OSIZE BIT(25) 2078c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_INT BIT(27) 2088c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_LS BIT(28) 2098c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_FS BIT(29) 2108c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_EOR BIT(30) 2118c7bd5a4SBartosz Golaszewski #define MTK_STAR_DESC_BIT_COWN BIT(31) 2128c7bd5a4SBartosz Golaszewski 2138c7bd5a4SBartosz Golaszewski /* Helper structure for storing data read from/written to descriptors in order 2148c7bd5a4SBartosz Golaszewski * to limit reads from/writes to DMA memory. 2158c7bd5a4SBartosz Golaszewski */ 2168c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data { 2178c7bd5a4SBartosz Golaszewski unsigned int len; 2188c7bd5a4SBartosz Golaszewski unsigned int flags; 2198c7bd5a4SBartosz Golaszewski dma_addr_t dma_addr; 2208c7bd5a4SBartosz Golaszewski struct sk_buff *skb; 2218c7bd5a4SBartosz Golaszewski }; 2228c7bd5a4SBartosz Golaszewski 2238c7bd5a4SBartosz Golaszewski #define MTK_STAR_RING_NUM_DESCS 128 2248c7bd5a4SBartosz Golaszewski #define MTK_STAR_NUM_TX_DESCS MTK_STAR_RING_NUM_DESCS 2258c7bd5a4SBartosz Golaszewski #define MTK_STAR_NUM_RX_DESCS MTK_STAR_RING_NUM_DESCS 2268c7bd5a4SBartosz Golaszewski #define MTK_STAR_NUM_DESCS_TOTAL (MTK_STAR_RING_NUM_DESCS * 2) 2278c7bd5a4SBartosz Golaszewski #define MTK_STAR_DMA_SIZE \ 2288c7bd5a4SBartosz Golaszewski (MTK_STAR_NUM_DESCS_TOTAL * sizeof(struct mtk_star_ring_desc)) 2298c7bd5a4SBartosz Golaszewski 2308c7bd5a4SBartosz Golaszewski struct mtk_star_ring { 2318c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *descs; 2328c7bd5a4SBartosz Golaszewski struct sk_buff *skbs[MTK_STAR_RING_NUM_DESCS]; 2338c7bd5a4SBartosz Golaszewski dma_addr_t dma_addrs[MTK_STAR_RING_NUM_DESCS]; 2348c7bd5a4SBartosz Golaszewski unsigned int head; 2358c7bd5a4SBartosz Golaszewski unsigned int tail; 2368c7bd5a4SBartosz Golaszewski }; 2378c7bd5a4SBartosz Golaszewski 238c16cc6a0SBiao Huang struct mtk_star_compat { 239*6cde23b3SBiao Huang int (*set_interface_mode)(struct net_device *ndev); 240c16cc6a0SBiao Huang unsigned char bit_clk_div; 241c16cc6a0SBiao Huang }; 242c16cc6a0SBiao Huang 2438c7bd5a4SBartosz Golaszewski struct mtk_star_priv { 2448c7bd5a4SBartosz Golaszewski struct net_device *ndev; 2458c7bd5a4SBartosz Golaszewski 2468c7bd5a4SBartosz Golaszewski struct regmap *regs; 2478c7bd5a4SBartosz Golaszewski struct regmap *pericfg; 2488c7bd5a4SBartosz Golaszewski 2498c7bd5a4SBartosz Golaszewski struct clk_bulk_data clks[MTK_STAR_NCLKS]; 2508c7bd5a4SBartosz Golaszewski 2518c7bd5a4SBartosz Golaszewski void *ring_base; 2528c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *descs_base; 2538c7bd5a4SBartosz Golaszewski dma_addr_t dma_addr; 2548c7bd5a4SBartosz Golaszewski struct mtk_star_ring tx_ring; 2558c7bd5a4SBartosz Golaszewski struct mtk_star_ring rx_ring; 2568c7bd5a4SBartosz Golaszewski 2578c7bd5a4SBartosz Golaszewski struct mii_bus *mii; 2588c7bd5a4SBartosz Golaszewski struct napi_struct napi; 2598c7bd5a4SBartosz Golaszewski 2608c7bd5a4SBartosz Golaszewski struct device_node *phy_node; 2618c7bd5a4SBartosz Golaszewski phy_interface_t phy_intf; 2628c7bd5a4SBartosz Golaszewski struct phy_device *phydev; 2638c7bd5a4SBartosz Golaszewski unsigned int link; 2648c7bd5a4SBartosz Golaszewski int speed; 2658c7bd5a4SBartosz Golaszewski int duplex; 2668c7bd5a4SBartosz Golaszewski int pause; 2678c7bd5a4SBartosz Golaszewski 268c16cc6a0SBiao Huang const struct mtk_star_compat *compat_data; 269c16cc6a0SBiao Huang 2708c7bd5a4SBartosz Golaszewski /* Protects against concurrent descriptor access. */ 2718c7bd5a4SBartosz Golaszewski spinlock_t lock; 2728c7bd5a4SBartosz Golaszewski 2738c7bd5a4SBartosz Golaszewski struct rtnl_link_stats64 stats; 2748c7bd5a4SBartosz Golaszewski }; 2758c7bd5a4SBartosz Golaszewski 2768c7bd5a4SBartosz Golaszewski static struct device *mtk_star_get_dev(struct mtk_star_priv *priv) 2778c7bd5a4SBartosz Golaszewski { 2788c7bd5a4SBartosz Golaszewski return priv->ndev->dev.parent; 2798c7bd5a4SBartosz Golaszewski } 2808c7bd5a4SBartosz Golaszewski 2818c7bd5a4SBartosz Golaszewski static const struct regmap_config mtk_star_regmap_config = { 2828c7bd5a4SBartosz Golaszewski .reg_bits = 32, 2838c7bd5a4SBartosz Golaszewski .val_bits = 32, 2848c7bd5a4SBartosz Golaszewski .reg_stride = 4, 2858c7bd5a4SBartosz Golaszewski .disable_locking = true, 2868c7bd5a4SBartosz Golaszewski }; 2878c7bd5a4SBartosz Golaszewski 2888c7bd5a4SBartosz Golaszewski static void mtk_star_ring_init(struct mtk_star_ring *ring, 2898c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *descs) 2908c7bd5a4SBartosz Golaszewski { 2918c7bd5a4SBartosz Golaszewski memset(ring, 0, sizeof(*ring)); 2928c7bd5a4SBartosz Golaszewski ring->descs = descs; 2938c7bd5a4SBartosz Golaszewski ring->head = 0; 2948c7bd5a4SBartosz Golaszewski ring->tail = 0; 2958c7bd5a4SBartosz Golaszewski } 2968c7bd5a4SBartosz Golaszewski 2978c7bd5a4SBartosz Golaszewski static int mtk_star_ring_pop_tail(struct mtk_star_ring *ring, 2988c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 2998c7bd5a4SBartosz Golaszewski { 3008c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc = &ring->descs[ring->tail]; 3018c7bd5a4SBartosz Golaszewski unsigned int status; 3028c7bd5a4SBartosz Golaszewski 3038c7bd5a4SBartosz Golaszewski status = READ_ONCE(desc->status); 3048c7bd5a4SBartosz Golaszewski dma_rmb(); /* Make sure we read the status bits before checking it. */ 3058c7bd5a4SBartosz Golaszewski 3068c7bd5a4SBartosz Golaszewski if (!(status & MTK_STAR_DESC_BIT_COWN)) 3078c7bd5a4SBartosz Golaszewski return -1; 3088c7bd5a4SBartosz Golaszewski 3098c7bd5a4SBartosz Golaszewski desc_data->len = status & MTK_STAR_DESC_MSK_LEN; 3108c7bd5a4SBartosz Golaszewski desc_data->flags = status & ~MTK_STAR_DESC_MSK_LEN; 3118c7bd5a4SBartosz Golaszewski desc_data->dma_addr = ring->dma_addrs[ring->tail]; 3128c7bd5a4SBartosz Golaszewski desc_data->skb = ring->skbs[ring->tail]; 3138c7bd5a4SBartosz Golaszewski 3148c7bd5a4SBartosz Golaszewski ring->dma_addrs[ring->tail] = 0; 3158c7bd5a4SBartosz Golaszewski ring->skbs[ring->tail] = NULL; 3168c7bd5a4SBartosz Golaszewski 3178c7bd5a4SBartosz Golaszewski status &= MTK_STAR_DESC_BIT_COWN | MTK_STAR_DESC_BIT_EOR; 3188c7bd5a4SBartosz Golaszewski 3198c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->data_ptr, 0); 3208c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->status, status); 3218c7bd5a4SBartosz Golaszewski 3228c7bd5a4SBartosz Golaszewski ring->tail = (ring->tail + 1) % MTK_STAR_RING_NUM_DESCS; 3238c7bd5a4SBartosz Golaszewski 3248c7bd5a4SBartosz Golaszewski return 0; 3258c7bd5a4SBartosz Golaszewski } 3268c7bd5a4SBartosz Golaszewski 3278c7bd5a4SBartosz Golaszewski static void mtk_star_ring_push_head(struct mtk_star_ring *ring, 3288c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data, 3298c7bd5a4SBartosz Golaszewski unsigned int flags) 3308c7bd5a4SBartosz Golaszewski { 3318c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc = &ring->descs[ring->head]; 3328c7bd5a4SBartosz Golaszewski unsigned int status; 3338c7bd5a4SBartosz Golaszewski 3348c7bd5a4SBartosz Golaszewski status = READ_ONCE(desc->status); 3358c7bd5a4SBartosz Golaszewski 3368c7bd5a4SBartosz Golaszewski ring->skbs[ring->head] = desc_data->skb; 3378c7bd5a4SBartosz Golaszewski ring->dma_addrs[ring->head] = desc_data->dma_addr; 3388c7bd5a4SBartosz Golaszewski 3398c7bd5a4SBartosz Golaszewski status |= desc_data->len; 3408c7bd5a4SBartosz Golaszewski if (flags) 3418c7bd5a4SBartosz Golaszewski status |= flags; 3428c7bd5a4SBartosz Golaszewski 3438c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->data_ptr, desc_data->dma_addr); 3448c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->status, status); 3458c7bd5a4SBartosz Golaszewski status &= ~MTK_STAR_DESC_BIT_COWN; 3468c7bd5a4SBartosz Golaszewski /* Flush previous modifications before ownership change. */ 3478c7bd5a4SBartosz Golaszewski dma_wmb(); 3488c7bd5a4SBartosz Golaszewski WRITE_ONCE(desc->status, status); 3498c7bd5a4SBartosz Golaszewski 3508c7bd5a4SBartosz Golaszewski ring->head = (ring->head + 1) % MTK_STAR_RING_NUM_DESCS; 3518c7bd5a4SBartosz Golaszewski } 3528c7bd5a4SBartosz Golaszewski 3538c7bd5a4SBartosz Golaszewski static void 3548c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_rx(struct mtk_star_ring *ring, 3558c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 3568c7bd5a4SBartosz Golaszewski { 3578c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head(ring, desc_data, 0); 3588c7bd5a4SBartosz Golaszewski } 3598c7bd5a4SBartosz Golaszewski 3608c7bd5a4SBartosz Golaszewski static void 3618c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_tx(struct mtk_star_ring *ring, 3628c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 3638c7bd5a4SBartosz Golaszewski { 3648c7bd5a4SBartosz Golaszewski static const unsigned int flags = MTK_STAR_DESC_BIT_FS | 3658c7bd5a4SBartosz Golaszewski MTK_STAR_DESC_BIT_LS | 3668c7bd5a4SBartosz Golaszewski MTK_STAR_DESC_BIT_INT; 3678c7bd5a4SBartosz Golaszewski 3688c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head(ring, desc_data, flags); 3698c7bd5a4SBartosz Golaszewski } 3708c7bd5a4SBartosz Golaszewski 3718c7bd5a4SBartosz Golaszewski static unsigned int mtk_star_ring_num_used_descs(struct mtk_star_ring *ring) 3728c7bd5a4SBartosz Golaszewski { 3738c7bd5a4SBartosz Golaszewski return abs(ring->head - ring->tail); 3748c7bd5a4SBartosz Golaszewski } 3758c7bd5a4SBartosz Golaszewski 3768c7bd5a4SBartosz Golaszewski static bool mtk_star_ring_full(struct mtk_star_ring *ring) 3778c7bd5a4SBartosz Golaszewski { 3788c7bd5a4SBartosz Golaszewski return mtk_star_ring_num_used_descs(ring) == MTK_STAR_RING_NUM_DESCS; 3798c7bd5a4SBartosz Golaszewski } 3808c7bd5a4SBartosz Golaszewski 3818c7bd5a4SBartosz Golaszewski static bool mtk_star_ring_descs_available(struct mtk_star_ring *ring) 3828c7bd5a4SBartosz Golaszewski { 3838c7bd5a4SBartosz Golaszewski return mtk_star_ring_num_used_descs(ring) > 0; 3848c7bd5a4SBartosz Golaszewski } 3858c7bd5a4SBartosz Golaszewski 3868c7bd5a4SBartosz Golaszewski static dma_addr_t mtk_star_dma_map_rx(struct mtk_star_priv *priv, 3878c7bd5a4SBartosz Golaszewski struct sk_buff *skb) 3888c7bd5a4SBartosz Golaszewski { 3898c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 3908c7bd5a4SBartosz Golaszewski 3918c7bd5a4SBartosz Golaszewski /* Data pointer for the RX DMA descriptor must be aligned to 4N + 2. */ 3928c7bd5a4SBartosz Golaszewski return dma_map_single(dev, skb_tail_pointer(skb) - 2, 3938c7bd5a4SBartosz Golaszewski skb_tailroom(skb), DMA_FROM_DEVICE); 3948c7bd5a4SBartosz Golaszewski } 3958c7bd5a4SBartosz Golaszewski 3968c7bd5a4SBartosz Golaszewski static void mtk_star_dma_unmap_rx(struct mtk_star_priv *priv, 3978c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 3988c7bd5a4SBartosz Golaszewski { 3998c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 4008c7bd5a4SBartosz Golaszewski 4018c7bd5a4SBartosz Golaszewski dma_unmap_single(dev, desc_data->dma_addr, 4028c7bd5a4SBartosz Golaszewski skb_tailroom(desc_data->skb), DMA_FROM_DEVICE); 4038c7bd5a4SBartosz Golaszewski } 4048c7bd5a4SBartosz Golaszewski 4058c7bd5a4SBartosz Golaszewski static dma_addr_t mtk_star_dma_map_tx(struct mtk_star_priv *priv, 4068c7bd5a4SBartosz Golaszewski struct sk_buff *skb) 4078c7bd5a4SBartosz Golaszewski { 4088c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 4098c7bd5a4SBartosz Golaszewski 4108c7bd5a4SBartosz Golaszewski return dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); 4118c7bd5a4SBartosz Golaszewski } 4128c7bd5a4SBartosz Golaszewski 4138c7bd5a4SBartosz Golaszewski static void mtk_star_dma_unmap_tx(struct mtk_star_priv *priv, 4148c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *desc_data) 4158c7bd5a4SBartosz Golaszewski { 4168c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 4178c7bd5a4SBartosz Golaszewski 4188c7bd5a4SBartosz Golaszewski return dma_unmap_single(dev, desc_data->dma_addr, 4198c7bd5a4SBartosz Golaszewski skb_headlen(desc_data->skb), DMA_TO_DEVICE); 4208c7bd5a4SBartosz Golaszewski } 4218c7bd5a4SBartosz Golaszewski 4228c7bd5a4SBartosz Golaszewski static void mtk_star_nic_disable_pd(struct mtk_star_priv *priv) 4238c7bd5a4SBartosz Golaszewski { 424240f1ae4SBartosz Golaszewski regmap_clear_bits(priv->regs, MTK_STAR_REG_MAC_CFG, 425240f1ae4SBartosz Golaszewski MTK_STAR_BIT_MAC_CFG_NIC_PD); 4268c7bd5a4SBartosz Golaszewski } 4278c7bd5a4SBartosz Golaszewski 4288c7bd5a4SBartosz Golaszewski /* Unmask the three interrupts we care about, mask all others. */ 4298c7bd5a4SBartosz Golaszewski static void mtk_star_intr_enable(struct mtk_star_priv *priv) 4308c7bd5a4SBartosz Golaszewski { 4318c7bd5a4SBartosz Golaszewski unsigned int val = MTK_STAR_BIT_INT_STS_TNTC | 4328c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_INT_STS_FNRC | 4338c7bd5a4SBartosz Golaszewski MTK_STAR_REG_INT_STS_MIB_CNT_TH; 4348c7bd5a4SBartosz Golaszewski 4358c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_INT_MASK, ~val); 4368c7bd5a4SBartosz Golaszewski } 4378c7bd5a4SBartosz Golaszewski 4388c7bd5a4SBartosz Golaszewski static void mtk_star_intr_disable(struct mtk_star_priv *priv) 4398c7bd5a4SBartosz Golaszewski { 4408c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_INT_MASK, ~0); 4418c7bd5a4SBartosz Golaszewski } 4428c7bd5a4SBartosz Golaszewski 4438c7bd5a4SBartosz Golaszewski static unsigned int mtk_star_intr_read(struct mtk_star_priv *priv) 4448c7bd5a4SBartosz Golaszewski { 4458c7bd5a4SBartosz Golaszewski unsigned int val; 4468c7bd5a4SBartosz Golaszewski 4478c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, MTK_STAR_REG_INT_STS, &val); 4488c7bd5a4SBartosz Golaszewski 4498c7bd5a4SBartosz Golaszewski return val; 4508c7bd5a4SBartosz Golaszewski } 4518c7bd5a4SBartosz Golaszewski 4528c7bd5a4SBartosz Golaszewski static unsigned int mtk_star_intr_ack_all(struct mtk_star_priv *priv) 4538c7bd5a4SBartosz Golaszewski { 4548c7bd5a4SBartosz Golaszewski unsigned int val; 4558c7bd5a4SBartosz Golaszewski 4568c7bd5a4SBartosz Golaszewski val = mtk_star_intr_read(priv); 4578c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_INT_STS, val); 4588c7bd5a4SBartosz Golaszewski 4598c7bd5a4SBartosz Golaszewski return val; 4608c7bd5a4SBartosz Golaszewski } 4618c7bd5a4SBartosz Golaszewski 4628c7bd5a4SBartosz Golaszewski static void mtk_star_dma_init(struct mtk_star_priv *priv) 4638c7bd5a4SBartosz Golaszewski { 4648c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc; 4658c7bd5a4SBartosz Golaszewski unsigned int val; 4668c7bd5a4SBartosz Golaszewski int i; 4678c7bd5a4SBartosz Golaszewski 4688c7bd5a4SBartosz Golaszewski priv->descs_base = (struct mtk_star_ring_desc *)priv->ring_base; 4698c7bd5a4SBartosz Golaszewski 4708c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NUM_DESCS_TOTAL; i++) { 4718c7bd5a4SBartosz Golaszewski desc = &priv->descs_base[i]; 4728c7bd5a4SBartosz Golaszewski 4738c7bd5a4SBartosz Golaszewski memset(desc, 0, sizeof(*desc)); 4748c7bd5a4SBartosz Golaszewski desc->status = MTK_STAR_DESC_BIT_COWN; 4758c7bd5a4SBartosz Golaszewski if ((i == MTK_STAR_NUM_TX_DESCS - 1) || 4768c7bd5a4SBartosz Golaszewski (i == MTK_STAR_NUM_DESCS_TOTAL - 1)) 4778c7bd5a4SBartosz Golaszewski desc->status |= MTK_STAR_DESC_BIT_EOR; 4788c7bd5a4SBartosz Golaszewski } 4798c7bd5a4SBartosz Golaszewski 4808c7bd5a4SBartosz Golaszewski mtk_star_ring_init(&priv->tx_ring, priv->descs_base); 4818c7bd5a4SBartosz Golaszewski mtk_star_ring_init(&priv->rx_ring, 4828c7bd5a4SBartosz Golaszewski priv->descs_base + MTK_STAR_NUM_TX_DESCS); 4838c7bd5a4SBartosz Golaszewski 4848c7bd5a4SBartosz Golaszewski /* Set DMA pointers. */ 4858c7bd5a4SBartosz Golaszewski val = (unsigned int)priv->dma_addr; 4868c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_TX_BASE_ADDR, val); 4878c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_TX_DPTR, val); 4888c7bd5a4SBartosz Golaszewski 4898c7bd5a4SBartosz Golaszewski val += sizeof(struct mtk_star_ring_desc) * MTK_STAR_NUM_TX_DESCS; 4908c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_RX_BASE_ADDR, val); 4918c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_RX_DPTR, val); 4928c7bd5a4SBartosz Golaszewski } 4938c7bd5a4SBartosz Golaszewski 4948c7bd5a4SBartosz Golaszewski static void mtk_star_dma_start(struct mtk_star_priv *priv) 4958c7bd5a4SBartosz Golaszewski { 496240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_TX_DMA_CTRL, 4978c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TX_DMA_CTRL_START); 498240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_RX_DMA_CTRL, 4998c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_RX_DMA_CTRL_START); 5008c7bd5a4SBartosz Golaszewski } 5018c7bd5a4SBartosz Golaszewski 5028c7bd5a4SBartosz Golaszewski static void mtk_star_dma_stop(struct mtk_star_priv *priv) 5038c7bd5a4SBartosz Golaszewski { 5048c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_TX_DMA_CTRL, 5058c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TX_DMA_CTRL_STOP); 5068c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_RX_DMA_CTRL, 5078c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_RX_DMA_CTRL_STOP); 5088c7bd5a4SBartosz Golaszewski } 5098c7bd5a4SBartosz Golaszewski 5108c7bd5a4SBartosz Golaszewski static void mtk_star_dma_disable(struct mtk_star_priv *priv) 5118c7bd5a4SBartosz Golaszewski { 5128c7bd5a4SBartosz Golaszewski int i; 5138c7bd5a4SBartosz Golaszewski 5148c7bd5a4SBartosz Golaszewski mtk_star_dma_stop(priv); 5158c7bd5a4SBartosz Golaszewski 5168c7bd5a4SBartosz Golaszewski /* Take back all descriptors. */ 5178c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NUM_DESCS_TOTAL; i++) 5188c7bd5a4SBartosz Golaszewski priv->descs_base[i].status |= MTK_STAR_DESC_BIT_COWN; 5198c7bd5a4SBartosz Golaszewski } 5208c7bd5a4SBartosz Golaszewski 5218c7bd5a4SBartosz Golaszewski static void mtk_star_dma_resume_rx(struct mtk_star_priv *priv) 5228c7bd5a4SBartosz Golaszewski { 523240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_RX_DMA_CTRL, 5248c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_RX_DMA_CTRL_RESUME); 5258c7bd5a4SBartosz Golaszewski } 5268c7bd5a4SBartosz Golaszewski 5278c7bd5a4SBartosz Golaszewski static void mtk_star_dma_resume_tx(struct mtk_star_priv *priv) 5288c7bd5a4SBartosz Golaszewski { 529240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_TX_DMA_CTRL, 5308c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TX_DMA_CTRL_RESUME); 5318c7bd5a4SBartosz Golaszewski } 5328c7bd5a4SBartosz Golaszewski 5338c7bd5a4SBartosz Golaszewski static void mtk_star_set_mac_addr(struct net_device *ndev) 5348c7bd5a4SBartosz Golaszewski { 5358c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 53676660757SJakub Kicinski const u8 *mac_addr = ndev->dev_addr; 5378c7bd5a4SBartosz Golaszewski unsigned int high, low; 5388c7bd5a4SBartosz Golaszewski 5398c7bd5a4SBartosz Golaszewski high = mac_addr[0] << 8 | mac_addr[1] << 0; 5408c7bd5a4SBartosz Golaszewski low = mac_addr[2] << 24 | mac_addr[3] << 16 | 5418c7bd5a4SBartosz Golaszewski mac_addr[4] << 8 | mac_addr[5]; 5428c7bd5a4SBartosz Golaszewski 5438c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_MY_MAC_H, high); 5448c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_MY_MAC_L, low); 5458c7bd5a4SBartosz Golaszewski } 5468c7bd5a4SBartosz Golaszewski 5478c7bd5a4SBartosz Golaszewski static void mtk_star_reset_counters(struct mtk_star_priv *priv) 5488c7bd5a4SBartosz Golaszewski { 5498c7bd5a4SBartosz Golaszewski static const unsigned int counter_regs[] = { 5508c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXOKPKT, 5518c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXOKBYTE, 5528c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXRUNT, 5538c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXLONG, 5548c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXDROP, 5558c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXCRC, 5568c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXARLDROP, 5578c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXVLANDROP, 5588c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXCSERR, 5598c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RXPAUSE, 5608c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXOKPKT, 5618c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXOKBYTE, 5628c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXPAUSECOL, 5638c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXRTY, 5648c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TXSKIP, 5658c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_ARP, 5668c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_RERR, 5678c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_UNI, 5688c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_MULTI, 5698c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_BROAD, 5708c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_ALIGNERR, 5718c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_UNI, 5728c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_MULTI, 5738c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_BROAD, 5748c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_TIMEOUT, 5758c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_TX_LATECOL, 5768c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_LENGTHERR, 5778c7bd5a4SBartosz Golaszewski MTK_STAR_REG_C_RX_TWIST, 5788c7bd5a4SBartosz Golaszewski }; 5798c7bd5a4SBartosz Golaszewski 5808c7bd5a4SBartosz Golaszewski unsigned int i, val; 5818c7bd5a4SBartosz Golaszewski 5828c7bd5a4SBartosz Golaszewski for (i = 0; i < ARRAY_SIZE(counter_regs); i++) 5838c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, counter_regs[i], &val); 5848c7bd5a4SBartosz Golaszewski } 5858c7bd5a4SBartosz Golaszewski 5868c7bd5a4SBartosz Golaszewski static void mtk_star_update_stat(struct mtk_star_priv *priv, 5878c7bd5a4SBartosz Golaszewski unsigned int reg, u64 *stat) 5888c7bd5a4SBartosz Golaszewski { 5898c7bd5a4SBartosz Golaszewski unsigned int val; 5908c7bd5a4SBartosz Golaszewski 5918c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, reg, &val); 5928c7bd5a4SBartosz Golaszewski *stat += val; 5938c7bd5a4SBartosz Golaszewski } 5948c7bd5a4SBartosz Golaszewski 5958c7bd5a4SBartosz Golaszewski /* Try to get as many stats as possible from the internal registers instead 5968c7bd5a4SBartosz Golaszewski * of tracking them ourselves. 5978c7bd5a4SBartosz Golaszewski */ 5988c7bd5a4SBartosz Golaszewski static void mtk_star_update_stats(struct mtk_star_priv *priv) 5998c7bd5a4SBartosz Golaszewski { 6008c7bd5a4SBartosz Golaszewski struct rtnl_link_stats64 *stats = &priv->stats; 6018c7bd5a4SBartosz Golaszewski 6028c7bd5a4SBartosz Golaszewski /* OK packets and bytes. */ 6038c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXOKPKT, &stats->rx_packets); 6048c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TXOKPKT, &stats->tx_packets); 6058c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXOKBYTE, &stats->rx_bytes); 6068c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TXOKBYTE, &stats->tx_bytes); 6078c7bd5a4SBartosz Golaszewski 6088c7bd5a4SBartosz Golaszewski /* RX & TX multicast. */ 6098c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_MULTI, &stats->multicast); 6108c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TX_MULTI, &stats->multicast); 6118c7bd5a4SBartosz Golaszewski 6128c7bd5a4SBartosz Golaszewski /* Collisions. */ 6138c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TXPAUSECOL, 6148c7bd5a4SBartosz Golaszewski &stats->collisions); 6158c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_TX_LATECOL, 6168c7bd5a4SBartosz Golaszewski &stats->collisions); 6178c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXRUNT, &stats->collisions); 6188c7bd5a4SBartosz Golaszewski 6198c7bd5a4SBartosz Golaszewski /* RX Errors. */ 6208c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_LENGTHERR, 6218c7bd5a4SBartosz Golaszewski &stats->rx_length_errors); 6228c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXLONG, 6238c7bd5a4SBartosz Golaszewski &stats->rx_over_errors); 6248c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXCRC, &stats->rx_crc_errors); 6258c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_ALIGNERR, 6268c7bd5a4SBartosz Golaszewski &stats->rx_frame_errors); 6278c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RXDROP, 6288c7bd5a4SBartosz Golaszewski &stats->rx_fifo_errors); 6298c7bd5a4SBartosz Golaszewski /* Sum of the general RX error counter + all of the above. */ 6308c7bd5a4SBartosz Golaszewski mtk_star_update_stat(priv, MTK_STAR_REG_C_RX_RERR, &stats->rx_errors); 6318c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_length_errors; 6328c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_over_errors; 6338c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_crc_errors; 6348c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_frame_errors; 6358c7bd5a4SBartosz Golaszewski stats->rx_errors += stats->rx_fifo_errors; 6368c7bd5a4SBartosz Golaszewski } 6378c7bd5a4SBartosz Golaszewski 6388c7bd5a4SBartosz Golaszewski static struct sk_buff *mtk_star_alloc_skb(struct net_device *ndev) 6398c7bd5a4SBartosz Golaszewski { 6408c7bd5a4SBartosz Golaszewski uintptr_t tail, offset; 6418c7bd5a4SBartosz Golaszewski struct sk_buff *skb; 6428c7bd5a4SBartosz Golaszewski 6438c7bd5a4SBartosz Golaszewski skb = dev_alloc_skb(MTK_STAR_MAX_FRAME_SIZE); 6448c7bd5a4SBartosz Golaszewski if (!skb) 6458c7bd5a4SBartosz Golaszewski return NULL; 6468c7bd5a4SBartosz Golaszewski 6478c7bd5a4SBartosz Golaszewski /* Align to 16 bytes. */ 6488c7bd5a4SBartosz Golaszewski tail = (uintptr_t)skb_tail_pointer(skb); 6498c7bd5a4SBartosz Golaszewski if (tail & (MTK_STAR_SKB_ALIGNMENT - 1)) { 6508c7bd5a4SBartosz Golaszewski offset = tail & (MTK_STAR_SKB_ALIGNMENT - 1); 6518c7bd5a4SBartosz Golaszewski skb_reserve(skb, MTK_STAR_SKB_ALIGNMENT - offset); 6528c7bd5a4SBartosz Golaszewski } 6538c7bd5a4SBartosz Golaszewski 6548c7bd5a4SBartosz Golaszewski /* Ensure 16-byte alignment of the skb pointer: eth_type_trans() will 6558c7bd5a4SBartosz Golaszewski * extract the Ethernet header (14 bytes) so we need two more bytes. 6568c7bd5a4SBartosz Golaszewski */ 6578c7bd5a4SBartosz Golaszewski skb_reserve(skb, MTK_STAR_IP_ALIGN); 6588c7bd5a4SBartosz Golaszewski 6598c7bd5a4SBartosz Golaszewski return skb; 6608c7bd5a4SBartosz Golaszewski } 6618c7bd5a4SBartosz Golaszewski 6628c7bd5a4SBartosz Golaszewski static int mtk_star_prepare_rx_skbs(struct net_device *ndev) 6638c7bd5a4SBartosz Golaszewski { 6648c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 6658c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->rx_ring; 6668c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 6678c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc *desc; 6688c7bd5a4SBartosz Golaszewski struct sk_buff *skb; 6698c7bd5a4SBartosz Golaszewski dma_addr_t dma_addr; 6708c7bd5a4SBartosz Golaszewski int i; 6718c7bd5a4SBartosz Golaszewski 6728c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NUM_RX_DESCS; i++) { 6738c7bd5a4SBartosz Golaszewski skb = mtk_star_alloc_skb(ndev); 6748c7bd5a4SBartosz Golaszewski if (!skb) 6758c7bd5a4SBartosz Golaszewski return -ENOMEM; 6768c7bd5a4SBartosz Golaszewski 6778c7bd5a4SBartosz Golaszewski dma_addr = mtk_star_dma_map_rx(priv, skb); 6788c7bd5a4SBartosz Golaszewski if (dma_mapping_error(dev, dma_addr)) { 6798c7bd5a4SBartosz Golaszewski dev_kfree_skb(skb); 6808c7bd5a4SBartosz Golaszewski return -ENOMEM; 6818c7bd5a4SBartosz Golaszewski } 6828c7bd5a4SBartosz Golaszewski 6838c7bd5a4SBartosz Golaszewski desc = &ring->descs[i]; 6848c7bd5a4SBartosz Golaszewski desc->data_ptr = dma_addr; 6858c7bd5a4SBartosz Golaszewski desc->status |= skb_tailroom(skb) & MTK_STAR_DESC_MSK_LEN; 6868c7bd5a4SBartosz Golaszewski desc->status &= ~MTK_STAR_DESC_BIT_COWN; 6878c7bd5a4SBartosz Golaszewski ring->skbs[i] = skb; 6888c7bd5a4SBartosz Golaszewski ring->dma_addrs[i] = dma_addr; 6898c7bd5a4SBartosz Golaszewski } 6908c7bd5a4SBartosz Golaszewski 6918c7bd5a4SBartosz Golaszewski return 0; 6928c7bd5a4SBartosz Golaszewski } 6938c7bd5a4SBartosz Golaszewski 6948c7bd5a4SBartosz Golaszewski static void 6958c7bd5a4SBartosz Golaszewski mtk_star_ring_free_skbs(struct mtk_star_priv *priv, struct mtk_star_ring *ring, 6968c7bd5a4SBartosz Golaszewski void (*unmap_func)(struct mtk_star_priv *, 6978c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data *)) 6988c7bd5a4SBartosz Golaszewski { 6998c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 7008c7bd5a4SBartosz Golaszewski int i; 7018c7bd5a4SBartosz Golaszewski 7028c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_RING_NUM_DESCS; i++) { 7038c7bd5a4SBartosz Golaszewski if (!ring->dma_addrs[i]) 7048c7bd5a4SBartosz Golaszewski continue; 7058c7bd5a4SBartosz Golaszewski 7068c7bd5a4SBartosz Golaszewski desc_data.dma_addr = ring->dma_addrs[i]; 7078c7bd5a4SBartosz Golaszewski desc_data.skb = ring->skbs[i]; 7088c7bd5a4SBartosz Golaszewski 7098c7bd5a4SBartosz Golaszewski unmap_func(priv, &desc_data); 7108c7bd5a4SBartosz Golaszewski dev_kfree_skb(desc_data.skb); 7118c7bd5a4SBartosz Golaszewski } 7128c7bd5a4SBartosz Golaszewski } 7138c7bd5a4SBartosz Golaszewski 7148c7bd5a4SBartosz Golaszewski static void mtk_star_free_rx_skbs(struct mtk_star_priv *priv) 7158c7bd5a4SBartosz Golaszewski { 7168c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->rx_ring; 7178c7bd5a4SBartosz Golaszewski 7188c7bd5a4SBartosz Golaszewski mtk_star_ring_free_skbs(priv, ring, mtk_star_dma_unmap_rx); 7198c7bd5a4SBartosz Golaszewski } 7208c7bd5a4SBartosz Golaszewski 7218c7bd5a4SBartosz Golaszewski static void mtk_star_free_tx_skbs(struct mtk_star_priv *priv) 7228c7bd5a4SBartosz Golaszewski { 7238c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 7248c7bd5a4SBartosz Golaszewski 7258c7bd5a4SBartosz Golaszewski mtk_star_ring_free_skbs(priv, ring, mtk_star_dma_unmap_tx); 7268c7bd5a4SBartosz Golaszewski } 7278c7bd5a4SBartosz Golaszewski 728adaff6d9SBartosz Golaszewski /* All processing for TX and RX happens in the napi poll callback. 729adaff6d9SBartosz Golaszewski * 730adaff6d9SBartosz Golaszewski * FIXME: The interrupt handling should be more fine-grained with each 731adaff6d9SBartosz Golaszewski * interrupt enabled/disabled independently when needed. Unfortunatly this 732adaff6d9SBartosz Golaszewski * turned out to impact the driver's stability and until we have something 733adaff6d9SBartosz Golaszewski * working properly, we're disabling all interrupts during TX & RX processing 734adaff6d9SBartosz Golaszewski * or when resetting the counter registers. 735adaff6d9SBartosz Golaszewski */ 7368c7bd5a4SBartosz Golaszewski static irqreturn_t mtk_star_handle_irq(int irq, void *data) 7378c7bd5a4SBartosz Golaszewski { 7388c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 7398c7bd5a4SBartosz Golaszewski struct net_device *ndev; 7408c7bd5a4SBartosz Golaszewski 7418c7bd5a4SBartosz Golaszewski ndev = data; 7428c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 7438c7bd5a4SBartosz Golaszewski 7448c7bd5a4SBartosz Golaszewski if (netif_running(ndev)) { 745adaff6d9SBartosz Golaszewski mtk_star_intr_disable(priv); 7468c7bd5a4SBartosz Golaszewski napi_schedule(&priv->napi); 7478c7bd5a4SBartosz Golaszewski } 7488c7bd5a4SBartosz Golaszewski 7498c7bd5a4SBartosz Golaszewski return IRQ_HANDLED; 7508c7bd5a4SBartosz Golaszewski } 7518c7bd5a4SBartosz Golaszewski 7528c7bd5a4SBartosz Golaszewski /* Wait for the completion of any previous command - CMD_START bit must be 7538c7bd5a4SBartosz Golaszewski * cleared by hardware. 7548c7bd5a4SBartosz Golaszewski */ 7558c7bd5a4SBartosz Golaszewski static int mtk_star_hash_wait_cmd_start(struct mtk_star_priv *priv) 7568c7bd5a4SBartosz Golaszewski { 7578c7bd5a4SBartosz Golaszewski unsigned int val; 7588c7bd5a4SBartosz Golaszewski 7598c7bd5a4SBartosz Golaszewski return regmap_read_poll_timeout_atomic(priv->regs, 7608c7bd5a4SBartosz Golaszewski MTK_STAR_REG_HASH_CTRL, val, 7618c7bd5a4SBartosz Golaszewski !(val & MTK_STAR_BIT_HASH_CTRL_CMD_START), 7628c7bd5a4SBartosz Golaszewski 10, MTK_STAR_WAIT_TIMEOUT); 7638c7bd5a4SBartosz Golaszewski } 7648c7bd5a4SBartosz Golaszewski 7658c7bd5a4SBartosz Golaszewski static int mtk_star_hash_wait_ok(struct mtk_star_priv *priv) 7668c7bd5a4SBartosz Golaszewski { 7678c7bd5a4SBartosz Golaszewski unsigned int val; 7688c7bd5a4SBartosz Golaszewski int ret; 7698c7bd5a4SBartosz Golaszewski 7708c7bd5a4SBartosz Golaszewski /* Wait for BIST_DONE bit. */ 7718c7bd5a4SBartosz Golaszewski ret = regmap_read_poll_timeout_atomic(priv->regs, 7728c7bd5a4SBartosz Golaszewski MTK_STAR_REG_HASH_CTRL, val, 7738c7bd5a4SBartosz Golaszewski val & MTK_STAR_BIT_HASH_CTRL_BIST_DONE, 7748c7bd5a4SBartosz Golaszewski 10, MTK_STAR_WAIT_TIMEOUT); 7758c7bd5a4SBartosz Golaszewski if (ret) 7768c7bd5a4SBartosz Golaszewski return ret; 7778c7bd5a4SBartosz Golaszewski 7788c7bd5a4SBartosz Golaszewski /* Check the BIST_OK bit. */ 779240f1ae4SBartosz Golaszewski if (!regmap_test_bits(priv->regs, MTK_STAR_REG_HASH_CTRL, 780240f1ae4SBartosz Golaszewski MTK_STAR_BIT_HASH_CTRL_BIST_OK)) 7818c7bd5a4SBartosz Golaszewski return -EIO; 7828c7bd5a4SBartosz Golaszewski 7838c7bd5a4SBartosz Golaszewski return 0; 7848c7bd5a4SBartosz Golaszewski } 7858c7bd5a4SBartosz Golaszewski 7868c7bd5a4SBartosz Golaszewski static int mtk_star_set_hashbit(struct mtk_star_priv *priv, 7878c7bd5a4SBartosz Golaszewski unsigned int hash_addr) 7888c7bd5a4SBartosz Golaszewski { 7898c7bd5a4SBartosz Golaszewski unsigned int val; 7908c7bd5a4SBartosz Golaszewski int ret; 7918c7bd5a4SBartosz Golaszewski 7928c7bd5a4SBartosz Golaszewski ret = mtk_star_hash_wait_cmd_start(priv); 7938c7bd5a4SBartosz Golaszewski if (ret) 7948c7bd5a4SBartosz Golaszewski return ret; 7958c7bd5a4SBartosz Golaszewski 7968c7bd5a4SBartosz Golaszewski val = hash_addr & MTK_STAR_MSK_HASH_CTRL_HASH_BIT_ADDR; 7978c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_ACC_CMD; 7988c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_CMD_START; 7998c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_BIST_EN; 8008c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_HASH_CTRL_HASH_BIT_DATA; 8018c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_HASH_CTRL, val); 8028c7bd5a4SBartosz Golaszewski 8038c7bd5a4SBartosz Golaszewski return mtk_star_hash_wait_ok(priv); 8048c7bd5a4SBartosz Golaszewski } 8058c7bd5a4SBartosz Golaszewski 8068c7bd5a4SBartosz Golaszewski static int mtk_star_reset_hash_table(struct mtk_star_priv *priv) 8078c7bd5a4SBartosz Golaszewski { 8088c7bd5a4SBartosz Golaszewski int ret; 8098c7bd5a4SBartosz Golaszewski 8108c7bd5a4SBartosz Golaszewski ret = mtk_star_hash_wait_cmd_start(priv); 8118c7bd5a4SBartosz Golaszewski if (ret) 8128c7bd5a4SBartosz Golaszewski return ret; 8138c7bd5a4SBartosz Golaszewski 814240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_HASH_CTRL, 8158c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_HASH_CTRL_BIST_EN); 816240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_TEST1, 8178c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_TEST1_RST_HASH_MBIST); 8188c7bd5a4SBartosz Golaszewski 8198c7bd5a4SBartosz Golaszewski return mtk_star_hash_wait_ok(priv); 8208c7bd5a4SBartosz Golaszewski } 8218c7bd5a4SBartosz Golaszewski 8228c7bd5a4SBartosz Golaszewski static void mtk_star_phy_config(struct mtk_star_priv *priv) 8238c7bd5a4SBartosz Golaszewski { 8248c7bd5a4SBartosz Golaszewski unsigned int val; 8258c7bd5a4SBartosz Golaszewski 8268c7bd5a4SBartosz Golaszewski if (priv->speed == SPEED_1000) 8278c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_1000M; 8288c7bd5a4SBartosz Golaszewski else if (priv->speed == SPEED_100) 8298c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_100M; 8308c7bd5a4SBartosz Golaszewski else 8318c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_10M; 8328c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_PHY_CTRL1_FORCE_SPD; 8338c7bd5a4SBartosz Golaszewski 8348c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_AN_EN; 8358c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_RX; 8368c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_TX; 8378c7bd5a4SBartosz Golaszewski /* Only full-duplex supported for now. */ 8388c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL1_FORCE_DPX; 8398c7bd5a4SBartosz Golaszewski 8408c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL1, val); 8418c7bd5a4SBartosz Golaszewski 8428c7bd5a4SBartosz Golaszewski if (priv->pause) { 8438c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_FC_CFG_SEND_PAUSE_TH_2K; 8448c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_FC_CFG_SEND_PAUSE_TH; 8458c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_FC_CFG_UC_PAUSE_DIR; 8468c7bd5a4SBartosz Golaszewski } else { 8478c7bd5a4SBartosz Golaszewski val = 0; 8488c7bd5a4SBartosz Golaszewski } 8498c7bd5a4SBartosz Golaszewski 8508c7bd5a4SBartosz Golaszewski regmap_update_bits(priv->regs, MTK_STAR_REG_FC_CFG, 8518c7bd5a4SBartosz Golaszewski MTK_STAR_MSK_FC_CFG_SEND_PAUSE_TH | 8528c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_FC_CFG_UC_PAUSE_DIR, val); 8538c7bd5a4SBartosz Golaszewski 8548c7bd5a4SBartosz Golaszewski if (priv->pause) { 8558c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_EXT_CFG_SND_PAUSE_RLS_1K; 8568c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_EXT_CFG_SND_PAUSE_RLS; 8578c7bd5a4SBartosz Golaszewski } else { 8588c7bd5a4SBartosz Golaszewski val = 0; 8598c7bd5a4SBartosz Golaszewski } 8608c7bd5a4SBartosz Golaszewski 8618c7bd5a4SBartosz Golaszewski regmap_update_bits(priv->regs, MTK_STAR_REG_EXT_CFG, 8628c7bd5a4SBartosz Golaszewski MTK_STAR_MSK_EXT_CFG_SND_PAUSE_RLS, val); 8638c7bd5a4SBartosz Golaszewski } 8648c7bd5a4SBartosz Golaszewski 8658c7bd5a4SBartosz Golaszewski static void mtk_star_adjust_link(struct net_device *ndev) 8668c7bd5a4SBartosz Golaszewski { 8678c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 8688c7bd5a4SBartosz Golaszewski struct phy_device *phydev = priv->phydev; 8698c7bd5a4SBartosz Golaszewski bool new_state = false; 8708c7bd5a4SBartosz Golaszewski 8718c7bd5a4SBartosz Golaszewski if (phydev->link) { 8728c7bd5a4SBartosz Golaszewski if (!priv->link) { 8738c7bd5a4SBartosz Golaszewski priv->link = phydev->link; 8748c7bd5a4SBartosz Golaszewski new_state = true; 8758c7bd5a4SBartosz Golaszewski } 8768c7bd5a4SBartosz Golaszewski 8778c7bd5a4SBartosz Golaszewski if (priv->speed != phydev->speed) { 8788c7bd5a4SBartosz Golaszewski priv->speed = phydev->speed; 8798c7bd5a4SBartosz Golaszewski new_state = true; 8808c7bd5a4SBartosz Golaszewski } 8818c7bd5a4SBartosz Golaszewski 8828c7bd5a4SBartosz Golaszewski if (priv->pause != phydev->pause) { 8838c7bd5a4SBartosz Golaszewski priv->pause = phydev->pause; 8848c7bd5a4SBartosz Golaszewski new_state = true; 8858c7bd5a4SBartosz Golaszewski } 8868c7bd5a4SBartosz Golaszewski } else { 8878c7bd5a4SBartosz Golaszewski if (priv->link) { 8888c7bd5a4SBartosz Golaszewski priv->link = phydev->link; 8898c7bd5a4SBartosz Golaszewski new_state = true; 8908c7bd5a4SBartosz Golaszewski } 8918c7bd5a4SBartosz Golaszewski } 8928c7bd5a4SBartosz Golaszewski 8938c7bd5a4SBartosz Golaszewski if (new_state) { 8948c7bd5a4SBartosz Golaszewski if (phydev->link) 8958c7bd5a4SBartosz Golaszewski mtk_star_phy_config(priv); 8968c7bd5a4SBartosz Golaszewski 8978c7bd5a4SBartosz Golaszewski phy_print_status(ndev->phydev); 8988c7bd5a4SBartosz Golaszewski } 8998c7bd5a4SBartosz Golaszewski } 9008c7bd5a4SBartosz Golaszewski 9018c7bd5a4SBartosz Golaszewski static void mtk_star_init_config(struct mtk_star_priv *priv) 9028c7bd5a4SBartosz Golaszewski { 9038c7bd5a4SBartosz Golaszewski unsigned int val; 9048c7bd5a4SBartosz Golaszewski 9058c7bd5a4SBartosz Golaszewski val = (MTK_STAR_BIT_MII_PAD_OUT_ENABLE | 9068c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_EXT_MDC_MODE | 9078c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_SWC_MII_MODE); 9088c7bd5a4SBartosz Golaszewski 9098c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_SYS_CONF, val); 9108c7bd5a4SBartosz Golaszewski regmap_update_bits(priv->regs, MTK_STAR_REG_MAC_CLK_CONF, 9118c7bd5a4SBartosz Golaszewski MTK_STAR_MSK_MAC_CLK_CONF, 912c16cc6a0SBiao Huang priv->compat_data->bit_clk_div); 9138c7bd5a4SBartosz Golaszewski } 9148c7bd5a4SBartosz Golaszewski 9158c7bd5a4SBartosz Golaszewski static int mtk_star_enable(struct net_device *ndev) 9168c7bd5a4SBartosz Golaszewski { 9178c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 9188c7bd5a4SBartosz Golaszewski unsigned int val; 9198c7bd5a4SBartosz Golaszewski int ret; 9208c7bd5a4SBartosz Golaszewski 9218c7bd5a4SBartosz Golaszewski mtk_star_nic_disable_pd(priv); 9228c7bd5a4SBartosz Golaszewski mtk_star_intr_disable(priv); 9238c7bd5a4SBartosz Golaszewski mtk_star_dma_stop(priv); 9248c7bd5a4SBartosz Golaszewski 9258c7bd5a4SBartosz Golaszewski mtk_star_set_mac_addr(ndev); 9268c7bd5a4SBartosz Golaszewski 9278c7bd5a4SBartosz Golaszewski /* Configure the MAC */ 9288c7bd5a4SBartosz Golaszewski val = MTK_STAR_VAL_MAC_CFG_IPG_96BIT; 9298c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_MAC_CFG_IPG; 9308c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_MAC_CFG_MAXLEN_1522; 9318c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_MAC_CFG_AUTO_PAD; 9328c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_MAC_CFG_CRC_STRIP; 9338c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_MAC_CFG, val); 9348c7bd5a4SBartosz Golaszewski 9358c7bd5a4SBartosz Golaszewski /* Enable Hash Table BIST and reset it */ 9368c7bd5a4SBartosz Golaszewski ret = mtk_star_reset_hash_table(priv); 9378c7bd5a4SBartosz Golaszewski if (ret) 9388c7bd5a4SBartosz Golaszewski return ret; 9398c7bd5a4SBartosz Golaszewski 9408c7bd5a4SBartosz Golaszewski /* Setup the hashing algorithm */ 941240f1ae4SBartosz Golaszewski regmap_clear_bits(priv->regs, MTK_STAR_REG_ARL_CFG, 9428c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_ARL_CFG_HASH_ALG | 943240f1ae4SBartosz Golaszewski MTK_STAR_BIT_ARL_CFG_MISC_MODE); 9448c7bd5a4SBartosz Golaszewski 9458c7bd5a4SBartosz Golaszewski /* Don't strip VLAN tags */ 946240f1ae4SBartosz Golaszewski regmap_clear_bits(priv->regs, MTK_STAR_REG_MAC_CFG, 947240f1ae4SBartosz Golaszewski MTK_STAR_BIT_MAC_CFG_VLAN_STRIP); 9488c7bd5a4SBartosz Golaszewski 9498c7bd5a4SBartosz Golaszewski /* Setup DMA */ 9508c7bd5a4SBartosz Golaszewski mtk_star_dma_init(priv); 9518c7bd5a4SBartosz Golaszewski 9528c7bd5a4SBartosz Golaszewski ret = mtk_star_prepare_rx_skbs(ndev); 9538c7bd5a4SBartosz Golaszewski if (ret) 9548c7bd5a4SBartosz Golaszewski goto err_out; 9558c7bd5a4SBartosz Golaszewski 9568c7bd5a4SBartosz Golaszewski /* Request the interrupt */ 9578c7bd5a4SBartosz Golaszewski ret = request_irq(ndev->irq, mtk_star_handle_irq, 9589ccbfdefSBiao Huang IRQF_TRIGGER_NONE, ndev->name, ndev); 9598c7bd5a4SBartosz Golaszewski if (ret) 9608c7bd5a4SBartosz Golaszewski goto err_free_skbs; 9618c7bd5a4SBartosz Golaszewski 9628c7bd5a4SBartosz Golaszewski napi_enable(&priv->napi); 9638c7bd5a4SBartosz Golaszewski 9648c7bd5a4SBartosz Golaszewski mtk_star_intr_ack_all(priv); 9658c7bd5a4SBartosz Golaszewski mtk_star_intr_enable(priv); 9668c7bd5a4SBartosz Golaszewski 9678c7bd5a4SBartosz Golaszewski /* Connect to and start PHY */ 9688c7bd5a4SBartosz Golaszewski priv->phydev = of_phy_connect(ndev, priv->phy_node, 9698c7bd5a4SBartosz Golaszewski mtk_star_adjust_link, 0, priv->phy_intf); 9708c7bd5a4SBartosz Golaszewski if (!priv->phydev) { 9718c7bd5a4SBartosz Golaszewski netdev_err(ndev, "failed to connect to PHY\n"); 972baee1991SZhang Changzhong ret = -ENODEV; 9738c7bd5a4SBartosz Golaszewski goto err_free_irq; 9748c7bd5a4SBartosz Golaszewski } 9758c7bd5a4SBartosz Golaszewski 9768c7bd5a4SBartosz Golaszewski mtk_star_dma_start(priv); 9778c7bd5a4SBartosz Golaszewski phy_start(priv->phydev); 9788c7bd5a4SBartosz Golaszewski netif_start_queue(ndev); 9798c7bd5a4SBartosz Golaszewski 9808c7bd5a4SBartosz Golaszewski return 0; 9818c7bd5a4SBartosz Golaszewski 9828c7bd5a4SBartosz Golaszewski err_free_irq: 9838c7bd5a4SBartosz Golaszewski free_irq(ndev->irq, ndev); 9848c7bd5a4SBartosz Golaszewski err_free_skbs: 9858c7bd5a4SBartosz Golaszewski mtk_star_free_rx_skbs(priv); 9868c7bd5a4SBartosz Golaszewski err_out: 9878c7bd5a4SBartosz Golaszewski return ret; 9888c7bd5a4SBartosz Golaszewski } 9898c7bd5a4SBartosz Golaszewski 9908c7bd5a4SBartosz Golaszewski static void mtk_star_disable(struct net_device *ndev) 9918c7bd5a4SBartosz Golaszewski { 9928c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 9938c7bd5a4SBartosz Golaszewski 9948c7bd5a4SBartosz Golaszewski netif_stop_queue(ndev); 9958c7bd5a4SBartosz Golaszewski napi_disable(&priv->napi); 9968c7bd5a4SBartosz Golaszewski mtk_star_intr_disable(priv); 9978c7bd5a4SBartosz Golaszewski mtk_star_dma_disable(priv); 9988c7bd5a4SBartosz Golaszewski mtk_star_intr_ack_all(priv); 9998c7bd5a4SBartosz Golaszewski phy_stop(priv->phydev); 10008c7bd5a4SBartosz Golaszewski phy_disconnect(priv->phydev); 10018c7bd5a4SBartosz Golaszewski free_irq(ndev->irq, ndev); 10028c7bd5a4SBartosz Golaszewski mtk_star_free_rx_skbs(priv); 10038c7bd5a4SBartosz Golaszewski mtk_star_free_tx_skbs(priv); 10048c7bd5a4SBartosz Golaszewski } 10058c7bd5a4SBartosz Golaszewski 10068c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_open(struct net_device *ndev) 10078c7bd5a4SBartosz Golaszewski { 10088c7bd5a4SBartosz Golaszewski return mtk_star_enable(ndev); 10098c7bd5a4SBartosz Golaszewski } 10108c7bd5a4SBartosz Golaszewski 10118c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_stop(struct net_device *ndev) 10128c7bd5a4SBartosz Golaszewski { 10138c7bd5a4SBartosz Golaszewski mtk_star_disable(ndev); 10148c7bd5a4SBartosz Golaszewski 10158c7bd5a4SBartosz Golaszewski return 0; 10168c7bd5a4SBartosz Golaszewski } 10178c7bd5a4SBartosz Golaszewski 10188c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_ioctl(struct net_device *ndev, 10198c7bd5a4SBartosz Golaszewski struct ifreq *req, int cmd) 10208c7bd5a4SBartosz Golaszewski { 10218c7bd5a4SBartosz Golaszewski if (!netif_running(ndev)) 10228c7bd5a4SBartosz Golaszewski return -EINVAL; 10238c7bd5a4SBartosz Golaszewski 10248c7bd5a4SBartosz Golaszewski return phy_mii_ioctl(ndev->phydev, req, cmd); 10258c7bd5a4SBartosz Golaszewski } 10268c7bd5a4SBartosz Golaszewski 10278c7bd5a4SBartosz Golaszewski static int mtk_star_netdev_start_xmit(struct sk_buff *skb, 10288c7bd5a4SBartosz Golaszewski struct net_device *ndev) 10298c7bd5a4SBartosz Golaszewski { 10308c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 10318c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 10328c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 10338c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 10348c7bd5a4SBartosz Golaszewski 10358c7bd5a4SBartosz Golaszewski desc_data.dma_addr = mtk_star_dma_map_tx(priv, skb); 10368c7bd5a4SBartosz Golaszewski if (dma_mapping_error(dev, desc_data.dma_addr)) 10378c7bd5a4SBartosz Golaszewski goto err_drop_packet; 10388c7bd5a4SBartosz Golaszewski 10398c7bd5a4SBartosz Golaszewski desc_data.skb = skb; 10408c7bd5a4SBartosz Golaszewski desc_data.len = skb->len; 10418c7bd5a4SBartosz Golaszewski 10428c7bd5a4SBartosz Golaszewski spin_lock_bh(&priv->lock); 10438c7bd5a4SBartosz Golaszewski 10448c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_tx(ring, &desc_data); 10458c7bd5a4SBartosz Golaszewski 10468c7bd5a4SBartosz Golaszewski netdev_sent_queue(ndev, skb->len); 10478c7bd5a4SBartosz Golaszewski 10488c7bd5a4SBartosz Golaszewski if (mtk_star_ring_full(ring)) 10498c7bd5a4SBartosz Golaszewski netif_stop_queue(ndev); 10508c7bd5a4SBartosz Golaszewski 10518c7bd5a4SBartosz Golaszewski spin_unlock_bh(&priv->lock); 10528c7bd5a4SBartosz Golaszewski 10538c7bd5a4SBartosz Golaszewski mtk_star_dma_resume_tx(priv); 10548c7bd5a4SBartosz Golaszewski 10558c7bd5a4SBartosz Golaszewski return NETDEV_TX_OK; 10568c7bd5a4SBartosz Golaszewski 10578c7bd5a4SBartosz Golaszewski err_drop_packet: 10588c7bd5a4SBartosz Golaszewski dev_kfree_skb(skb); 10598c7bd5a4SBartosz Golaszewski ndev->stats.tx_dropped++; 1060e8aa6d52SVincent Stehlé return NETDEV_TX_OK; 10618c7bd5a4SBartosz Golaszewski } 10628c7bd5a4SBartosz Golaszewski 10638c7bd5a4SBartosz Golaszewski /* Returns the number of bytes sent or a negative number on the first 10648c7bd5a4SBartosz Golaszewski * descriptor owned by DMA. 10658c7bd5a4SBartosz Golaszewski */ 10668c7bd5a4SBartosz Golaszewski static int mtk_star_tx_complete_one(struct mtk_star_priv *priv) 10678c7bd5a4SBartosz Golaszewski { 10688c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 10698c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 10708c7bd5a4SBartosz Golaszewski int ret; 10718c7bd5a4SBartosz Golaszewski 10728c7bd5a4SBartosz Golaszewski ret = mtk_star_ring_pop_tail(ring, &desc_data); 10738c7bd5a4SBartosz Golaszewski if (ret) 10748c7bd5a4SBartosz Golaszewski return ret; 10758c7bd5a4SBartosz Golaszewski 10768c7bd5a4SBartosz Golaszewski mtk_star_dma_unmap_tx(priv, &desc_data); 10778c7bd5a4SBartosz Golaszewski ret = desc_data.skb->len; 10788c7bd5a4SBartosz Golaszewski dev_kfree_skb_irq(desc_data.skb); 10798c7bd5a4SBartosz Golaszewski 10808c7bd5a4SBartosz Golaszewski return ret; 10818c7bd5a4SBartosz Golaszewski } 10828c7bd5a4SBartosz Golaszewski 10838c7bd5a4SBartosz Golaszewski static void mtk_star_tx_complete_all(struct mtk_star_priv *priv) 10848c7bd5a4SBartosz Golaszewski { 10858c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->tx_ring; 10868c7bd5a4SBartosz Golaszewski struct net_device *ndev = priv->ndev; 10878c7bd5a4SBartosz Golaszewski int ret, pkts_compl, bytes_compl; 10888c7bd5a4SBartosz Golaszewski bool wake = false; 10898c7bd5a4SBartosz Golaszewski 10908c7bd5a4SBartosz Golaszewski spin_lock(&priv->lock); 10918c7bd5a4SBartosz Golaszewski 10928c7bd5a4SBartosz Golaszewski for (pkts_compl = 0, bytes_compl = 0;; 10938c7bd5a4SBartosz Golaszewski pkts_compl++, bytes_compl += ret, wake = true) { 10948c7bd5a4SBartosz Golaszewski if (!mtk_star_ring_descs_available(ring)) 10958c7bd5a4SBartosz Golaszewski break; 10968c7bd5a4SBartosz Golaszewski 10978c7bd5a4SBartosz Golaszewski ret = mtk_star_tx_complete_one(priv); 10988c7bd5a4SBartosz Golaszewski if (ret < 0) 10998c7bd5a4SBartosz Golaszewski break; 11008c7bd5a4SBartosz Golaszewski } 11018c7bd5a4SBartosz Golaszewski 11028c7bd5a4SBartosz Golaszewski netdev_completed_queue(ndev, pkts_compl, bytes_compl); 11038c7bd5a4SBartosz Golaszewski 11048c7bd5a4SBartosz Golaszewski if (wake && netif_queue_stopped(ndev)) 11058c7bd5a4SBartosz Golaszewski netif_wake_queue(ndev); 11068c7bd5a4SBartosz Golaszewski 11078c7bd5a4SBartosz Golaszewski spin_unlock(&priv->lock); 11088c7bd5a4SBartosz Golaszewski } 11098c7bd5a4SBartosz Golaszewski 11108c7bd5a4SBartosz Golaszewski static void mtk_star_netdev_get_stats64(struct net_device *ndev, 11118c7bd5a4SBartosz Golaszewski struct rtnl_link_stats64 *stats) 11128c7bd5a4SBartosz Golaszewski { 11138c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 11148c7bd5a4SBartosz Golaszewski 11158c7bd5a4SBartosz Golaszewski mtk_star_update_stats(priv); 11168c7bd5a4SBartosz Golaszewski 11178c7bd5a4SBartosz Golaszewski memcpy(stats, &priv->stats, sizeof(*stats)); 11188c7bd5a4SBartosz Golaszewski } 11198c7bd5a4SBartosz Golaszewski 11208c7bd5a4SBartosz Golaszewski static void mtk_star_set_rx_mode(struct net_device *ndev) 11218c7bd5a4SBartosz Golaszewski { 11228c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 11238c7bd5a4SBartosz Golaszewski struct netdev_hw_addr *hw_addr; 11248c7bd5a4SBartosz Golaszewski unsigned int hash_addr, i; 11258c7bd5a4SBartosz Golaszewski int ret; 11268c7bd5a4SBartosz Golaszewski 11278c7bd5a4SBartosz Golaszewski if (ndev->flags & IFF_PROMISC) { 1128240f1ae4SBartosz Golaszewski regmap_set_bits(priv->regs, MTK_STAR_REG_ARL_CFG, 11298c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_ARL_CFG_MISC_MODE); 11308c7bd5a4SBartosz Golaszewski } else if (netdev_mc_count(ndev) > MTK_STAR_HASHTABLE_MC_LIMIT || 11318c7bd5a4SBartosz Golaszewski ndev->flags & IFF_ALLMULTI) { 11328c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_HASHTABLE_SIZE_MAX; i++) { 11338c7bd5a4SBartosz Golaszewski ret = mtk_star_set_hashbit(priv, i); 11348c7bd5a4SBartosz Golaszewski if (ret) 11358c7bd5a4SBartosz Golaszewski goto hash_fail; 11368c7bd5a4SBartosz Golaszewski } 11378c7bd5a4SBartosz Golaszewski } else { 11388c7bd5a4SBartosz Golaszewski /* Clear previous settings. */ 11398c7bd5a4SBartosz Golaszewski ret = mtk_star_reset_hash_table(priv); 11408c7bd5a4SBartosz Golaszewski if (ret) 11418c7bd5a4SBartosz Golaszewski goto hash_fail; 11428c7bd5a4SBartosz Golaszewski 11438c7bd5a4SBartosz Golaszewski netdev_for_each_mc_addr(hw_addr, ndev) { 11448c7bd5a4SBartosz Golaszewski hash_addr = (hw_addr->addr[0] & 0x01) << 8; 11458c7bd5a4SBartosz Golaszewski hash_addr += hw_addr->addr[5]; 11468c7bd5a4SBartosz Golaszewski ret = mtk_star_set_hashbit(priv, hash_addr); 11478c7bd5a4SBartosz Golaszewski if (ret) 11488c7bd5a4SBartosz Golaszewski goto hash_fail; 11498c7bd5a4SBartosz Golaszewski } 11508c7bd5a4SBartosz Golaszewski } 11518c7bd5a4SBartosz Golaszewski 11528c7bd5a4SBartosz Golaszewski return; 11538c7bd5a4SBartosz Golaszewski 11548c7bd5a4SBartosz Golaszewski hash_fail: 11558c7bd5a4SBartosz Golaszewski if (ret == -ETIMEDOUT) 11568c7bd5a4SBartosz Golaszewski netdev_err(ndev, "setting hash bit timed out\n"); 11578c7bd5a4SBartosz Golaszewski else 11588c7bd5a4SBartosz Golaszewski /* Should be -EIO */ 11598c7bd5a4SBartosz Golaszewski netdev_err(ndev, "unable to set hash bit"); 11608c7bd5a4SBartosz Golaszewski } 11618c7bd5a4SBartosz Golaszewski 11628c7bd5a4SBartosz Golaszewski static const struct net_device_ops mtk_star_netdev_ops = { 11638c7bd5a4SBartosz Golaszewski .ndo_open = mtk_star_netdev_open, 11648c7bd5a4SBartosz Golaszewski .ndo_stop = mtk_star_netdev_stop, 11658c7bd5a4SBartosz Golaszewski .ndo_start_xmit = mtk_star_netdev_start_xmit, 11668c7bd5a4SBartosz Golaszewski .ndo_get_stats64 = mtk_star_netdev_get_stats64, 11678c7bd5a4SBartosz Golaszewski .ndo_set_rx_mode = mtk_star_set_rx_mode, 1168a7605370SArnd Bergmann .ndo_eth_ioctl = mtk_star_netdev_ioctl, 11698c7bd5a4SBartosz Golaszewski .ndo_set_mac_address = eth_mac_addr, 11708c7bd5a4SBartosz Golaszewski .ndo_validate_addr = eth_validate_addr, 11718c7bd5a4SBartosz Golaszewski }; 11728c7bd5a4SBartosz Golaszewski 11738c7bd5a4SBartosz Golaszewski static void mtk_star_get_drvinfo(struct net_device *dev, 11748c7bd5a4SBartosz Golaszewski struct ethtool_drvinfo *info) 11758c7bd5a4SBartosz Golaszewski { 11768c7bd5a4SBartosz Golaszewski strlcpy(info->driver, MTK_STAR_DRVNAME, sizeof(info->driver)); 11778c7bd5a4SBartosz Golaszewski } 11788c7bd5a4SBartosz Golaszewski 11798c7bd5a4SBartosz Golaszewski /* TODO Add ethtool stats. */ 11808c7bd5a4SBartosz Golaszewski static const struct ethtool_ops mtk_star_ethtool_ops = { 11818c7bd5a4SBartosz Golaszewski .get_drvinfo = mtk_star_get_drvinfo, 11828c7bd5a4SBartosz Golaszewski .get_link = ethtool_op_get_link, 11838c7bd5a4SBartosz Golaszewski .get_link_ksettings = phy_ethtool_get_link_ksettings, 11848c7bd5a4SBartosz Golaszewski .set_link_ksettings = phy_ethtool_set_link_ksettings, 11858c7bd5a4SBartosz Golaszewski }; 11868c7bd5a4SBartosz Golaszewski 11878c7bd5a4SBartosz Golaszewski static int mtk_star_receive_packet(struct mtk_star_priv *priv) 11888c7bd5a4SBartosz Golaszewski { 11898c7bd5a4SBartosz Golaszewski struct mtk_star_ring *ring = &priv->rx_ring; 11908c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 11918c7bd5a4SBartosz Golaszewski struct mtk_star_ring_desc_data desc_data; 11928c7bd5a4SBartosz Golaszewski struct net_device *ndev = priv->ndev; 11938c7bd5a4SBartosz Golaszewski struct sk_buff *curr_skb, *new_skb; 11948c7bd5a4SBartosz Golaszewski dma_addr_t new_dma_addr; 11958c7bd5a4SBartosz Golaszewski int ret; 11968c7bd5a4SBartosz Golaszewski 11978c7bd5a4SBartosz Golaszewski spin_lock(&priv->lock); 11988c7bd5a4SBartosz Golaszewski ret = mtk_star_ring_pop_tail(ring, &desc_data); 11998c7bd5a4SBartosz Golaszewski spin_unlock(&priv->lock); 12008c7bd5a4SBartosz Golaszewski if (ret) 12018c7bd5a4SBartosz Golaszewski return -1; 12028c7bd5a4SBartosz Golaszewski 12038c7bd5a4SBartosz Golaszewski curr_skb = desc_data.skb; 12048c7bd5a4SBartosz Golaszewski 12058c7bd5a4SBartosz Golaszewski if ((desc_data.flags & MTK_STAR_DESC_BIT_RX_CRCE) || 12068c7bd5a4SBartosz Golaszewski (desc_data.flags & MTK_STAR_DESC_BIT_RX_OSIZE)) { 12078c7bd5a4SBartosz Golaszewski /* Error packet -> drop and reuse skb. */ 12088c7bd5a4SBartosz Golaszewski new_skb = curr_skb; 12098c7bd5a4SBartosz Golaszewski goto push_new_skb; 12108c7bd5a4SBartosz Golaszewski } 12118c7bd5a4SBartosz Golaszewski 12128c7bd5a4SBartosz Golaszewski /* Prepare new skb before receiving the current one. Reuse the current 12138c7bd5a4SBartosz Golaszewski * skb if we fail at any point. 12148c7bd5a4SBartosz Golaszewski */ 12158c7bd5a4SBartosz Golaszewski new_skb = mtk_star_alloc_skb(ndev); 12168c7bd5a4SBartosz Golaszewski if (!new_skb) { 12178c7bd5a4SBartosz Golaszewski ndev->stats.rx_dropped++; 12188c7bd5a4SBartosz Golaszewski new_skb = curr_skb; 12198c7bd5a4SBartosz Golaszewski goto push_new_skb; 12208c7bd5a4SBartosz Golaszewski } 12218c7bd5a4SBartosz Golaszewski 12228c7bd5a4SBartosz Golaszewski new_dma_addr = mtk_star_dma_map_rx(priv, new_skb); 12238c7bd5a4SBartosz Golaszewski if (dma_mapping_error(dev, new_dma_addr)) { 12248c7bd5a4SBartosz Golaszewski ndev->stats.rx_dropped++; 12258c7bd5a4SBartosz Golaszewski dev_kfree_skb(new_skb); 12268c7bd5a4SBartosz Golaszewski new_skb = curr_skb; 12278c7bd5a4SBartosz Golaszewski netdev_err(ndev, "DMA mapping error of RX descriptor\n"); 12288c7bd5a4SBartosz Golaszewski goto push_new_skb; 12298c7bd5a4SBartosz Golaszewski } 12308c7bd5a4SBartosz Golaszewski 12318c7bd5a4SBartosz Golaszewski /* We can't fail anymore at this point: it's safe to unmap the skb. */ 12328c7bd5a4SBartosz Golaszewski mtk_star_dma_unmap_rx(priv, &desc_data); 12338c7bd5a4SBartosz Golaszewski 12348c7bd5a4SBartosz Golaszewski skb_put(desc_data.skb, desc_data.len); 12358c7bd5a4SBartosz Golaszewski desc_data.skb->ip_summed = CHECKSUM_NONE; 12368c7bd5a4SBartosz Golaszewski desc_data.skb->protocol = eth_type_trans(desc_data.skb, ndev); 12378c7bd5a4SBartosz Golaszewski desc_data.skb->dev = ndev; 12388c7bd5a4SBartosz Golaszewski netif_receive_skb(desc_data.skb); 12398c7bd5a4SBartosz Golaszewski 124095b39f07SBiao Huang /* update dma_addr for new skb */ 124195b39f07SBiao Huang desc_data.dma_addr = new_dma_addr; 124295b39f07SBiao Huang 12438c7bd5a4SBartosz Golaszewski push_new_skb: 12448c7bd5a4SBartosz Golaszewski desc_data.len = skb_tailroom(new_skb); 12458c7bd5a4SBartosz Golaszewski desc_data.skb = new_skb; 12468c7bd5a4SBartosz Golaszewski 12478c7bd5a4SBartosz Golaszewski spin_lock(&priv->lock); 12488c7bd5a4SBartosz Golaszewski mtk_star_ring_push_head_rx(ring, &desc_data); 12498c7bd5a4SBartosz Golaszewski spin_unlock(&priv->lock); 12508c7bd5a4SBartosz Golaszewski 12518c7bd5a4SBartosz Golaszewski return 0; 12528c7bd5a4SBartosz Golaszewski } 12538c7bd5a4SBartosz Golaszewski 12548c7bd5a4SBartosz Golaszewski static int mtk_star_process_rx(struct mtk_star_priv *priv, int budget) 12558c7bd5a4SBartosz Golaszewski { 12568c7bd5a4SBartosz Golaszewski int received, ret; 12578c7bd5a4SBartosz Golaszewski 12588c7bd5a4SBartosz Golaszewski for (received = 0, ret = 0; received < budget && ret == 0; received++) 12598c7bd5a4SBartosz Golaszewski ret = mtk_star_receive_packet(priv); 12608c7bd5a4SBartosz Golaszewski 12618c7bd5a4SBartosz Golaszewski mtk_star_dma_resume_rx(priv); 12628c7bd5a4SBartosz Golaszewski 12638c7bd5a4SBartosz Golaszewski return received; 12648c7bd5a4SBartosz Golaszewski } 12658c7bd5a4SBartosz Golaszewski 12668c7bd5a4SBartosz Golaszewski static int mtk_star_poll(struct napi_struct *napi, int budget) 12678c7bd5a4SBartosz Golaszewski { 12688c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 1269adaff6d9SBartosz Golaszewski unsigned int status; 12708c7bd5a4SBartosz Golaszewski int received = 0; 12718c7bd5a4SBartosz Golaszewski 12728c7bd5a4SBartosz Golaszewski priv = container_of(napi, struct mtk_star_priv, napi); 12738c7bd5a4SBartosz Golaszewski 1274adaff6d9SBartosz Golaszewski status = mtk_star_intr_read(priv); 1275adaff6d9SBartosz Golaszewski mtk_star_intr_ack_all(priv); 1276adaff6d9SBartosz Golaszewski 1277adaff6d9SBartosz Golaszewski if (status & MTK_STAR_BIT_INT_STS_TNTC) 12788c7bd5a4SBartosz Golaszewski /* Clean-up all TX descriptors. */ 12798c7bd5a4SBartosz Golaszewski mtk_star_tx_complete_all(priv); 1280adaff6d9SBartosz Golaszewski 1281adaff6d9SBartosz Golaszewski if (status & MTK_STAR_BIT_INT_STS_FNRC) 12828c7bd5a4SBartosz Golaszewski /* Receive up to $budget packets. */ 12838c7bd5a4SBartosz Golaszewski received = mtk_star_process_rx(priv, budget); 12848c7bd5a4SBartosz Golaszewski 1285adaff6d9SBartosz Golaszewski if (unlikely(status & MTK_STAR_REG_INT_STS_MIB_CNT_TH)) { 1286adaff6d9SBartosz Golaszewski mtk_star_update_stats(priv); 1287adaff6d9SBartosz Golaszewski mtk_star_reset_counters(priv); 12888c7bd5a4SBartosz Golaszewski } 12898c7bd5a4SBartosz Golaszewski 1290adaff6d9SBartosz Golaszewski if (received < budget) 1291adaff6d9SBartosz Golaszewski napi_complete_done(napi, received); 1292adaff6d9SBartosz Golaszewski 1293adaff6d9SBartosz Golaszewski mtk_star_intr_enable(priv); 1294adaff6d9SBartosz Golaszewski 12958c7bd5a4SBartosz Golaszewski return received; 12968c7bd5a4SBartosz Golaszewski } 12978c7bd5a4SBartosz Golaszewski 12988c7bd5a4SBartosz Golaszewski static void mtk_star_mdio_rwok_clear(struct mtk_star_priv *priv) 12998c7bd5a4SBartosz Golaszewski { 13008c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL0, 13018c7bd5a4SBartosz Golaszewski MTK_STAR_BIT_PHY_CTRL0_RWOK); 13028c7bd5a4SBartosz Golaszewski } 13038c7bd5a4SBartosz Golaszewski 13048c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_rwok_wait(struct mtk_star_priv *priv) 13058c7bd5a4SBartosz Golaszewski { 13068c7bd5a4SBartosz Golaszewski unsigned int val; 13078c7bd5a4SBartosz Golaszewski 13088c7bd5a4SBartosz Golaszewski return regmap_read_poll_timeout(priv->regs, MTK_STAR_REG_PHY_CTRL0, 13098c7bd5a4SBartosz Golaszewski val, val & MTK_STAR_BIT_PHY_CTRL0_RWOK, 13108c7bd5a4SBartosz Golaszewski 10, MTK_STAR_WAIT_TIMEOUT); 13118c7bd5a4SBartosz Golaszewski } 13128c7bd5a4SBartosz Golaszewski 13138c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_read(struct mii_bus *mii, int phy_id, int regnum) 13148c7bd5a4SBartosz Golaszewski { 13158c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = mii->priv; 13168c7bd5a4SBartosz Golaszewski unsigned int val, data; 13178c7bd5a4SBartosz Golaszewski int ret; 13188c7bd5a4SBartosz Golaszewski 13198c7bd5a4SBartosz Golaszewski if (regnum & MII_ADDR_C45) 13208c7bd5a4SBartosz Golaszewski return -EOPNOTSUPP; 13218c7bd5a4SBartosz Golaszewski 13228c7bd5a4SBartosz Golaszewski mtk_star_mdio_rwok_clear(priv); 13238c7bd5a4SBartosz Golaszewski 13248c7bd5a4SBartosz Golaszewski val = (regnum << MTK_STAR_OFF_PHY_CTRL0_PREG); 13258c7bd5a4SBartosz Golaszewski val &= MTK_STAR_MSK_PHY_CTRL0_PREG; 13268c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL0_RDCMD; 13278c7bd5a4SBartosz Golaszewski 13288c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL0, val); 13298c7bd5a4SBartosz Golaszewski 13308c7bd5a4SBartosz Golaszewski ret = mtk_star_mdio_rwok_wait(priv); 13318c7bd5a4SBartosz Golaszewski if (ret) 13328c7bd5a4SBartosz Golaszewski return ret; 13338c7bd5a4SBartosz Golaszewski 13348c7bd5a4SBartosz Golaszewski regmap_read(priv->regs, MTK_STAR_REG_PHY_CTRL0, &data); 13358c7bd5a4SBartosz Golaszewski 13368c7bd5a4SBartosz Golaszewski data &= MTK_STAR_MSK_PHY_CTRL0_RWDATA; 13378c7bd5a4SBartosz Golaszewski data >>= MTK_STAR_OFF_PHY_CTRL0_RWDATA; 13388c7bd5a4SBartosz Golaszewski 13398c7bd5a4SBartosz Golaszewski return data; 13408c7bd5a4SBartosz Golaszewski } 13418c7bd5a4SBartosz Golaszewski 13428c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_write(struct mii_bus *mii, int phy_id, 13438c7bd5a4SBartosz Golaszewski int regnum, u16 data) 13448c7bd5a4SBartosz Golaszewski { 13458c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = mii->priv; 13468c7bd5a4SBartosz Golaszewski unsigned int val; 13478c7bd5a4SBartosz Golaszewski 13488c7bd5a4SBartosz Golaszewski if (regnum & MII_ADDR_C45) 13498c7bd5a4SBartosz Golaszewski return -EOPNOTSUPP; 13508c7bd5a4SBartosz Golaszewski 13518c7bd5a4SBartosz Golaszewski mtk_star_mdio_rwok_clear(priv); 13528c7bd5a4SBartosz Golaszewski 13538c7bd5a4SBartosz Golaszewski val = data; 13548c7bd5a4SBartosz Golaszewski val <<= MTK_STAR_OFF_PHY_CTRL0_RWDATA; 13558c7bd5a4SBartosz Golaszewski val &= MTK_STAR_MSK_PHY_CTRL0_RWDATA; 13568c7bd5a4SBartosz Golaszewski regnum <<= MTK_STAR_OFF_PHY_CTRL0_PREG; 13578c7bd5a4SBartosz Golaszewski regnum &= MTK_STAR_MSK_PHY_CTRL0_PREG; 13588c7bd5a4SBartosz Golaszewski val |= regnum; 13598c7bd5a4SBartosz Golaszewski val |= MTK_STAR_BIT_PHY_CTRL0_WTCMD; 13608c7bd5a4SBartosz Golaszewski 13618c7bd5a4SBartosz Golaszewski regmap_write(priv->regs, MTK_STAR_REG_PHY_CTRL0, val); 13628c7bd5a4SBartosz Golaszewski 13638c7bd5a4SBartosz Golaszewski return mtk_star_mdio_rwok_wait(priv); 13648c7bd5a4SBartosz Golaszewski } 13658c7bd5a4SBartosz Golaszewski 13668c7bd5a4SBartosz Golaszewski static int mtk_star_mdio_init(struct net_device *ndev) 13678c7bd5a4SBartosz Golaszewski { 13688c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = netdev_priv(ndev); 13698c7bd5a4SBartosz Golaszewski struct device *dev = mtk_star_get_dev(priv); 13708c7bd5a4SBartosz Golaszewski struct device_node *of_node, *mdio_node; 13718c7bd5a4SBartosz Golaszewski int ret; 13728c7bd5a4SBartosz Golaszewski 13738c7bd5a4SBartosz Golaszewski of_node = dev->of_node; 13748c7bd5a4SBartosz Golaszewski 13758c7bd5a4SBartosz Golaszewski mdio_node = of_get_child_by_name(of_node, "mdio"); 13768c7bd5a4SBartosz Golaszewski if (!mdio_node) 13778c7bd5a4SBartosz Golaszewski return -ENODEV; 13788c7bd5a4SBartosz Golaszewski 13798c7bd5a4SBartosz Golaszewski if (!of_device_is_available(mdio_node)) { 13808c7bd5a4SBartosz Golaszewski ret = -ENODEV; 13818c7bd5a4SBartosz Golaszewski goto out_put_node; 13828c7bd5a4SBartosz Golaszewski } 13838c7bd5a4SBartosz Golaszewski 13848c7bd5a4SBartosz Golaszewski priv->mii = devm_mdiobus_alloc(dev); 13858c7bd5a4SBartosz Golaszewski if (!priv->mii) { 13868c7bd5a4SBartosz Golaszewski ret = -ENOMEM; 13878c7bd5a4SBartosz Golaszewski goto out_put_node; 13888c7bd5a4SBartosz Golaszewski } 13898c7bd5a4SBartosz Golaszewski 13908c7bd5a4SBartosz Golaszewski snprintf(priv->mii->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); 13918c7bd5a4SBartosz Golaszewski priv->mii->name = "mtk-mac-mdio"; 13928c7bd5a4SBartosz Golaszewski priv->mii->parent = dev; 13938c7bd5a4SBartosz Golaszewski priv->mii->read = mtk_star_mdio_read; 13948c7bd5a4SBartosz Golaszewski priv->mii->write = mtk_star_mdio_write; 13958c7bd5a4SBartosz Golaszewski priv->mii->priv = priv; 13968c7bd5a4SBartosz Golaszewski 13979ed0a3faSBartosz Golaszewski ret = devm_of_mdiobus_register(dev, priv->mii, mdio_node); 13988c7bd5a4SBartosz Golaszewski 13998c7bd5a4SBartosz Golaszewski out_put_node: 14008c7bd5a4SBartosz Golaszewski of_node_put(mdio_node); 14018c7bd5a4SBartosz Golaszewski return ret; 14028c7bd5a4SBartosz Golaszewski } 14038c7bd5a4SBartosz Golaszewski 1404f99c0646SArnd Bergmann static __maybe_unused int mtk_star_suspend(struct device *dev) 14058c7bd5a4SBartosz Golaszewski { 14068c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 14078c7bd5a4SBartosz Golaszewski struct net_device *ndev; 14088c7bd5a4SBartosz Golaszewski 14098c7bd5a4SBartosz Golaszewski ndev = dev_get_drvdata(dev); 14108c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 14118c7bd5a4SBartosz Golaszewski 14128c7bd5a4SBartosz Golaszewski if (netif_running(ndev)) 14138c7bd5a4SBartosz Golaszewski mtk_star_disable(ndev); 14148c7bd5a4SBartosz Golaszewski 14158c7bd5a4SBartosz Golaszewski clk_bulk_disable_unprepare(MTK_STAR_NCLKS, priv->clks); 14168c7bd5a4SBartosz Golaszewski 14178c7bd5a4SBartosz Golaszewski return 0; 14188c7bd5a4SBartosz Golaszewski } 14198c7bd5a4SBartosz Golaszewski 1420f99c0646SArnd Bergmann static __maybe_unused int mtk_star_resume(struct device *dev) 14218c7bd5a4SBartosz Golaszewski { 14228c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 14238c7bd5a4SBartosz Golaszewski struct net_device *ndev; 14248c7bd5a4SBartosz Golaszewski int ret; 14258c7bd5a4SBartosz Golaszewski 14268c7bd5a4SBartosz Golaszewski ndev = dev_get_drvdata(dev); 14278c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 14288c7bd5a4SBartosz Golaszewski 14298c7bd5a4SBartosz Golaszewski ret = clk_bulk_prepare_enable(MTK_STAR_NCLKS, priv->clks); 14308c7bd5a4SBartosz Golaszewski if (ret) 14318c7bd5a4SBartosz Golaszewski return ret; 14328c7bd5a4SBartosz Golaszewski 14338c7bd5a4SBartosz Golaszewski if (netif_running(ndev)) { 14348c7bd5a4SBartosz Golaszewski ret = mtk_star_enable(ndev); 14358c7bd5a4SBartosz Golaszewski if (ret) 14368c7bd5a4SBartosz Golaszewski clk_bulk_disable_unprepare(MTK_STAR_NCLKS, priv->clks); 14378c7bd5a4SBartosz Golaszewski } 14388c7bd5a4SBartosz Golaszewski 14398c7bd5a4SBartosz Golaszewski return ret; 14408c7bd5a4SBartosz Golaszewski } 14418c7bd5a4SBartosz Golaszewski 14428c7bd5a4SBartosz Golaszewski static void mtk_star_clk_disable_unprepare(void *data) 14438c7bd5a4SBartosz Golaszewski { 14448c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv = data; 14458c7bd5a4SBartosz Golaszewski 14468c7bd5a4SBartosz Golaszewski clk_bulk_disable_unprepare(MTK_STAR_NCLKS, priv->clks); 14478c7bd5a4SBartosz Golaszewski } 14488c7bd5a4SBartosz Golaszewski 14498c7bd5a4SBartosz Golaszewski static int mtk_star_probe(struct platform_device *pdev) 14508c7bd5a4SBartosz Golaszewski { 14518c7bd5a4SBartosz Golaszewski struct device_node *of_node; 14528c7bd5a4SBartosz Golaszewski struct mtk_star_priv *priv; 14538c7bd5a4SBartosz Golaszewski struct net_device *ndev; 14548c7bd5a4SBartosz Golaszewski struct device *dev; 14558c7bd5a4SBartosz Golaszewski void __iomem *base; 14568c7bd5a4SBartosz Golaszewski int ret, i; 14578c7bd5a4SBartosz Golaszewski 14588c7bd5a4SBartosz Golaszewski dev = &pdev->dev; 14598c7bd5a4SBartosz Golaszewski of_node = dev->of_node; 14608c7bd5a4SBartosz Golaszewski 14618c7bd5a4SBartosz Golaszewski ndev = devm_alloc_etherdev(dev, sizeof(*priv)); 14628c7bd5a4SBartosz Golaszewski if (!ndev) 14638c7bd5a4SBartosz Golaszewski return -ENOMEM; 14648c7bd5a4SBartosz Golaszewski 14658c7bd5a4SBartosz Golaszewski priv = netdev_priv(ndev); 14668c7bd5a4SBartosz Golaszewski priv->ndev = ndev; 1467c16cc6a0SBiao Huang priv->compat_data = of_device_get_match_data(&pdev->dev); 14688c7bd5a4SBartosz Golaszewski SET_NETDEV_DEV(ndev, dev); 14698c7bd5a4SBartosz Golaszewski platform_set_drvdata(pdev, ndev); 14708c7bd5a4SBartosz Golaszewski 14718c7bd5a4SBartosz Golaszewski ndev->min_mtu = ETH_ZLEN; 14728c7bd5a4SBartosz Golaszewski ndev->max_mtu = MTK_STAR_MAX_FRAME_SIZE; 14738c7bd5a4SBartosz Golaszewski 14748c7bd5a4SBartosz Golaszewski spin_lock_init(&priv->lock); 14758c7bd5a4SBartosz Golaszewski 14768c7bd5a4SBartosz Golaszewski base = devm_platform_ioremap_resource(pdev, 0); 14778c7bd5a4SBartosz Golaszewski if (IS_ERR(base)) 14788c7bd5a4SBartosz Golaszewski return PTR_ERR(base); 14798c7bd5a4SBartosz Golaszewski 14808c7bd5a4SBartosz Golaszewski /* We won't be checking the return values of regmap read & write 14818c7bd5a4SBartosz Golaszewski * functions. They can only fail for mmio if there's a clock attached 14828c7bd5a4SBartosz Golaszewski * to regmap which is not the case here. 14838c7bd5a4SBartosz Golaszewski */ 14848c7bd5a4SBartosz Golaszewski priv->regs = devm_regmap_init_mmio(dev, base, 14858c7bd5a4SBartosz Golaszewski &mtk_star_regmap_config); 14868c7bd5a4SBartosz Golaszewski if (IS_ERR(priv->regs)) 14878c7bd5a4SBartosz Golaszewski return PTR_ERR(priv->regs); 14888c7bd5a4SBartosz Golaszewski 14898c7bd5a4SBartosz Golaszewski priv->pericfg = syscon_regmap_lookup_by_phandle(of_node, 14908c7bd5a4SBartosz Golaszewski "mediatek,pericfg"); 14918c7bd5a4SBartosz Golaszewski if (IS_ERR(priv->pericfg)) { 14928c7bd5a4SBartosz Golaszewski dev_err(dev, "Failed to lookup the PERICFG syscon\n"); 14938c7bd5a4SBartosz Golaszewski return PTR_ERR(priv->pericfg); 14948c7bd5a4SBartosz Golaszewski } 14958c7bd5a4SBartosz Golaszewski 14968c7bd5a4SBartosz Golaszewski ndev->irq = platform_get_irq(pdev, 0); 14978c7bd5a4SBartosz Golaszewski if (ndev->irq < 0) 14988c7bd5a4SBartosz Golaszewski return ndev->irq; 14998c7bd5a4SBartosz Golaszewski 15008c7bd5a4SBartosz Golaszewski for (i = 0; i < MTK_STAR_NCLKS; i++) 15018c7bd5a4SBartosz Golaszewski priv->clks[i].id = mtk_star_clk_names[i]; 15028c7bd5a4SBartosz Golaszewski ret = devm_clk_bulk_get(dev, MTK_STAR_NCLKS, priv->clks); 15038c7bd5a4SBartosz Golaszewski if (ret) 15048c7bd5a4SBartosz Golaszewski return ret; 15058c7bd5a4SBartosz Golaszewski 15068c7bd5a4SBartosz Golaszewski ret = clk_bulk_prepare_enable(MTK_STAR_NCLKS, priv->clks); 15078c7bd5a4SBartosz Golaszewski if (ret) 15088c7bd5a4SBartosz Golaszewski return ret; 15098c7bd5a4SBartosz Golaszewski 15108c7bd5a4SBartosz Golaszewski ret = devm_add_action_or_reset(dev, 15118c7bd5a4SBartosz Golaszewski mtk_star_clk_disable_unprepare, priv); 15128c7bd5a4SBartosz Golaszewski if (ret) 15138c7bd5a4SBartosz Golaszewski return ret; 15148c7bd5a4SBartosz Golaszewski 15158c7bd5a4SBartosz Golaszewski ret = of_get_phy_mode(of_node, &priv->phy_intf); 15168c7bd5a4SBartosz Golaszewski if (ret) { 15178c7bd5a4SBartosz Golaszewski return ret; 15188c7bd5a4SBartosz Golaszewski } else if (priv->phy_intf != PHY_INTERFACE_MODE_RMII) { 15198c7bd5a4SBartosz Golaszewski dev_err(dev, "unsupported phy mode: %s\n", 15208c7bd5a4SBartosz Golaszewski phy_modes(priv->phy_intf)); 15218c7bd5a4SBartosz Golaszewski return -EINVAL; 15228c7bd5a4SBartosz Golaszewski } 15238c7bd5a4SBartosz Golaszewski 15248c7bd5a4SBartosz Golaszewski priv->phy_node = of_parse_phandle(of_node, "phy-handle", 0); 15258c7bd5a4SBartosz Golaszewski if (!priv->phy_node) { 15268c7bd5a4SBartosz Golaszewski dev_err(dev, "failed to retrieve the phy handle from device tree\n"); 15278c7bd5a4SBartosz Golaszewski return -ENODEV; 15288c7bd5a4SBartosz Golaszewski } 15298c7bd5a4SBartosz Golaszewski 1530*6cde23b3SBiao Huang if (priv->compat_data->set_interface_mode) { 1531*6cde23b3SBiao Huang ret = priv->compat_data->set_interface_mode(ndev); 1532*6cde23b3SBiao Huang if (ret) { 1533*6cde23b3SBiao Huang dev_err(dev, "Failed to set phy interface, err = %d\n", ret); 1534*6cde23b3SBiao Huang return -EINVAL; 1535*6cde23b3SBiao Huang } 1536*6cde23b3SBiao Huang } 15378c7bd5a4SBartosz Golaszewski 15388c7bd5a4SBartosz Golaszewski ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 15398c7bd5a4SBartosz Golaszewski if (ret) { 15408c7bd5a4SBartosz Golaszewski dev_err(dev, "unsupported DMA mask\n"); 15418c7bd5a4SBartosz Golaszewski return ret; 15428c7bd5a4SBartosz Golaszewski } 15438c7bd5a4SBartosz Golaszewski 15448c7bd5a4SBartosz Golaszewski priv->ring_base = dmam_alloc_coherent(dev, MTK_STAR_DMA_SIZE, 15458c7bd5a4SBartosz Golaszewski &priv->dma_addr, 15468c7bd5a4SBartosz Golaszewski GFP_KERNEL | GFP_DMA); 15478c7bd5a4SBartosz Golaszewski if (!priv->ring_base) 15488c7bd5a4SBartosz Golaszewski return -ENOMEM; 15498c7bd5a4SBartosz Golaszewski 15508c7bd5a4SBartosz Golaszewski mtk_star_nic_disable_pd(priv); 15518c7bd5a4SBartosz Golaszewski mtk_star_init_config(priv); 15528c7bd5a4SBartosz Golaszewski 15538c7bd5a4SBartosz Golaszewski ret = mtk_star_mdio_init(ndev); 15548c7bd5a4SBartosz Golaszewski if (ret) 15558c7bd5a4SBartosz Golaszewski return ret; 15568c7bd5a4SBartosz Golaszewski 15574d04cdc5SJakub Kicinski ret = platform_get_ethdev_address(dev, ndev); 15588c7bd5a4SBartosz Golaszewski if (ret || !is_valid_ether_addr(ndev->dev_addr)) 15598c7bd5a4SBartosz Golaszewski eth_hw_addr_random(ndev); 15608c7bd5a4SBartosz Golaszewski 15618c7bd5a4SBartosz Golaszewski ndev->netdev_ops = &mtk_star_netdev_ops; 15628c7bd5a4SBartosz Golaszewski ndev->ethtool_ops = &mtk_star_ethtool_ops; 15638c7bd5a4SBartosz Golaszewski 15645f012b40SJakub Kicinski netif_napi_add(ndev, &priv->napi, mtk_star_poll, NAPI_POLL_WEIGHT); 15658c7bd5a4SBartosz Golaszewski 15669250dcccSBartosz Golaszewski return devm_register_netdev(dev, ndev); 15678c7bd5a4SBartosz Golaszewski } 15688c7bd5a4SBartosz Golaszewski 1569a9c5eb64SLorenzo Bianconi #ifdef CONFIG_OF 1570*6cde23b3SBiao Huang static int mt8516_set_interface_mode(struct net_device *ndev) 1571*6cde23b3SBiao Huang { 1572*6cde23b3SBiao Huang struct mtk_star_priv *priv = netdev_priv(ndev); 1573*6cde23b3SBiao Huang struct device *dev = mtk_star_get_dev(priv); 1574*6cde23b3SBiao Huang unsigned int intf_val; 1575*6cde23b3SBiao Huang 1576*6cde23b3SBiao Huang switch (priv->phy_intf) { 1577*6cde23b3SBiao Huang case PHY_INTERFACE_MODE_RMII: 1578*6cde23b3SBiao Huang intf_val = MTK_PERICFG_BIT_NIC_CFG_CON_RMII; 1579*6cde23b3SBiao Huang break; 1580*6cde23b3SBiao Huang default: 1581*6cde23b3SBiao Huang dev_err(dev, "This interface not supported\n"); 1582*6cde23b3SBiao Huang return -EINVAL; 1583*6cde23b3SBiao Huang } 1584*6cde23b3SBiao Huang 1585*6cde23b3SBiao Huang return regmap_update_bits(priv->pericfg, 1586*6cde23b3SBiao Huang MTK_PERICFG_REG_NIC_CFG0_CON, 1587*6cde23b3SBiao Huang MTK_PERICFG_REG_NIC_CFG_CON_CFG_INTF, 1588*6cde23b3SBiao Huang intf_val); 1589*6cde23b3SBiao Huang } 1590*6cde23b3SBiao Huang 1591*6cde23b3SBiao Huang static int mt8365_set_interface_mode(struct net_device *ndev) 1592*6cde23b3SBiao Huang { 1593*6cde23b3SBiao Huang struct mtk_star_priv *priv = netdev_priv(ndev); 1594*6cde23b3SBiao Huang struct device *dev = mtk_star_get_dev(priv); 1595*6cde23b3SBiao Huang unsigned int intf_val; 1596*6cde23b3SBiao Huang 1597*6cde23b3SBiao Huang switch (priv->phy_intf) { 1598*6cde23b3SBiao Huang case PHY_INTERFACE_MODE_RMII: 1599*6cde23b3SBiao Huang intf_val = MTK_PERICFG_BIT_NIC_CFG_CON_RMII; 1600*6cde23b3SBiao Huang break; 1601*6cde23b3SBiao Huang default: 1602*6cde23b3SBiao Huang dev_err(dev, "This interface not supported\n"); 1603*6cde23b3SBiao Huang return -EINVAL; 1604*6cde23b3SBiao Huang } 1605*6cde23b3SBiao Huang 1606*6cde23b3SBiao Huang return regmap_update_bits(priv->pericfg, 1607*6cde23b3SBiao Huang MTK_PERICFG_REG_NIC_CFG_CON_V2, 1608*6cde23b3SBiao Huang MTK_PERICFG_REG_NIC_CFG_CON_CFG_INTF, 1609*6cde23b3SBiao Huang intf_val); 1610*6cde23b3SBiao Huang } 1611*6cde23b3SBiao Huang 1612c16cc6a0SBiao Huang static const struct mtk_star_compat mtk_star_mt8516_compat = { 1613*6cde23b3SBiao Huang .set_interface_mode = mt8516_set_interface_mode, 1614c16cc6a0SBiao Huang .bit_clk_div = MTK_STAR_BIT_CLK_DIV_10, 1615c16cc6a0SBiao Huang }; 1616c16cc6a0SBiao Huang 1617*6cde23b3SBiao Huang static const struct mtk_star_compat mtk_star_mt8365_compat = { 1618*6cde23b3SBiao Huang .set_interface_mode = mt8365_set_interface_mode, 1619*6cde23b3SBiao Huang .bit_clk_div = MTK_STAR_BIT_CLK_DIV_50, 1620*6cde23b3SBiao Huang }; 1621*6cde23b3SBiao Huang 16228c7bd5a4SBartosz Golaszewski static const struct of_device_id mtk_star_of_match[] = { 1623c16cc6a0SBiao Huang { .compatible = "mediatek,mt8516-eth", 1624c16cc6a0SBiao Huang .data = &mtk_star_mt8516_compat }, 1625c16cc6a0SBiao Huang { .compatible = "mediatek,mt8518-eth", 1626c16cc6a0SBiao Huang .data = &mtk_star_mt8516_compat }, 1627c16cc6a0SBiao Huang { .compatible = "mediatek,mt8175-eth", 1628c16cc6a0SBiao Huang .data = &mtk_star_mt8516_compat }, 1629*6cde23b3SBiao Huang { .compatible = "mediatek,mt8365-eth", 1630*6cde23b3SBiao Huang .data = &mtk_star_mt8365_compat }, 16318c7bd5a4SBartosz Golaszewski { } 16328c7bd5a4SBartosz Golaszewski }; 16338c7bd5a4SBartosz Golaszewski MODULE_DEVICE_TABLE(of, mtk_star_of_match); 1634a9c5eb64SLorenzo Bianconi #endif 16358c7bd5a4SBartosz Golaszewski 16368c7bd5a4SBartosz Golaszewski static SIMPLE_DEV_PM_OPS(mtk_star_pm_ops, 16378c7bd5a4SBartosz Golaszewski mtk_star_suspend, mtk_star_resume); 16388c7bd5a4SBartosz Golaszewski 16398c7bd5a4SBartosz Golaszewski static struct platform_driver mtk_star_driver = { 16408c7bd5a4SBartosz Golaszewski .driver = { 16418c7bd5a4SBartosz Golaszewski .name = MTK_STAR_DRVNAME, 16428c7bd5a4SBartosz Golaszewski .pm = &mtk_star_pm_ops, 16438c7bd5a4SBartosz Golaszewski .of_match_table = of_match_ptr(mtk_star_of_match), 16448c7bd5a4SBartosz Golaszewski }, 16458c7bd5a4SBartosz Golaszewski .probe = mtk_star_probe, 16468c7bd5a4SBartosz Golaszewski }; 16478c7bd5a4SBartosz Golaszewski module_platform_driver(mtk_star_driver); 16488c7bd5a4SBartosz Golaszewski 16498c7bd5a4SBartosz Golaszewski MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); 16508c7bd5a4SBartosz Golaszewski MODULE_DESCRIPTION("Mediatek STAR Ethernet MAC Driver"); 16518c7bd5a4SBartosz Golaszewski MODULE_LICENSE("GPL"); 1652