cpsw.c revision d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3
1df828598a755732e717b0adca82f884e44d37576Mugunthan V N/* 2df828598a755732e717b0adca82f884e44d37576Mugunthan V N * Texas Instruments Ethernet Switch Driver 3df828598a755732e717b0adca82f884e44d37576Mugunthan V N * 4df828598a755732e717b0adca82f884e44d37576Mugunthan V N * Copyright (C) 2012 Texas Instruments 5df828598a755732e717b0adca82f884e44d37576Mugunthan V N * 6df828598a755732e717b0adca82f884e44d37576Mugunthan V N * This program is free software; you can redistribute it and/or 7df828598a755732e717b0adca82f884e44d37576Mugunthan V N * modify it under the terms of the GNU General Public License as 8df828598a755732e717b0adca82f884e44d37576Mugunthan V N * published by the Free Software Foundation version 2. 9df828598a755732e717b0adca82f884e44d37576Mugunthan V N * 10df828598a755732e717b0adca82f884e44d37576Mugunthan V N * This program is distributed "as is" WITHOUT ANY WARRANTY of any 11df828598a755732e717b0adca82f884e44d37576Mugunthan V N * kind, whether express or implied; without even the implied warranty 12df828598a755732e717b0adca82f884e44d37576Mugunthan V N * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13df828598a755732e717b0adca82f884e44d37576Mugunthan V N * GNU General Public License for more details. 14df828598a755732e717b0adca82f884e44d37576Mugunthan V N */ 15df828598a755732e717b0adca82f884e44d37576Mugunthan V N 16df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/kernel.h> 17df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/io.h> 18df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/clk.h> 19df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/timer.h> 20df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/module.h> 21df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/platform_device.h> 22df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/irqreturn.h> 23df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/interrupt.h> 24df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/if_ether.h> 25df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/etherdevice.h> 26df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/netdevice.h> 272e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#include <linux/net_tstamp.h> 28df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/phy.h> 29df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/workqueue.h> 30df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/delay.h> 31f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N#include <linux/pm_runtime.h> 322eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N#include <linux/of.h> 332eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N#include <linux/of_net.h> 342eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N#include <linux/of_device.h> 353b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N#include <linux/if_vlan.h> 36df828598a755732e717b0adca82f884e44d37576Mugunthan V N 37df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include <linux/platform_data/cpsw.h> 38df828598a755732e717b0adca82f884e44d37576Mugunthan V N 39df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include "cpsw_ale.h" 402e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#include "cpts.h" 41df828598a755732e717b0adca82f884e44d37576Mugunthan V N#include "davinci_cpdma.h" 42df828598a755732e717b0adca82f884e44d37576Mugunthan V N 43df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPSW_DEBUG (NETIF_MSG_HW | NETIF_MSG_WOL | \ 44df828598a755732e717b0adca82f884e44d37576Mugunthan V N NETIF_MSG_DRV | NETIF_MSG_LINK | \ 45df828598a755732e717b0adca82f884e44d37576Mugunthan V N NETIF_MSG_IFUP | NETIF_MSG_INTR | \ 46df828598a755732e717b0adca82f884e44d37576Mugunthan V N NETIF_MSG_PROBE | NETIF_MSG_TIMER | \ 47df828598a755732e717b0adca82f884e44d37576Mugunthan V N NETIF_MSG_IFDOWN | NETIF_MSG_RX_ERR | \ 48df828598a755732e717b0adca82f884e44d37576Mugunthan V N NETIF_MSG_TX_ERR | NETIF_MSG_TX_DONE | \ 49df828598a755732e717b0adca82f884e44d37576Mugunthan V N NETIF_MSG_PKTDATA | NETIF_MSG_TX_QUEUED | \ 50df828598a755732e717b0adca82f884e44d37576Mugunthan V N NETIF_MSG_RX_STATUS) 51df828598a755732e717b0adca82f884e44d37576Mugunthan V N 52df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define cpsw_info(priv, type, format, ...) \ 53df828598a755732e717b0adca82f884e44d37576Mugunthan V Ndo { \ 54df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_msg_##type(priv) && net_ratelimit()) \ 55df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_info(priv->dev, format, ## __VA_ARGS__); \ 56df828598a755732e717b0adca82f884e44d37576Mugunthan V N} while (0) 57df828598a755732e717b0adca82f884e44d37576Mugunthan V N 58df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define cpsw_err(priv, type, format, ...) \ 59df828598a755732e717b0adca82f884e44d37576Mugunthan V Ndo { \ 60df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_msg_##type(priv) && net_ratelimit()) \ 61df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, format, ## __VA_ARGS__); \ 62df828598a755732e717b0adca82f884e44d37576Mugunthan V N} while (0) 63df828598a755732e717b0adca82f884e44d37576Mugunthan V N 64df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define cpsw_dbg(priv, type, format, ...) \ 65df828598a755732e717b0adca82f884e44d37576Mugunthan V Ndo { \ 66df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_msg_##type(priv) && net_ratelimit()) \ 67df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_dbg(priv->dev, format, ## __VA_ARGS__); \ 68df828598a755732e717b0adca82f884e44d37576Mugunthan V N} while (0) 69df828598a755732e717b0adca82f884e44d37576Mugunthan V N 70df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define cpsw_notice(priv, type, format, ...) \ 71df828598a755732e717b0adca82f884e44d37576Mugunthan V Ndo { \ 72df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_msg_##type(priv) && net_ratelimit()) \ 73df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_notice(priv->dev, format, ## __VA_ARGS__); \ 74df828598a755732e717b0adca82f884e44d37576Mugunthan V N} while (0) 75df828598a755732e717b0adca82f884e44d37576Mugunthan V N 765c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N#define ALE_ALL_PORTS 0x7 775c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 78df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPSW_MAJOR_VERSION(reg) (reg >> 8 & 0x7) 79df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPSW_MINOR_VERSION(reg) (reg & 0xff) 80df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPSW_RTL_VERSION(reg) ((reg >> 11) & 0x1f) 81df828598a755732e717b0adca82f884e44d37576Mugunthan V N 82e90cfac6c281da3c8b89dba0eb783c23872705b1Richard Cochran#define CPSW_VERSION_1 0x19010a 83e90cfac6c281da3c8b89dba0eb783c23872705b1Richard Cochran#define CPSW_VERSION_2 0x19010c 84549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 85549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define HOST_PORT_NUM 0 86549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define SLIVER_SIZE 0x40 87549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 88549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_HOST_PORT_OFFSET 0x028 89549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_SLAVE_OFFSET 0x050 90549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_SLAVE_SIZE 0x040 91549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_CPDMA_OFFSET 0x100 92549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_STATERAM_OFFSET 0x200 93549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_CPTS_OFFSET 0x500 94549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_ALE_OFFSET 0x600 95549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW1_SLIVER_OFFSET 0x700 96549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 97549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_HOST_PORT_OFFSET 0x108 98549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_SLAVE_OFFSET 0x200 99549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_SLAVE_SIZE 0x100 100549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_CPDMA_OFFSET 0x800 101549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_STATERAM_OFFSET 0xa00 102549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_CPTS_OFFSET 0xc00 103549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_ALE_OFFSET 0xd00 104549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_SLIVER_OFFSET 0xd80 105549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran#define CPSW2_BD_OFFSET 0x2000 106549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 107df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPDMA_RXTHRESH 0x0c0 108df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPDMA_RXFREE 0x0e0 109df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPDMA_TXHDP 0x00 110df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPDMA_RXHDP 0x20 111df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPDMA_TXCP 0x40 112df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPDMA_RXCP 0x60 113df828598a755732e717b0adca82f884e44d37576Mugunthan V N 114df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPSW_POLL_WEIGHT 64 115df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPSW_MIN_PACKET_SIZE 60 116df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPSW_MAX_PACKET_SIZE (1500 + 14 + 4 + 4) 117df828598a755732e717b0adca82f884e44d37576Mugunthan V N 118df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define RX_PRIORITY_MAPPING 0x76543210 119df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define TX_PRIORITY_MAPPING 0x33221100 120df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define CPDMA_TX_PRIORITY_MAP 0x76543210 121df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1223b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N#define CPSW_VLAN_AWARE BIT(1) 1233b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N#define CPSW_ALE_VLAN_AWARE 1 1243b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 125d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define CPSW_FIFO_NORMAL_MODE (0 << 15) 126d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define CPSW_FIFO_DUAL_MAC_MODE (1 << 15) 127d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define CPSW_FIFO_RATE_LIMIT_MODE (2 << 15) 128d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 129df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define cpsw_enable_irq(priv) \ 130df828598a755732e717b0adca82f884e44d37576Mugunthan V N do { \ 131df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 i; \ 132df828598a755732e717b0adca82f884e44d37576Mugunthan V N for (i = 0; i < priv->num_irqs; i++) \ 133df828598a755732e717b0adca82f884e44d37576Mugunthan V N enable_irq(priv->irqs_table[i]); \ 134df828598a755732e717b0adca82f884e44d37576Mugunthan V N } while (0); 135df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define cpsw_disable_irq(priv) \ 136df828598a755732e717b0adca82f884e44d37576Mugunthan V N do { \ 137df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 i; \ 138df828598a755732e717b0adca82f884e44d37576Mugunthan V N for (i = 0; i < priv->num_irqs; i++) \ 139df828598a755732e717b0adca82f884e44d37576Mugunthan V N disable_irq_nosync(priv->irqs_table[i]); \ 140df828598a755732e717b0adca82f884e44d37576Mugunthan V N } while (0); 141df828598a755732e717b0adca82f884e44d37576Mugunthan V N 142df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int debug_level; 143df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_param(debug_level, int, 0); 144df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_PARM_DESC(debug_level, "cpsw debug level (NETIF_MSG bits)"); 145df828598a755732e717b0adca82f884e44d37576Mugunthan V N 146df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int ale_ageout = 10; 147df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_param(ale_ageout, int, 0); 148df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_PARM_DESC(ale_ageout, "cpsw ale ageout interval (seconds)"); 149df828598a755732e717b0adca82f884e44d37576Mugunthan V N 150df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int rx_packet_max = CPSW_MAX_PACKET_SIZE; 151df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_param(rx_packet_max, int, 0); 152df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_PARM_DESC(rx_packet_max, "maximum receive packet size (bytes)"); 153df828598a755732e717b0adca82f884e44d37576Mugunthan V N 154996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochranstruct cpsw_wr_regs { 155df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 id_ver; 156df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 soft_reset; 157df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 control; 158df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 int_control; 159df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_thresh_en; 160df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_en; 161df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 tx_en; 162df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 misc_en; 163df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 164df828598a755732e717b0adca82f884e44d37576Mugunthan V N 165996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochranstruct cpsw_ss_regs { 166df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 id_ver; 167df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 control; 168df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 soft_reset; 169df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 stat_port_en; 170df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 ptype; 171bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 soft_idle; 172bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 thru_rate; 173bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 gap_thresh; 174bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 tx_start_wds; 175bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 flow_control; 176bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 vlan_ltype; 177bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 ts_ltype; 178bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 dlr_ltype; 179df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 180df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1819750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V1 */ 1829750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_MAX_BLKS 0x00 /* Maximum FIFO Blocks */ 1839750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_BLK_CNT 0x04 /* FIFO Block Usage Count (Read Only) */ 1849750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TX_IN_CTL 0x08 /* Transmit FIFO Control */ 1859750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_PORT_VLAN 0x0c /* VLAN Register */ 1869750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TX_PRI_MAP 0x10 /* Tx Header Priority to Switch Pri Mapping */ 1879750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TS_CTL 0x14 /* Time Sync Control */ 1889750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TS_SEQ_LTYPE 0x18 /* Time Sync Sequence ID Offset and Msg Type */ 1899750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TS_VLAN 0x1c /* Time Sync VLAN1 and VLAN2 */ 1909750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 1919750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V2 */ 1929750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_CONTROL 0x00 /* Control Register */ 1939750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_MAX_BLKS 0x08 /* Maximum FIFO Blocks */ 1949750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_BLK_CNT 0x0c /* FIFO Block Usage Count (Read Only) */ 1959750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_TX_IN_CTL 0x10 /* Transmit FIFO Control */ 1969750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_PORT_VLAN 0x14 /* VLAN Register */ 1979750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */ 1989750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */ 1999750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2009750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V1 and V2 */ 2019750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define SA_LO 0x20 /* CPGMAC_SL Source Address Low */ 2029750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define SA_HI 0x24 /* CPGMAC_SL Source Address High */ 2039750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define SEND_PERCENT 0x28 /* Transmit Queue Send Percentages */ 2049750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2059750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V2 only */ 2069750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP0 0x30 /* Rx DSCP Priority to Rx Packet Mapping */ 2079750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP1 0x34 /* Rx DSCP Priority to Rx Packet Mapping */ 2089750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP2 0x38 /* Rx DSCP Priority to Rx Packet Mapping */ 2099750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP3 0x3c /* Rx DSCP Priority to Rx Packet Mapping */ 2109750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP4 0x40 /* Rx DSCP Priority to Rx Packet Mapping */ 2119750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP5 0x44 /* Rx DSCP Priority to Rx Packet Mapping */ 2129750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP6 0x48 /* Rx DSCP Priority to Rx Packet Mapping */ 2139750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP7 0x4c /* Rx DSCP Priority to Rx Packet Mapping */ 2149750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2159750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* Bit definitions for the CPSW2_CONTROL register */ 2169750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define PASS_PRI_TAGGED (1<<24) /* Pass Priority Tagged */ 2179750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define VLAN_LTYPE2_EN (1<<21) /* VLAN LTYPE 2 enable */ 2189750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define VLAN_LTYPE1_EN (1<<20) /* VLAN LTYPE 1 enable */ 2199750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define DSCP_PRI_EN (1<<16) /* DSCP Priority Enable */ 2209750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_320 (1<<14) /* Time Sync Dest Port 320 enable */ 2219750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_319 (1<<13) /* Time Sync Dest Port 319 enable */ 2229750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_132 (1<<12) /* Time Sync Dest IP Addr 132 enable */ 2239750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_131 (1<<11) /* Time Sync Dest IP Addr 131 enable */ 2249750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_130 (1<<10) /* Time Sync Dest IP Addr 130 enable */ 2259750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_129 (1<<9) /* Time Sync Dest IP Addr 129 enable */ 2269750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_BIT8 (1<<8) /* ts_ttl_nonzero? */ 2279750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_ANNEX_D_EN (1<<4) /* Time Sync Annex D enable */ 2289750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_LTYPE2_EN (1<<3) /* Time Sync LTYPE 2 enable */ 2299750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_LTYPE1_EN (1<<2) /* Time Sync LTYPE 1 enable */ 2309750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_TX_EN (1<<1) /* Time Sync Transmit Enable */ 2319750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_RX_EN (1<<0) /* Time Sync Receive Enable */ 2329750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2339750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_TS_BITS \ 2349750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran (TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \ 2359750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran TS_ANNEX_D_EN | TS_LTYPE1_EN) 2369750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2379750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN) 2389750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_TX_TS_BITS (CTRL_TS_BITS | TS_TX_EN) 2399750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_RX_TS_BITS (CTRL_TS_BITS | TS_RX_EN) 2409750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2419750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* Bit definitions for the CPSW2_TS_SEQ_MTYPE register */ 2429750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_SEQ_ID_OFFSET_SHIFT (16) /* Time Sync Sequence ID Offset */ 2439750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_SEQ_ID_OFFSET_MASK (0x3f) 2449750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_MSG_TYPE_EN_SHIFT (0) /* Time Sync Message Type Enable */ 2459750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_MSG_TYPE_EN_MASK (0xffff) 2469750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2479750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */ 2489750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3)) 249df828598a755732e717b0adca82f884e44d37576Mugunthan V N 2502e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran/* Bit definitions for the CPSW1_TS_CTL register */ 2512e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_TS_RX_EN BIT(0) 2522e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_TS_TX_EN BIT(4) 2532e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_MSG_TYPE_OFS 16 2542e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 2552e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran/* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */ 2562e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_SEQ_ID_OFS_SHIFT 16 2572e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 258df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_host_regs { 259df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 max_blks; 260df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 blk_cnt; 261d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 tx_in_ctl; 262df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 port_vlan; 263df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 tx_pri_map; 264df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 cpdma_tx_pri_map; 265df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 cpdma_rx_chan_map; 266df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 267df828598a755732e717b0adca82f884e44d37576Mugunthan V N 268df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_sliver_regs { 269df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 id_ver; 270df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_control; 271df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_status; 272df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 soft_reset; 273df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_maxlen; 274df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 __reserved_0; 275df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_pause; 276df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 tx_pause; 277df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 __reserved_1; 278df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_pri_map; 279df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 280df828598a755732e717b0adca82f884e44d37576Mugunthan V N 281df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_slave { 2829750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran void __iomem *regs; 283df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_sliver_regs __iomem *sliver; 284df828598a755732e717b0adca82f884e44d37576Mugunthan V N int slave_num; 285df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_control; 286df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_slave_data *data; 287df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct phy_device *phy; 288d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct net_device *ndev; 289d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 port_vlan; 290d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 open_stat; 291df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 292df828598a755732e717b0adca82f884e44d37576Mugunthan V N 2939750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochranstatic inline u32 slave_read(struct cpsw_slave *slave, u32 offset) 2949750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran{ 2959750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran return __raw_readl(slave->regs + offset); 2969750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran} 2979750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2989750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochranstatic inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset) 2999750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran{ 3009750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran __raw_writel(val, slave->regs + offset); 3019750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran} 3029750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 303df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_priv { 304df828598a755732e717b0adca82f884e44d37576Mugunthan V N spinlock_t lock; 305df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct platform_device *pdev; 306df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev; 307df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct resource *cpsw_res; 308a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran struct resource *cpsw_wr_res; 309df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct napi_struct napi; 310df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct device *dev; 311df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_platform_data data; 312996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran struct cpsw_ss_regs __iomem *regs; 313996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran struct cpsw_wr_regs __iomem *wr_regs; 314df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_host_regs __iomem *host_port_regs; 315df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 msg_enable; 316e90cfac6c281da3c8b89dba0eb783c23872705b1Richard Cochran u32 version; 317df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device_stats stats; 318df828598a755732e717b0adca82f884e44d37576Mugunthan V N int rx_packet_max; 319df828598a755732e717b0adca82f884e44d37576Mugunthan V N int host_port; 320df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct clk *clk; 321df828598a755732e717b0adca82f884e44d37576Mugunthan V N u8 mac_addr[ETH_ALEN]; 322df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_slave *slaves; 323df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpdma_ctlr *dma; 324df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpdma_chan *txch, *rxch; 325df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_ale *ale; 326df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* snapshot of IRQ numbers */ 327df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 irqs_table[4]; 328df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 num_irqs; 3299232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N struct cpts *cpts; 330d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 emac_port; 331df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 332df828598a755732e717b0adca82f884e44d37576Mugunthan V N 333df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi) 334d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define for_each_slave(priv, func, arg...) \ 335d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N do { \ 336d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N int idx; \ 337d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) \ 338d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N (func)((priv)->slaves + priv->emac_port, ##arg);\ 339d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else \ 340d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (idx = 0; idx < (priv)->data.slaves; idx++) \ 341d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N (func)((priv)->slaves + idx, ##arg); \ 342d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } while (0) 343d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_get_slave_ndev(priv, __slave_no__) \ 344d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N (priv->slaves[__slave_no__].ndev) 345d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_get_slave_priv(priv, __slave_no__) \ 346d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ((priv->slaves[__slave_no__].ndev) ? \ 347d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N netdev_priv(priv->slaves[__slave_no__].ndev) : NULL) \ 348d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 349d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb) \ 350d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N do { \ 351d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) \ 352d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N break; \ 353d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (CPDMA_RX_SOURCE_PORT(status) == 1) { \ 354d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev = cpsw_get_slave_ndev(priv, 0); \ 355d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv = netdev_priv(ndev); \ 356d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->dev = ndev; \ 357d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else if (CPDMA_RX_SOURCE_PORT(status) == 2) { \ 358d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev = cpsw_get_slave_ndev(priv, 1); \ 359d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv = netdev_priv(ndev); \ 360d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->dev = ndev; \ 361d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } \ 362df828598a755732e717b0adca82f884e44d37576Mugunthan V N } while (0) 363d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_add_mcast(priv, addr) \ 364d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N do { \ 365d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) { \ 366d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_slave *slave = priv->slaves + \ 367d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->emac_port; \ 368d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N int slave_port = cpsw_get_slave_port(priv, \ 369d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave->slave_num); \ 370d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, addr, \ 371d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1 << slave_port | 1 << priv->host_port, \ 372d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ALE_VLAN, slave->port_vlan, 0); \ 373d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { \ 374d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, addr, \ 375d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ALE_ALL_PORTS << priv->host_port, \ 376d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 0, 0, 0); \ 377d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } \ 378d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } while (0) 379d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 380d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num) 381d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 382d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->host_port == 0) 383d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return slave_num + 1; 384d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 385d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return slave_num; 386d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 387df828598a755732e717b0adca82f884e44d37576Mugunthan V N 3885c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V Nstatic void cpsw_ndo_set_rx_mode(struct net_device *ndev) 3895c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N{ 3905c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 3915c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 3925c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N if (ndev->flags & IFF_PROMISC) { 3935c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N /* Enable promiscuous mode */ 3945c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N dev_err(priv->dev, "Ignoring Promiscuous mode\n"); 3955c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N return; 3965c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N } 3975c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 3985c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N /* Clear all mcast from ALE */ 3995c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port); 4005c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 4015c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N if (!netdev_mc_empty(ndev)) { 4025c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N struct netdev_hw_addr *ha; 4035c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 4045c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N /* program multicast address list into ALE register */ 4055c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N netdev_for_each_mc_addr(ha, ndev) { 406d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_add_mcast(priv, (u8 *)ha->addr); 4075c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N } 4085c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N } 4095c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N} 4105c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 411df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_intr_enable(struct cpsw_priv *priv) 412df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 413996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0xFF, &priv->wr_regs->tx_en); 414996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0xFF, &priv->wr_regs->rx_en); 415df828598a755732e717b0adca82f884e44d37576Mugunthan V N 416df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, true); 417df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 418df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 419df828598a755732e717b0adca82f884e44d37576Mugunthan V N 420df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_intr_disable(struct cpsw_priv *priv) 421df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 422996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0, &priv->wr_regs->tx_en); 423996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0, &priv->wr_regs->rx_en); 424df828598a755732e717b0adca82f884e44d37576Mugunthan V N 425df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 426df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 427df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 428df828598a755732e717b0adca82f884e44d37576Mugunthan V N 429df828598a755732e717b0adca82f884e44d37576Mugunthan V Nvoid cpsw_tx_handler(void *token, int len, int status) 430df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 431df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct sk_buff *skb = token; 432df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = skb->dev; 433df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 434df828598a755732e717b0adca82f884e44d37576Mugunthan V N 435fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N /* Check whether the queue is stopped due to stalled tx dma, if the 436fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N * queue is stopped then start the queue as we have free desc for tx 437fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N */ 438df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(netif_queue_stopped(ndev))) 439df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_start_queue(ndev); 4409232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N cpts_tx_timestamp(priv->cpts, skb); 441df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_packets++; 442df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_bytes += len; 443df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_kfree_skb_any(skb); 444df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 445df828598a755732e717b0adca82f884e44d37576Mugunthan V N 446df828598a755732e717b0adca82f884e44d37576Mugunthan V Nvoid cpsw_rx_handler(void *token, int len, int status) 447df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 448df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct sk_buff *skb = token; 449df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = skb->dev; 450df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 451df828598a755732e717b0adca82f884e44d37576Mugunthan V N int ret = 0; 452df828598a755732e717b0adca82f884e44d37576Mugunthan V N 453d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_dual_emac_src_port_detect(status, priv, ndev, skb); 454d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 455df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* free and bail if we are shutting down */ 456df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(!netif_running(ndev)) || 457df828598a755732e717b0adca82f884e44d37576Mugunthan V N unlikely(!netif_carrier_ok(ndev))) { 458df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_kfree_skb_any(skb); 459df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 460df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 461df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (likely(status >= 0)) { 462df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb_put(skb, len); 4639232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N cpts_rx_timestamp(priv->cpts, skb); 464df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb->protocol = eth_type_trans(skb, ndev); 465df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_receive_skb(skb); 466df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.rx_bytes += len; 467df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.rx_packets++; 468df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb = NULL; 469df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 470df828598a755732e717b0adca82f884e44d37576Mugunthan V N 471df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(!netif_running(ndev))) { 472df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (skb) 473df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_kfree_skb_any(skb); 474df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 475df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 476df828598a755732e717b0adca82f884e44d37576Mugunthan V N 477df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (likely(!skb)) { 478df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb = netdev_alloc_skb_ip_align(ndev, priv->rx_packet_max); 479df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (WARN_ON(!skb)) 480df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 481df828598a755732e717b0adca82f884e44d37576Mugunthan V N 482df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = cpdma_chan_submit(priv->rxch, skb, skb->data, 483f6e135c81eeb648c6addc6aeff2ee80f28ea413bMugunthan V N skb_tailroom(skb), 0, GFP_KERNEL); 484df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 485df828598a755732e717b0adca82f884e44d37576Mugunthan V N WARN_ON(ret < 0); 486df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 487df828598a755732e717b0adca82f884e44d37576Mugunthan V N 488df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic irqreturn_t cpsw_interrupt(int irq, void *dev_id) 489df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 490df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = dev_id; 491df828598a755732e717b0adca82f884e44d37576Mugunthan V N 492df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (likely(netif_running(priv->ndev))) { 493df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_disable(priv); 494df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_disable_irq(priv); 495df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_schedule(&priv->napi); 496d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { 497d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv = cpsw_get_slave_priv(priv, 1); 498d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (likely(priv) && likely(netif_running(priv->ndev))) { 499d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_intr_disable(priv); 500d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_disable_irq(priv); 501d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N napi_schedule(&priv->napi); 502d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 503df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 504df828598a755732e717b0adca82f884e44d37576Mugunthan V N return IRQ_HANDLED; 505df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 506df828598a755732e717b0adca82f884e44d37576Mugunthan V N 507df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_poll(struct napi_struct *napi, int budget) 508df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 509df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = napi_to_priv(napi); 510df828598a755732e717b0adca82f884e44d37576Mugunthan V N int num_tx, num_rx; 511df828598a755732e717b0adca82f884e44d37576Mugunthan V N 512df828598a755732e717b0adca82f884e44d37576Mugunthan V N num_tx = cpdma_chan_process(priv->txch, 128); 513df828598a755732e717b0adca82f884e44d37576Mugunthan V N num_rx = cpdma_chan_process(priv->rxch, budget); 514df828598a755732e717b0adca82f884e44d37576Mugunthan V N 515df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (num_rx || num_tx) 516df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n", 517df828598a755732e717b0adca82f884e44d37576Mugunthan V N num_rx, num_tx); 518df828598a755732e717b0adca82f884e44d37576Mugunthan V N 519df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (num_rx < budget) { 520df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_complete(napi); 521df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 522df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_eoi(priv->dma); 523df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_enable_irq(priv); 524df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 525df828598a755732e717b0adca82f884e44d37576Mugunthan V N 526df828598a755732e717b0adca82f884e44d37576Mugunthan V N return num_rx; 527df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 528df828598a755732e717b0adca82f884e44d37576Mugunthan V N 529df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic inline void soft_reset(const char *module, void __iomem *reg) 530df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 531df828598a755732e717b0adca82f884e44d37576Mugunthan V N unsigned long timeout = jiffies + HZ; 532df828598a755732e717b0adca82f884e44d37576Mugunthan V N 533df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(1, reg); 534df828598a755732e717b0adca82f884e44d37576Mugunthan V N do { 535df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpu_relax(); 536df828598a755732e717b0adca82f884e44d37576Mugunthan V N } while ((__raw_readl(reg) & 1) && time_after(timeout, jiffies)); 537df828598a755732e717b0adca82f884e44d37576Mugunthan V N 538df828598a755732e717b0adca82f884e44d37576Mugunthan V N WARN(__raw_readl(reg) & 1, "failed to soft-reset %s\n", module); 539df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 540df828598a755732e717b0adca82f884e44d37576Mugunthan V N 541df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \ 542df828598a755732e717b0adca82f884e44d37576Mugunthan V N ((mac)[2] << 16) | ((mac)[3] << 24)) 543df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8)) 544df828598a755732e717b0adca82f884e44d37576Mugunthan V N 545df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_set_slave_mac(struct cpsw_slave *slave, 546df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv) 547df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 5489750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, mac_hi(priv->mac_addr), SA_HI); 5499750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, mac_lo(priv->mac_addr), SA_LO); 550df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 551df828598a755732e717b0adca82f884e44d37576Mugunthan V N 552df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void _cpsw_adjust_link(struct cpsw_slave *slave, 553df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv, bool *link) 554df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 555df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct phy_device *phy = slave->phy; 556df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_control = 0; 557df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 slave_port; 558df828598a755732e717b0adca82f884e44d37576Mugunthan V N 559df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!phy) 560df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 561df828598a755732e717b0adca82f884e44d37576Mugunthan V N 562df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave_port = cpsw_get_slave_port(priv, slave->slave_num); 563df828598a755732e717b0adca82f884e44d37576Mugunthan V N 564df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (phy->link) { 565df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control = priv->data.mac_control; 566df828598a755732e717b0adca82f884e44d37576Mugunthan V N 567df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* enable forwarding */ 568df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_control_set(priv->ale, slave_port, 569df828598a755732e717b0adca82f884e44d37576Mugunthan V N ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 570df828598a755732e717b0adca82f884e44d37576Mugunthan V N 571df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (phy->speed == 1000) 572df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control |= BIT(7); /* GIGABITEN */ 573df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (phy->duplex) 574df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control |= BIT(0); /* FULLDUPLEXEN */ 575342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack 576342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack /* set speed_in input in case RMII mode is used in 100Mbps */ 577342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack if (phy->speed == 100) 578342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack mac_control |= BIT(15); 579342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack 580df828598a755732e717b0adca82f884e44d37576Mugunthan V N *link = true; 581df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 582df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control = 0; 583df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* disable forwarding */ 584df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_control_set(priv->ale, slave_port, 585df828598a755732e717b0adca82f884e44d37576Mugunthan V N ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); 586df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 587df828598a755732e717b0adca82f884e44d37576Mugunthan V N 588df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (mac_control != slave->mac_control) { 589df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_print_status(phy); 590df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(mac_control, &slave->sliver->mac_control); 591df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 592df828598a755732e717b0adca82f884e44d37576Mugunthan V N 593df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->mac_control = mac_control; 594df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 595df828598a755732e717b0adca82f884e44d37576Mugunthan V N 596df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_adjust_link(struct net_device *ndev) 597df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 598df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 599df828598a755732e717b0adca82f884e44d37576Mugunthan V N bool link = false; 600df828598a755732e717b0adca82f884e44d37576Mugunthan V N 601df828598a755732e717b0adca82f884e44d37576Mugunthan V N for_each_slave(priv, _cpsw_adjust_link, priv, &link); 602df828598a755732e717b0adca82f884e44d37576Mugunthan V N 603df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (link) { 604df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_on(ndev); 605df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_running(ndev)) 606df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_wake_queue(ndev); 607df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 608df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_off(ndev); 609df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_stop_queue(ndev); 610df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 611df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 612df828598a755732e717b0adca82f884e44d37576Mugunthan V N 613df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic inline int __show_stat(char *buf, int maxlen, const char *name, u32 val) 614df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 615df828598a755732e717b0adca82f884e44d37576Mugunthan V N static char *leader = "........................................"; 616df828598a755732e717b0adca82f884e44d37576Mugunthan V N 617df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!val) 618df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 619df828598a755732e717b0adca82f884e44d37576Mugunthan V N else 620df828598a755732e717b0adca82f884e44d37576Mugunthan V N return snprintf(buf, maxlen, "%s %s %10d\n", name, 621df828598a755732e717b0adca82f884e44d37576Mugunthan V N leader + strlen(name), val); 622df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 623df828598a755732e717b0adca82f884e44d37576Mugunthan V N 624d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic int cpsw_common_res_usage_state(struct cpsw_priv *priv) 625d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 626d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 i; 627d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 usage_count = 0; 628d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 629d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) 630d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return 0; 631d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 632d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (i = 0; i < priv->data.slaves; i++) 633d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->slaves[i].open_stat) 634d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N usage_count++; 635d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 636d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return usage_count; 637d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 638d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 639d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic inline int cpsw_tx_packet_submit(struct net_device *ndev, 640d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv, struct sk_buff *skb) 641d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 642d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) 643d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return cpdma_chan_submit(priv->txch, skb, skb->data, 644d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->len, 0, GFP_KERNEL); 645d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 646d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (ndev == cpsw_get_slave_ndev(priv, 0)) 647d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return cpdma_chan_submit(priv->txch, skb, skb->data, 648d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->len, 1, GFP_KERNEL); 649d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 650d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return cpdma_chan_submit(priv->txch, skb, skb->data, 651d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->len, 2, GFP_KERNEL); 652d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 653d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 654d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic inline void cpsw_add_dual_emac_def_ale_entries( 655d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv, struct cpsw_slave *slave, 656d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 slave_port) 657d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 658d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 port_mask = 1 << slave_port | 1 << priv->host_port; 659d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 660d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->version == CPSW_VERSION_1) 661d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN); 662d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 663d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN); 664d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask, 665d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N port_mask, port_mask, 0); 666d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 667d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N port_mask, ALE_VLAN, slave->port_vlan, 0); 668d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_ucast(priv->ale, priv->mac_addr, 669d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->host_port, ALE_VLAN, slave->port_vlan); 670d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 671d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 672df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) 673df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 674df828598a755732e717b0adca82f884e44d37576Mugunthan V N char name[32]; 675df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 slave_port; 676df828598a755732e717b0adca82f884e44d37576Mugunthan V N 677df828598a755732e717b0adca82f884e44d37576Mugunthan V N sprintf(name, "slave-%d", slave->slave_num); 678df828598a755732e717b0adca82f884e44d37576Mugunthan V N 679df828598a755732e717b0adca82f884e44d37576Mugunthan V N soft_reset(name, &slave->sliver->soft_reset); 680df828598a755732e717b0adca82f884e44d37576Mugunthan V N 681df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* setup priority mapping */ 682df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(RX_PRIORITY_MAPPING, &slave->sliver->rx_pri_map); 6839750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 6849750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran switch (priv->version) { 6859750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran case CPSW_VERSION_1: 6869750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP); 6879750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran break; 6889750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran case CPSW_VERSION_2: 6899750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP); 6909750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran break; 6919750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran } 692df828598a755732e717b0adca82f884e44d37576Mugunthan V N 693df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* setup max packet size, and mac address */ 694df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(priv->rx_packet_max, &slave->sliver->rx_maxlen); 695df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_set_slave_mac(slave, priv); 696df828598a755732e717b0adca82f884e44d37576Mugunthan V N 697df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->mac_control = 0; /* no link yet */ 698df828598a755732e717b0adca82f884e44d37576Mugunthan V N 699df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave_port = cpsw_get_slave_port(priv, slave->slave_num); 700df828598a755732e717b0adca82f884e44d37576Mugunthan V N 701d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 702d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port); 703d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 704d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 705d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1 << slave_port, 0, 0, ALE_MCAST_FWD_2); 706df828598a755732e717b0adca82f884e44d37576Mugunthan V N 707df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy = phy_connect(priv->ndev, slave->data->phy_id, 708f9a8f83b04e0c362a2fc660dbad980d24af209fcFlorian Fainelli &cpsw_adjust_link, slave->data->phy_if); 709df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (IS_ERR(slave->phy)) { 710df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "phy %s not found on slave %d\n", 711df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->data->phy_id, slave->slave_num); 712df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy = NULL; 713df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 714df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_info(priv->dev, "phy found : id is : 0x%x\n", 715df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy->phy_id); 716df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_start(slave->phy); 717df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 718df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 719df828598a755732e717b0adca82f884e44d37576Mugunthan V N 7203b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic inline void cpsw_add_default_vlan(struct cpsw_priv *priv) 7213b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 7223b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N const int vlan = priv->data.default_vlan; 7233b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N const int port = priv->host_port; 7243b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N u32 reg; 7253b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N int i; 7263b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7273b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN : 7283b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N CPSW2_PORT_VLAN; 7293b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7303b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N writel(vlan, &priv->host_port_regs->port_vlan); 7313b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7323b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N for (i = 0; i < 2; i++) 7333b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N slave_write(priv->slaves + i, vlan, reg); 7343b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7353b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, 7363b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_ALL_PORTS << port, ALE_ALL_PORTS << port, 7373b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N (ALE_PORT_1 | ALE_PORT_2) << port); 7383b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 7393b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 740df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_init_host_port(struct cpsw_priv *priv) 741df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 7423b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N u32 control_reg; 743d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 fifo_mode; 7443b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 745df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* soft reset the controller and initialize ale */ 746df828598a755732e717b0adca82f884e44d37576Mugunthan V N soft_reset("cpsw", &priv->regs->soft_reset); 747df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_start(priv->ale); 748df828598a755732e717b0adca82f884e44d37576Mugunthan V N 749df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* switch to vlan unaware mode */ 7503b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_control_set(priv->ale, priv->host_port, ALE_VLAN_AWARE, 7513b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N CPSW_ALE_VLAN_AWARE); 7523b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N control_reg = readl(&priv->regs->control); 7533b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N control_reg |= CPSW_VLAN_AWARE; 7543b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N writel(control_reg, &priv->regs->control); 755d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE : 756d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N CPSW_FIFO_NORMAL_MODE; 757d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N writel(fifo_mode, &priv->host_port_regs->tx_in_ctl); 758df828598a755732e717b0adca82f884e44d37576Mugunthan V N 759df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* setup host port priority mapping */ 760df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(CPDMA_TX_PRIORITY_MAP, 761df828598a755732e717b0adca82f884e44d37576Mugunthan V N &priv->host_port_regs->cpdma_tx_pri_map); 762df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(0, &priv->host_port_regs->cpdma_rx_chan_map); 763df828598a755732e717b0adca82f884e44d37576Mugunthan V N 764df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_control_set(priv->ale, priv->host_port, 765df828598a755732e717b0adca82f884e44d37576Mugunthan V N ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 766df828598a755732e717b0adca82f884e44d37576Mugunthan V N 767d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) { 768d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 769d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 0, 0); 770d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 771d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2); 772d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 773df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 774df828598a755732e717b0adca82f884e44d37576Mugunthan V N 775df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_ndo_open(struct net_device *ndev) 776df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 777df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 778df828598a755732e717b0adca82f884e44d37576Mugunthan V N int i, ret; 779df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 reg; 780df828598a755732e717b0adca82f884e44d37576Mugunthan V N 781d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!cpsw_common_res_usage_state(priv)) 782d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_intr_disable(priv); 783df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_off(ndev); 784df828598a755732e717b0adca82f884e44d37576Mugunthan V N 785f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_get_sync(&priv->pdev->dev); 786df828598a755732e717b0adca82f884e44d37576Mugunthan V N 787549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran reg = priv->version; 788df828598a755732e717b0adca82f884e44d37576Mugunthan V N 789df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_info(priv->dev, "initializing cpsw version %d.%d (%d)\n", 790df828598a755732e717b0adca82f884e44d37576Mugunthan V N CPSW_MAJOR_VERSION(reg), CPSW_MINOR_VERSION(reg), 791df828598a755732e717b0adca82f884e44d37576Mugunthan V N CPSW_RTL_VERSION(reg)); 792df828598a755732e717b0adca82f884e44d37576Mugunthan V N 793df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* initialize host and slave ports */ 794d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!cpsw_common_res_usage_state(priv)) 795d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_init_host_port(priv); 796df828598a755732e717b0adca82f884e44d37576Mugunthan V N for_each_slave(priv, cpsw_slave_open, priv); 797df828598a755732e717b0adca82f884e44d37576Mugunthan V N 7983b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N /* Add default VLAN */ 799d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) 800d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_add_default_vlan(priv); 8013b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 802d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!cpsw_common_res_usage_state(priv)) { 803d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* setup tx dma to fixed prio and zero offset */ 804d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1); 805d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0); 806df828598a755732e717b0adca82f884e44d37576Mugunthan V N 807d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* disable priority elevation */ 808d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N __raw_writel(0, &priv->regs->ptype); 809df828598a755732e717b0adca82f884e44d37576Mugunthan V N 810d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* enable statistics collection only on all ports */ 811d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N __raw_writel(0x7, &priv->regs->stat_port_en); 812df828598a755732e717b0adca82f884e44d37576Mugunthan V N 813d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (WARN_ON(!priv->data.rx_descs)) 814d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->data.rx_descs = 128; 815df828598a755732e717b0adca82f884e44d37576Mugunthan V N 816d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (i = 0; i < priv->data.rx_descs; i++) { 817d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct sk_buff *skb; 818df828598a755732e717b0adca82f884e44d37576Mugunthan V N 819d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = -ENOMEM; 820d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb = netdev_alloc_skb_ip_align(priv->ndev, 821d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->rx_packet_max); 822d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!skb) 823d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N break; 824d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = cpdma_chan_submit(priv->rxch, skb, skb->data, 825f6e135c81eeb648c6addc6aeff2ee80f28ea413bMugunthan V N skb_tailroom(skb), 0, GFP_KERNEL); 826d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (WARN_ON(ret < 0)) 827d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N break; 828d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 829d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* continue even if we didn't manage to submit all 830d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N * receive descs 831d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N */ 832d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i); 833df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 834df828598a755732e717b0adca82f884e44d37576Mugunthan V N 835df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_start(priv->dma); 836df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 837df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_enable(&priv->napi); 838df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_eoi(priv->dma); 839df828598a755732e717b0adca82f884e44d37576Mugunthan V N 840d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 841d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[priv->emac_port].open_stat = true; 842df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 843df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 844df828598a755732e717b0adca82f884e44d37576Mugunthan V N 845df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv) 846df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 847df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!slave->phy) 848df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 849df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_stop(slave->phy); 850df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_disconnect(slave->phy); 851df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy = NULL; 852df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 853df828598a755732e717b0adca82f884e44d37576Mugunthan V N 854df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_ndo_stop(struct net_device *ndev) 855df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 856df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 857df828598a755732e717b0adca82f884e44d37576Mugunthan V N 858df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_info(priv, ifdown, "shutting down cpsw device\n"); 859df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_stop_queue(priv->ndev); 860df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_disable(&priv->napi); 861df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_off(priv->ndev); 862d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 863d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (cpsw_common_res_usage_state(priv) <= 1) { 864d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_intr_disable(priv); 865d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 866d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_ctlr_stop(priv->dma); 867d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_stop(priv->ale); 868d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 869df828598a755732e717b0adca82f884e44d37576Mugunthan V N for_each_slave(priv, cpsw_slave_stop, priv); 870f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_put_sync(&priv->pdev->dev); 871d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 872d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[priv->emac_port].open_stat = false; 873df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 874df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 875df828598a755732e717b0adca82f884e44d37576Mugunthan V N 876df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, 877df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev) 878df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 879df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 880df828598a755732e717b0adca82f884e44d37576Mugunthan V N int ret; 881df828598a755732e717b0adca82f884e44d37576Mugunthan V N 882df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev->trans_start = jiffies; 883df828598a755732e717b0adca82f884e44d37576Mugunthan V N 884df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (skb_padto(skb, CPSW_MIN_PACKET_SIZE)) { 885df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_err(priv, tx_err, "packet pad failed\n"); 886df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_dropped++; 887df828598a755732e717b0adca82f884e44d37576Mugunthan V N return NETDEV_TX_OK; 888df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 889df828598a755732e717b0adca82f884e44d37576Mugunthan V N 8909232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && 8919232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts->tx_enable) 8922e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 8932e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 8942e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran skb_tx_timestamp(skb); 8952e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 896d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = cpsw_tx_packet_submit(ndev, priv, skb); 897df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(ret != 0)) { 898df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_err(priv, tx_err, "desc submit failed\n"); 899df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto fail; 900df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 901df828598a755732e717b0adca82f884e44d37576Mugunthan V N 902fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N /* If there is no more tx desc left free then we need to 903fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N * tell the kernel to stop sending us tx frames. 904fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N */ 905fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N if (unlikely(cpdma_check_free_tx_desc(priv->txch))) 906fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N netif_stop_queue(ndev); 907fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N 908df828598a755732e717b0adca82f884e44d37576Mugunthan V N return NETDEV_TX_OK; 909df828598a755732e717b0adca82f884e44d37576Mugunthan V Nfail: 910df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_dropped++; 911df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_stop_queue(ndev); 912df828598a755732e717b0adca82f884e44d37576Mugunthan V N return NETDEV_TX_BUSY; 913df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 914df828598a755732e717b0adca82f884e44d37576Mugunthan V N 915df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags) 916df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 917df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* 918df828598a755732e717b0adca82f884e44d37576Mugunthan V N * The switch cannot operate in promiscuous mode without substantial 919df828598a755732e717b0adca82f884e44d37576Mugunthan V N * headache. For promiscuous mode to work, we would need to put the 920df828598a755732e717b0adca82f884e44d37576Mugunthan V N * ALE in bypass mode and route all traffic to the host port. 921df828598a755732e717b0adca82f884e44d37576Mugunthan V N * Subsequently, the host will need to operate as a "bridge", learn, 922df828598a755732e717b0adca82f884e44d37576Mugunthan V N * and flood as needed. For now, we simply complain here and 923df828598a755732e717b0adca82f884e44d37576Mugunthan V N * do nothing about it :-) 924df828598a755732e717b0adca82f884e44d37576Mugunthan V N */ 925df828598a755732e717b0adca82f884e44d37576Mugunthan V N if ((flags & IFF_PROMISC) && (ndev->flags & IFF_PROMISC)) 926df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(&ndev->dev, "promiscuity ignored!\n"); 927df828598a755732e717b0adca82f884e44d37576Mugunthan V N 928df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* 929df828598a755732e717b0adca82f884e44d37576Mugunthan V N * The switch cannot filter multicast traffic unless it is configured 930df828598a755732e717b0adca82f884e44d37576Mugunthan V N * in "VLAN Aware" mode. Unfortunately, VLAN awareness requires a 931df828598a755732e717b0adca82f884e44d37576Mugunthan V N * whole bunch of additional logic that this driver does not implement 932df828598a755732e717b0adca82f884e44d37576Mugunthan V N * at present. 933df828598a755732e717b0adca82f884e44d37576Mugunthan V N */ 934df828598a755732e717b0adca82f884e44d37576Mugunthan V N if ((flags & IFF_ALLMULTI) && !(ndev->flags & IFF_ALLMULTI)) 935df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n"); 936df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 937df828598a755732e717b0adca82f884e44d37576Mugunthan V N 9382e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#ifdef CONFIG_TI_CPTS 9392e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9402e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic void cpsw_hwtstamp_v1(struct cpsw_priv *priv) 9412e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 9422e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave]; 9432e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran u32 ts_en, seq_id; 9442e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9459232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (!priv->cpts->tx_enable && !priv->cpts->rx_enable) { 9462e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, 0, CPSW1_TS_CTL); 9472e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return; 9482e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 9492e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9502e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588; 9512e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS; 9522e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9539232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->tx_enable) 9542e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ts_en |= CPSW_V1_TS_TX_EN; 9552e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9569232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->rx_enable) 9572e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ts_en |= CPSW_V1_TS_RX_EN; 9582e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9592e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, ts_en, CPSW1_TS_CTL); 9602e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, seq_id, CPSW1_TS_SEQ_LTYPE); 9612e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 9622e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9632e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic void cpsw_hwtstamp_v2(struct cpsw_priv *priv) 9642e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 965d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_slave *slave; 9662e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran u32 ctrl, mtype; 9672e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 968d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 969d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave = &priv->slaves[priv->emac_port]; 970d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 971d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave = &priv->slaves[priv->data.cpts_active_slave]; 972d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 9732e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl = slave_read(slave, CPSW2_CONTROL); 9742e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl &= ~CTRL_ALL_TS_MASK; 9752e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9769232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->tx_enable) 9772e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl |= CTRL_TX_TS_BITS; 9782e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9799232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->rx_enable) 9802e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl |= CTRL_RX_TS_BITS; 9812e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9822e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS; 9832e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9842e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE); 9852e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, ctrl, CPSW2_CONTROL); 9862e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran __raw_writel(ETH_P_1588, &priv->regs->ts_ltype); 9872e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 9882e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9893177bf6f922f62743133abbcbbbb5545f4133b2dMugunthan V Nstatic int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 9902e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 9913177bf6f922f62743133abbcbbbb5545f4133b2dMugunthan V N struct cpsw_priv *priv = netdev_priv(dev); 9929232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N struct cpts *cpts = priv->cpts; 9932e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran struct hwtstamp_config cfg; 9942e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9952e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) 9962e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -EFAULT; 9972e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9982e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran /* reserved for future extensions */ 9992e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (cfg.flags) 10002e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -EINVAL; 10012e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10022e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran switch (cfg.tx_type) { 10032e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_TX_OFF: 10042e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->tx_enable = 0; 10052e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10062e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_TX_ON: 10072e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->tx_enable = 1; 10082e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10092e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran default: 10102e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ERANGE; 10112e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 10122e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10132e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran switch (cfg.rx_filter) { 10142e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_NONE: 10152e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->rx_enable = 0; 10162e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10172e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_ALL: 10182e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 10192e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 10202e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 10212e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ERANGE; 10222e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 10232e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 10242e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 10252e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 10262e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 10272e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 10282e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_EVENT: 10292e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_SYNC: 10302e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 10312e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->rx_enable = 1; 10322e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 10332e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10342e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran default: 10352e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ERANGE; 10362e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 10372e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10382e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran switch (priv->version) { 10392e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case CPSW_VERSION_1: 10402e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpsw_hwtstamp_v1(priv); 10412e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10422e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case CPSW_VERSION_2: 10432e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpsw_hwtstamp_v2(priv); 10442e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10452e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran default: 10462e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ENOTSUPP; 10472e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 10482e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10492e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 10502e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 10512e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10522e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#endif /*CONFIG_TI_CPTS*/ 10532e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10542e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) 10552e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 10562e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (!netif_running(dev)) 10572e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -EINVAL; 10582e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10592e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#ifdef CONFIG_TI_CPTS 10602e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (cmd == SIOCSHWTSTAMP) 10613177bf6f922f62743133abbcbbbb5545f4133b2dMugunthan V N return cpsw_hwtstamp_ioctl(dev, req); 10622e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#endif 10632e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ENOTSUPP; 10642e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 10652e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 1066df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_ndo_tx_timeout(struct net_device *ndev) 1067df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1068df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1069df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1070df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_err(priv, tx_err, "transmit timeout, restarting dma\n"); 1071df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_errors++; 1072df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_disable(priv); 1073df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 1074df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_stop(priv->txch); 1075df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_start(priv->txch); 1076df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, true); 1077df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 1078df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_eoi(priv->dma); 1079df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1080df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1081df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev) 1082df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1083df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1084df828598a755732e717b0adca82f884e44d37576Mugunthan V N return &priv->stats; 1085df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1086df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1087df828598a755732e717b0adca82f884e44d37576Mugunthan V N#ifdef CONFIG_NET_POLL_CONTROLLER 1088df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_ndo_poll_controller(struct net_device *ndev) 1089df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1090df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1091df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1092df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_disable(priv); 1093df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 1094df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_interrupt(ndev->irq, priv); 1095df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, true); 1096df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 1097df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_eoi(priv->dma); 1098df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1099df828598a755732e717b0adca82f884e44d37576Mugunthan V N#endif 1100df828598a755732e717b0adca82f884e44d37576Mugunthan V N 11013b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, 11023b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N unsigned short vid) 11033b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 11043b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N int ret; 11053b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11063b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_add_vlan(priv->ale, vid, 11073b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_ALL_PORTS << priv->host_port, 11083b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 0, ALE_ALL_PORTS << priv->host_port, 11093b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N (ALE_PORT_1 | ALE_PORT_2) << priv->host_port); 11103b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11113b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11123b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11133b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_add_ucast(priv->ale, priv->mac_addr, 11143b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N priv->host_port, ALE_VLAN, vid); 11153b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11163b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N goto clean_vid; 11173b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11183b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 11193b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_ALL_PORTS << priv->host_port, 11203b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_VLAN, vid, 0); 11213b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11223b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N goto clean_vlan_ucast; 11233b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return 0; 11243b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11253b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nclean_vlan_ucast: 11263b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_del_ucast(priv->ale, priv->mac_addr, 11273b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N priv->host_port, ALE_VLAN, vid); 11283b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nclean_vid: 11293b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_del_vlan(priv->ale, vid, 0); 11303b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11313b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 11323b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11333b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, 11343b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N unsigned short vid) 11353b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 11363b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 11373b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11383b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (vid == priv->data.default_vlan) 11393b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return 0; 11403b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11413b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid); 11423b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return cpsw_add_vlan_ale_entry(priv, vid); 11433b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 11443b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11453b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, 11463b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N unsigned short vid) 11473b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 11483b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 11493b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N int ret; 11503b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11513b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (vid == priv->data.default_vlan) 11523b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return 0; 11533b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11543b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid); 11553b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_del_vlan(priv->ale, vid, 0); 11563b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11573b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11583b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11593b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_del_ucast(priv->ale, priv->mac_addr, 11603b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N priv->host_port, ALE_VLAN, vid); 11613b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11623b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11633b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11643b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 11653b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 0, ALE_VLAN, vid); 11663b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 11673b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 1168df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic const struct net_device_ops cpsw_netdev_ops = { 1169df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_open = cpsw_ndo_open, 1170df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_stop = cpsw_ndo_stop, 1171df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_start_xmit = cpsw_ndo_start_xmit, 1172df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_change_rx_flags = cpsw_ndo_change_rx_flags, 11732e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran .ndo_do_ioctl = cpsw_ndo_ioctl, 1174df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_validate_addr = eth_validate_addr, 11755c473ed26dba609622c9a625f896f8f59d86066cDavid S. Miller .ndo_change_mtu = eth_change_mtu, 1176df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_tx_timeout = cpsw_ndo_tx_timeout, 1177df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_get_stats = cpsw_ndo_get_stats, 11785c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N .ndo_set_rx_mode = cpsw_ndo_set_rx_mode, 1179df828598a755732e717b0adca82f884e44d37576Mugunthan V N#ifdef CONFIG_NET_POLL_CONTROLLER 1180df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_poll_controller = cpsw_ndo_poll_controller, 1181df828598a755732e717b0adca82f884e44d37576Mugunthan V N#endif 11823b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid, 11833b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid, 1184df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1185df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1186df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_get_drvinfo(struct net_device *ndev, 1187df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct ethtool_drvinfo *info) 1188df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1189df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 11907826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko 11917826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko strlcpy(info->driver, "TI CPSW Driver v1.0", sizeof(info->driver)); 11927826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko strlcpy(info->version, "1.0", sizeof(info->version)); 11937826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko strlcpy(info->bus_info, priv->pdev->name, sizeof(info->bus_info)); 1194df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1195df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1196df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic u32 cpsw_get_msglevel(struct net_device *ndev) 1197df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1198df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1199df828598a755732e717b0adca82f884e44d37576Mugunthan V N return priv->msg_enable; 1200df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1201df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1202df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_set_msglevel(struct net_device *ndev, u32 value) 1203df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1204df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1205df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->msg_enable = value; 1206df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1207df828598a755732e717b0adca82f884e44d37576Mugunthan V N 12082e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic int cpsw_get_ts_info(struct net_device *ndev, 12092e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran struct ethtool_ts_info *info) 12102e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 12112e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#ifdef CONFIG_TI_CPTS 12122e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran struct cpsw_priv *priv = netdev_priv(ndev); 12132e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 12142e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->so_timestamping = 12152e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_TX_HARDWARE | 12162e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_TX_SOFTWARE | 12172e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RX_HARDWARE | 12182e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RX_SOFTWARE | 12192e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_SOFTWARE | 12202e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RAW_HARDWARE; 12219232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N info->phc_index = priv->cpts->phc_index; 12222e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->tx_types = 12232e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_TX_OFF) | 12242e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_TX_ON); 12252e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->rx_filters = 12262e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_FILTER_NONE) | 12272e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); 12282e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#else 12292e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->so_timestamping = 12302e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_TX_SOFTWARE | 12312e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RX_SOFTWARE | 12322e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_SOFTWARE; 12332e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->phc_index = -1; 12342e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->tx_types = 0; 12352e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->rx_filters = 0; 12362e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#endif 12372e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return 0; 12382e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 12392e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 1240df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic const struct ethtool_ops cpsw_ethtool_ops = { 1241df828598a755732e717b0adca82f884e44d37576Mugunthan V N .get_drvinfo = cpsw_get_drvinfo, 1242df828598a755732e717b0adca82f884e44d37576Mugunthan V N .get_msglevel = cpsw_get_msglevel, 1243df828598a755732e717b0adca82f884e44d37576Mugunthan V N .set_msglevel = cpsw_set_msglevel, 1244df828598a755732e717b0adca82f884e44d37576Mugunthan V N .get_link = ethtool_op_get_link, 12452e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran .get_ts_info = cpsw_get_ts_info, 1246df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1247df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1248549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochranstatic void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv, 1249549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran u32 slave_reg_ofs, u32 sliver_reg_ofs) 1250df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1251df828598a755732e717b0adca82f884e44d37576Mugunthan V N void __iomem *regs = priv->regs; 1252df828598a755732e717b0adca82f884e44d37576Mugunthan V N int slave_num = slave->slave_num; 1253df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_slave_data *data = priv->data.slave_data + slave_num; 1254df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1255df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->data = data; 1256549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave->regs = regs + slave_reg_ofs; 1257549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave->sliver = regs + sliver_reg_ofs; 1258d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave->port_vlan = data->dual_emac_res_vlan; 1259df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1260df828598a755732e717b0adca82f884e44d37576Mugunthan V N 12612eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V Nstatic int cpsw_probe_dt(struct cpsw_platform_data *data, 12622eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct platform_device *pdev) 12632eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N{ 12642eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct device_node *node = pdev->dev.of_node; 12652eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct device_node *slave_node; 12662eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N int i = 0, ret; 12672eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N u32 prop; 12682eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 12692eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (!node) 12702eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return -EINVAL; 12712eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 12722eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "slaves", &prop)) { 12732eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing slaves property in the DT.\n"); 12742eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return -EINVAL; 12752eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 12762eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->slaves = prop; 12772eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 127878ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran if (of_property_read_u32(node, "cpts_active_slave", &prop)) { 127978ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran pr_err("Missing cpts_active_slave property in the DT.\n"); 128078ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran ret = -EINVAL; 128178ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran goto error_ret; 128278ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran } 128378ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran data->cpts_active_slave = prop; 128478ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran 128500ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran if (of_property_read_u32(node, "cpts_clock_mult", &prop)) { 128600ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran pr_err("Missing cpts_clock_mult property in the DT.\n"); 128700ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran ret = -EINVAL; 128800ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran goto error_ret; 128900ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran } 129000ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran data->cpts_clock_mult = prop; 129100ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran 129200ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran if (of_property_read_u32(node, "cpts_clock_shift", &prop)) { 129300ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran pr_err("Missing cpts_clock_shift property in the DT.\n"); 129400ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran ret = -EINVAL; 129500ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran goto error_ret; 129600ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran } 129700ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran data->cpts_clock_shift = prop; 129800ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran 1299b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches data->slave_data = kcalloc(data->slaves, sizeof(struct cpsw_slave_data), 1300b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches GFP_KERNEL); 1301b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches if (!data->slave_data) 13022eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return -EINVAL; 13032eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13042eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "cpdma_channels", &prop)) { 13052eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing cpdma_channels property in the DT.\n"); 13062eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13072eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13082eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13092eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->channels = prop; 13102eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13112eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "ale_entries", &prop)) { 13122eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing ale_entries property in the DT.\n"); 13132eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13142eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13152eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13162eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->ale_entries = prop; 13172eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13182eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "bd_ram_size", &prop)) { 13192eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing bd_ram_size property in the DT.\n"); 13202eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13212eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13222eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13232eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->bd_ram_size = prop; 13242eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13252eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "rx_descs", &prop)) { 13262eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing rx_descs property in the DT.\n"); 13272eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13282eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13292eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13302eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->rx_descs = prop; 13312eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13322eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "mac_control", &prop)) { 13332eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing mac_control property in the DT.\n"); 13342eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13352eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13362eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13372eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->mac_control = prop; 13382eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1339d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!of_property_read_u32(node, "dual_emac", &prop)) 1340d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N data->dual_emac = prop; 1341d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1342549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran /* 1343549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran * Populate all the child nodes here... 1344549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran */ 1345549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ret = of_platform_populate(node, NULL, NULL, &pdev->dev); 1346549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran /* We do not want to force this, as in some cases may not have child */ 1347549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if (ret) 1348549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran pr_warn("Doesn't have any child node\n"); 1349549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 13501fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath for_each_node_by_name(slave_node, "slave") { 13512eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct cpsw_slave_data *slave_data = data->slave_data + i; 13522eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N const void *mac_addr = NULL; 1353549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran u32 phyid; 1354549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran int lenp; 1355549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran const __be32 *parp; 1356549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran struct device_node *mdio_node; 1357549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran struct platform_device *mdio; 1358549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 1359549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran parp = of_get_property(slave_node, "phy_id", &lenp); 1360549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) { 13612eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing slave[%d] phy_id property\n", i); 13622eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13632eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13642eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 1365549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); 1366549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran phyid = be32_to_cpup(parp+1); 1367549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran mdio = of_find_device_by_node(mdio_node); 1368549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), 1369549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran PHY_ID_FMT, mdio->name, phyid); 13702eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13712eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N mac_addr = of_get_mac_address(slave_node); 13722eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (mac_addr) 13732eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); 13742eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1375d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (data->dual_emac) { 1376d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (of_property_read_u32(node, "dual_emac_res_vlan", 1377d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N &prop)) { 1378d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("Missing dual_emac_res_vlan in DT.\n"); 1379d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_data->dual_emac_res_vlan = i+1; 1380d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("Using %d as Reserved VLAN for %d slave\n", 1381d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_data->dual_emac_res_vlan, i); 1382d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { 1383d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_data->dual_emac_res_vlan = prop; 1384d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1385d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1386d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 13872eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N i++; 13882eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13892eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13902eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return 0; 13912eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13922eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V Nerror_ret: 13932eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N kfree(data->slave_data); 13942eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return ret; 13952eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N} 13962eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1397d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic int cpsw_probe_dual_emac(struct platform_device *pdev, 1398d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv) 1399d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 1400d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_platform_data *data = &priv->data; 1401d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct net_device *ndev; 1402d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv_sl2; 1403d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N int ret = 0, i; 1404d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1405d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev = alloc_etherdev(sizeof(struct cpsw_priv)); 1406d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!ndev) { 1407d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("cpsw: error allocating net_device\n"); 1408d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return -ENOMEM; 1409d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1410d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1411d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2 = netdev_priv(ndev); 1412d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N spin_lock_init(&priv_sl2->lock); 1413d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->data = *data; 1414d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->pdev = pdev; 1415d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->ndev = ndev; 1416d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->dev = &ndev->dev; 1417d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); 1418d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->rx_packet_max = max(rx_packet_max, 128); 1419d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1420d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (is_valid_ether_addr(data->slave_data[1].mac_addr)) { 1421d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr, 1422d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ETH_ALEN); 1423d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr); 1424d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { 1425d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N random_ether_addr(priv_sl2->mac_addr); 1426d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr); 1427d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1428d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN); 1429d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1430d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->slaves = priv->slaves; 1431d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->clk = priv->clk; 1432d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1433d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->cpsw_res = priv->cpsw_res; 1434d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->regs = priv->regs; 1435d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->host_port = priv->host_port; 1436d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->host_port_regs = priv->host_port_regs; 1437d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->wr_regs = priv->wr_regs; 1438d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->dma = priv->dma; 1439d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->txch = priv->txch; 1440d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->rxch = priv->rxch; 1441d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->ale = priv->ale; 1442d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->emac_port = 1; 1443d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[1].ndev = ndev; 1444d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->cpts = priv->cpts; 1445d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->version = priv->version; 1446d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1447d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (i = 0; i < priv->num_irqs; i++) { 1448d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->irqs_table[i] = priv->irqs_table[i]; 1449d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->num_irqs = priv->num_irqs; 1450d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1451d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1452d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev->features |= NETIF_F_HW_VLAN_FILTER; 1453d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1454d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev->netdev_ops = &cpsw_netdev_ops; 1455d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops); 1456d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT); 1457d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1458d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* register the network device */ 1459d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N SET_NETDEV_DEV(ndev, &pdev->dev); 1460d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = register_netdev(ndev); 1461d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (ret) { 1462d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("cpsw: error registering net device\n"); 1463d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N free_netdev(ndev); 1464d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = -ENODEV; 1465d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1466d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1467d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return ret; 1468d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 1469d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1470663e12e61d8764ce342588325d1050d9cb5460c0Bill Pembertonstatic int cpsw_probe(struct platform_device *pdev) 1471df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1472df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_platform_data *data = pdev->dev.platform_data; 1473df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev; 1474df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv; 1475df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpdma_params dma_params; 1476df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_ale_params ale_params; 1477549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran void __iomem *ss_regs, *wr_regs; 1478df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct resource *res; 1479549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran u32 slave_offset, sliver_offset, slave_size; 1480df828598a755732e717b0adca82f884e44d37576Mugunthan V N int ret = 0, i, k = 0; 1481df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1482df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev = alloc_etherdev(sizeof(struct cpsw_priv)); 1483df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!ndev) { 1484df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_err("error allocating net_device\n"); 1485df828598a755732e717b0adca82f884e44d37576Mugunthan V N return -ENOMEM; 1486df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1487df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1488df828598a755732e717b0adca82f884e44d37576Mugunthan V N platform_set_drvdata(pdev, ndev); 1489df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv = netdev_priv(ndev); 1490df828598a755732e717b0adca82f884e44d37576Mugunthan V N spin_lock_init(&priv->lock); 1491df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->pdev = pdev; 1492df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->ndev = ndev; 1493df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->dev = &ndev->dev; 1494df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); 1495df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->rx_packet_max = max(rx_packet_max, 128); 14969232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL); 14979232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (!ndev) { 14989232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N pr_err("error allocating cpts\n"); 14999232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N goto clean_ndev_ret; 15009232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N } 1501df828598a755732e717b0adca82f884e44d37576Mugunthan V N 15021fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath /* 15031fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath * This may be required here for child devices. 15041fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath */ 15051fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath pm_runtime_enable(&pdev->dev); 15061fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath 15072eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (cpsw_probe_dt(&priv->data, pdev)) { 15082eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("cpsw: platform data missing\n"); 15092eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -ENODEV; 15102eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto clean_ndev_ret; 15112eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 15122eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data = &priv->data; 15132eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1514df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (is_valid_ether_addr(data->slave_data[0].mac_addr)) { 1515df828598a755732e717b0adca82f884e44d37576Mugunthan V N memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN); 1516df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_info("Detected MACID = %pM", priv->mac_addr); 1517df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 15187efd26d0db5917b9e53d72e76e52338b2600ae20Joe Perches eth_random_addr(priv->mac_addr); 1519df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_info("Random MACID = %pM", priv->mac_addr); 1520df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1521df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1522df828598a755732e717b0adca82f884e44d37576Mugunthan V N memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN); 1523df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1524df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->slaves = kzalloc(sizeof(struct cpsw_slave) * data->slaves, 1525df828598a755732e717b0adca82f884e44d37576Mugunthan V N GFP_KERNEL); 1526df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->slaves) { 1527df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -EBUSY; 1528df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_ndev_ret; 1529df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1530df828598a755732e717b0adca82f884e44d37576Mugunthan V N for (i = 0; i < data->slaves; i++) 1531df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->slaves[i].slave_num = i; 1532df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1533d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[0].ndev = ndev; 1534d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->emac_port = 0; 1535d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1536f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N priv->clk = clk_get(&pdev->dev, "fck"); 1537df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (IS_ERR(priv->clk)) { 1538f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N dev_err(&pdev->dev, "fck is not found\n"); 1539f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N ret = -ENODEV; 1540f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N goto clean_slave_ret; 1541df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1542df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1543df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1544df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->cpsw_res) { 1545df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error getting i/o resource\n"); 1546df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOENT; 1547df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_clk_ret; 1548df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1549df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!request_mem_region(priv->cpsw_res->start, 1550df828598a755732e717b0adca82f884e44d37576Mugunthan V N resource_size(priv->cpsw_res), ndev->name)) { 1551df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "failed request i/o region\n"); 1552df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENXIO; 1553df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_clk_ret; 1554df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1555549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res)); 1556549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if (!ss_regs) { 1557df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "unable to map i/o region\n"); 1558df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_cpsw_iores_ret; 1559df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1560549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->regs = ss_regs; 1561549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->version = __raw_readl(&priv->regs->id_ver); 1562549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->host_port = HOST_PORT_NUM; 1563df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1564a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1565a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran if (!priv->cpsw_wr_res) { 1566df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error getting i/o resource\n"); 1567df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOENT; 15685250c9694fa879532470d87ebf6a485be1124221Richard Cochran goto clean_iomap_ret; 1569df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1570a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran if (!request_mem_region(priv->cpsw_wr_res->start, 1571a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res), ndev->name)) { 1572df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "failed request i/o region\n"); 1573df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENXIO; 15745250c9694fa879532470d87ebf6a485be1124221Richard Cochran goto clean_iomap_ret; 1575df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1576549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran wr_regs = ioremap(priv->cpsw_wr_res->start, 1577a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res)); 1578549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if (!wr_regs) { 1579df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "unable to map i/o region\n"); 1580a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran goto clean_cpsw_wr_iores_ret; 1581df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1582549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->wr_regs = wr_regs; 1583df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1584df828598a755732e717b0adca82f884e44d37576Mugunthan V N memset(&dma_params, 0, sizeof(dma_params)); 1585549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran memset(&ale_params, 0, sizeof(ale_params)); 1586549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 1587549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran switch (priv->version) { 1588549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran case CPSW_VERSION_1: 1589549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET; 15909232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts->reg = ss_regs + CPSW1_CPTS_OFFSET; 1591549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.dmaregs = ss_regs + CPSW1_CPDMA_OFFSET; 1592549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.txhdp = ss_regs + CPSW1_STATERAM_OFFSET; 1593549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ale_params.ale_regs = ss_regs + CPSW1_ALE_OFFSET; 1594549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_offset = CPSW1_SLAVE_OFFSET; 1595549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_size = CPSW1_SLAVE_SIZE; 1596549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran sliver_offset = CPSW1_SLIVER_OFFSET; 1597549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.desc_mem_phys = 0; 1598549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran break; 1599549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran case CPSW_VERSION_2: 1600549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET; 16019232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts->reg = ss_regs + CPSW2_CPTS_OFFSET; 1602549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.dmaregs = ss_regs + CPSW2_CPDMA_OFFSET; 1603549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.txhdp = ss_regs + CPSW2_STATERAM_OFFSET; 1604549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ale_params.ale_regs = ss_regs + CPSW2_ALE_OFFSET; 1605549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_offset = CPSW2_SLAVE_OFFSET; 1606549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_size = CPSW2_SLAVE_SIZE; 1607549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran sliver_offset = CPSW2_SLIVER_OFFSET; 1608549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.desc_mem_phys = 1609549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET; 1610549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran break; 1611549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran default: 1612549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dev_err(priv->dev, "unknown version 0x%08x\n", priv->version); 1613549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ret = -ENODEV; 1614549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran goto clean_cpsw_wr_iores_ret; 1615549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran } 1616549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran for (i = 0; i < priv->data.slaves; i++) { 1617549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran struct cpsw_slave *slave = &priv->slaves[i]; 1618549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran cpsw_slave_init(slave, priv, slave_offset, sliver_offset); 1619549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_offset += slave_size; 1620549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran sliver_offset += SLIVER_SIZE; 1621549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran } 1622549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 1623df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.dev = &pdev->dev; 1624549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxthresh = dma_params.dmaregs + CPDMA_RXTHRESH; 1625549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxfree = dma_params.dmaregs + CPDMA_RXFREE; 1626549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxhdp = dma_params.txhdp + CPDMA_RXHDP; 1627549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.txcp = dma_params.txhdp + CPDMA_TXCP; 1628549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxcp = dma_params.txhdp + CPDMA_RXCP; 1629df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1630df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.num_chan = data->channels; 1631df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.has_soft_reset = true; 1632df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.min_packet_size = CPSW_MIN_PACKET_SIZE; 1633df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.desc_mem_size = data->bd_ram_size; 1634df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.desc_align = 16; 1635df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.has_ext_regs = true; 1636549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.desc_hw_addr = dma_params.desc_mem_phys; 1637df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1638df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->dma = cpdma_ctlr_create(&dma_params); 1639df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->dma) { 1640df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error initializing dma\n"); 1641df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOMEM; 16425250c9694fa879532470d87ebf6a485be1124221Richard Cochran goto clean_wr_iomap_ret; 1643df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1644df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1645df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0), 1646df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_tx_handler); 1647df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->rxch = cpdma_chan_create(priv->dma, rx_chan_num(0), 1648df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_rx_handler); 1649df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1650df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (WARN_ON(!priv->txch || !priv->rxch)) { 1651df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error initializing dma channels\n"); 1652df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOMEM; 1653df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_dma_ret; 1654df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1655df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1656df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.dev = &ndev->dev; 1657df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.ale_ageout = ale_ageout; 1658df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.ale_entries = data->ale_entries; 1659df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.ale_ports = data->slaves; 1660df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1661df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->ale = cpsw_ale_create(&ale_params); 1662df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->ale) { 1663df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error initializing ale engine\n"); 1664df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENODEV; 1665df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_dma_ret; 1666df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1667df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1668df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev->irq = platform_get_irq(pdev, 0); 1669df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (ndev->irq < 0) { 1670df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error getting irq resource\n"); 1671df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOENT; 1672df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_ale_ret; 1673df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1674df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1675df828598a755732e717b0adca82f884e44d37576Mugunthan V N while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { 1676df828598a755732e717b0adca82f884e44d37576Mugunthan V N for (i = res->start; i <= res->end; i++) { 1677df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (request_irq(i, cpsw_interrupt, IRQF_DISABLED, 1678df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_name(&pdev->dev), priv)) { 1679df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error attaching irq\n"); 1680df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_ale_ret; 1681df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1682df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->irqs_table[k] = i; 1683df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->num_irqs = k; 1684df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1685df828598a755732e717b0adca82f884e44d37576Mugunthan V N k++; 1686df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1687df828598a755732e717b0adca82f884e44d37576Mugunthan V N 16883b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ndev->features |= NETIF_F_HW_VLAN_FILTER; 1689df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1690df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev->netdev_ops = &cpsw_netdev_ops; 1691df828598a755732e717b0adca82f884e44d37576Mugunthan V N SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops); 1692df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT); 1693df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1694df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* register the network device */ 1695df828598a755732e717b0adca82f884e44d37576Mugunthan V N SET_NETDEV_DEV(ndev, &pdev->dev); 1696df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = register_netdev(ndev); 1697df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (ret) { 1698df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error registering net device\n"); 1699df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENODEV; 1700df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_irq_ret; 1701df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1702df828598a755732e717b0adca82f884e44d37576Mugunthan V N 17039232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (cpts_register(&pdev->dev, priv->cpts, 17042e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran data->cpts_clock_mult, data->cpts_clock_shift)) 17052e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran dev_err(priv->dev, "error registering cpts device\n"); 17062e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 1707df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n", 1708df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->cpsw_res->start, ndev->irq); 1709df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1710d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) { 1711d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = cpsw_probe_dual_emac(pdev, priv); 1712d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (ret) { 1713d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_err(priv, probe, "error probe slave 2 emac interface\n"); 1714d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N goto clean_irq_ret; 1715d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1716d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1717d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1718df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1719df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1720df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_irq_ret: 1721df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_irq(ndev->irq, priv); 1722df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_ale_ret: 1723df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_destroy(priv->ale); 1724df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_dma_ret: 1725df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->txch); 1726df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->rxch); 1727df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_destroy(priv->dma); 17285250c9694fa879532470d87ebf6a485be1124221Richard Cochranclean_wr_iomap_ret: 17295250c9694fa879532470d87ebf6a485be1124221Richard Cochran iounmap(priv->wr_regs); 1730a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochranclean_cpsw_wr_iores_ret: 1731a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran release_mem_region(priv->cpsw_wr_res->start, 1732a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res)); 17335250c9694fa879532470d87ebf6a485be1124221Richard Cochranclean_iomap_ret: 17345250c9694fa879532470d87ebf6a485be1124221Richard Cochran iounmap(priv->regs); 1735df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_cpsw_iores_ret: 1736df828598a755732e717b0adca82f884e44d37576Mugunthan V N release_mem_region(priv->cpsw_res->start, 1737df828598a755732e717b0adca82f884e44d37576Mugunthan V N resource_size(priv->cpsw_res)); 1738df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_clk_ret: 1739df828598a755732e717b0adca82f884e44d37576Mugunthan V N clk_put(priv->clk); 1740f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V Nclean_slave_ret: 1741f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_disable(&pdev->dev); 1742df828598a755732e717b0adca82f884e44d37576Mugunthan V N kfree(priv->slaves); 1743df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_ndev_ret: 1744df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_netdev(ndev); 1745df828598a755732e717b0adca82f884e44d37576Mugunthan V N return ret; 1746df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1747df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1748663e12e61d8764ce342588325d1050d9cb5460c0Bill Pembertonstatic int cpsw_remove(struct platform_device *pdev) 1749df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1750df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = platform_get_drvdata(pdev); 1751df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1752df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1753df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_info("removing device"); 1754df828598a755732e717b0adca82f884e44d37576Mugunthan V N platform_set_drvdata(pdev, NULL); 1755df828598a755732e717b0adca82f884e44d37576Mugunthan V N 17569232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N cpts_unregister(priv->cpts); 1757df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_irq(ndev->irq, priv); 1758df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_destroy(priv->ale); 1759df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->txch); 1760df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->rxch); 1761df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_destroy(priv->dma); 1762df828598a755732e717b0adca82f884e44d37576Mugunthan V N iounmap(priv->regs); 1763df828598a755732e717b0adca82f884e44d37576Mugunthan V N release_mem_region(priv->cpsw_res->start, 1764df828598a755732e717b0adca82f884e44d37576Mugunthan V N resource_size(priv->cpsw_res)); 17655250c9694fa879532470d87ebf6a485be1124221Richard Cochran iounmap(priv->wr_regs); 1766a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran release_mem_region(priv->cpsw_wr_res->start, 1767a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res)); 1768f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_disable(&pdev->dev); 1769df828598a755732e717b0adca82f884e44d37576Mugunthan V N clk_put(priv->clk); 1770df828598a755732e717b0adca82f884e44d37576Mugunthan V N kfree(priv->slaves); 1771df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_netdev(ndev); 1772df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1773df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1774df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1775df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1776df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_suspend(struct device *dev) 1777df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1778df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct platform_device *pdev = to_platform_device(dev); 1779df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = platform_get_drvdata(pdev); 1780df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1781df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_running(ndev)) 1782df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ndo_stop(ndev); 1783f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_put_sync(&pdev->dev); 1784f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N 1785df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1786df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1787df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1788df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_resume(struct device *dev) 1789df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1790df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct platform_device *pdev = to_platform_device(dev); 1791df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = platform_get_drvdata(pdev); 1792df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1793f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_get_sync(&pdev->dev); 1794df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_running(ndev)) 1795df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ndo_open(ndev); 1796df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1797df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1798df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1799df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic const struct dev_pm_ops cpsw_pm_ops = { 1800df828598a755732e717b0adca82f884e44d37576Mugunthan V N .suspend = cpsw_suspend, 1801df828598a755732e717b0adca82f884e44d37576Mugunthan V N .resume = cpsw_resume, 1802df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1803df828598a755732e717b0adca82f884e44d37576Mugunthan V N 18042eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V Nstatic const struct of_device_id cpsw_of_mtable[] = { 18052eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N { .compatible = "ti,cpsw", }, 18062eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N { /* sentinel */ }, 18072eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N}; 18082eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1809df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic struct platform_driver cpsw_driver = { 1810df828598a755732e717b0adca82f884e44d37576Mugunthan V N .driver = { 1811df828598a755732e717b0adca82f884e44d37576Mugunthan V N .name = "cpsw", 1812df828598a755732e717b0adca82f884e44d37576Mugunthan V N .owner = THIS_MODULE, 1813df828598a755732e717b0adca82f884e44d37576Mugunthan V N .pm = &cpsw_pm_ops, 18142eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N .of_match_table = of_match_ptr(cpsw_of_mtable), 1815df828598a755732e717b0adca82f884e44d37576Mugunthan V N }, 1816df828598a755732e717b0adca82f884e44d37576Mugunthan V N .probe = cpsw_probe, 1817663e12e61d8764ce342588325d1050d9cb5460c0Bill Pemberton .remove = cpsw_remove, 1818df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1819df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1820df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int __init cpsw_init(void) 1821df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1822df828598a755732e717b0adca82f884e44d37576Mugunthan V N return platform_driver_register(&cpsw_driver); 1823df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1824df828598a755732e717b0adca82f884e44d37576Mugunthan V Nlate_initcall(cpsw_init); 1825df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1826df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void __exit cpsw_exit(void) 1827df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1828df828598a755732e717b0adca82f884e44d37576Mugunthan V N platform_driver_unregister(&cpsw_driver); 1829df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1830df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_exit(cpsw_exit); 1831df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1832df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_LICENSE("GPL"); 1833df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_AUTHOR("Cyril Chemparathy <cyril@ti.com>"); 1834df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_AUTHOR("Mugunthan V N <mugunthanvnm@ti.com>"); 1835df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_DESCRIPTION("TI CPSW Ethernet driver"); 1836