cpsw.c revision d3bb9c58b567d240eaaa2dc8bd778696eaed5fbd
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 142d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N#define cpsw_slave_index(priv) \ 143d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N ((priv->data.dual_emac) ? priv->emac_port : \ 144d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N priv->data.active_slave) 145d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N 146df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int debug_level; 147df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_param(debug_level, int, 0); 148df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_PARM_DESC(debug_level, "cpsw debug level (NETIF_MSG bits)"); 149df828598a755732e717b0adca82f884e44d37576Mugunthan V N 150df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int ale_ageout = 10; 151df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_param(ale_ageout, int, 0); 152df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_PARM_DESC(ale_ageout, "cpsw ale ageout interval (seconds)"); 153df828598a755732e717b0adca82f884e44d37576Mugunthan V N 154df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int rx_packet_max = CPSW_MAX_PACKET_SIZE; 155df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_param(rx_packet_max, int, 0); 156df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_PARM_DESC(rx_packet_max, "maximum receive packet size (bytes)"); 157df828598a755732e717b0adca82f884e44d37576Mugunthan V N 158996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochranstruct cpsw_wr_regs { 159df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 id_ver; 160df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 soft_reset; 161df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 control; 162df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 int_control; 163df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_thresh_en; 164df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_en; 165df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 tx_en; 166df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 misc_en; 167df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 168df828598a755732e717b0adca82f884e44d37576Mugunthan V N 169996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochranstruct cpsw_ss_regs { 170df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 id_ver; 171df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 control; 172df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 soft_reset; 173df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 stat_port_en; 174df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 ptype; 175bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 soft_idle; 176bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 thru_rate; 177bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 gap_thresh; 178bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 tx_start_wds; 179bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 flow_control; 180bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 vlan_ltype; 181bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 ts_ltype; 182bd357af2a52259778dfcc06482dc70463b7b1301Richard Cochran u32 dlr_ltype; 183df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 184df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1859750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V1 */ 1869750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_MAX_BLKS 0x00 /* Maximum FIFO Blocks */ 1879750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_BLK_CNT 0x04 /* FIFO Block Usage Count (Read Only) */ 1889750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TX_IN_CTL 0x08 /* Transmit FIFO Control */ 1899750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_PORT_VLAN 0x0c /* VLAN Register */ 1909750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TX_PRI_MAP 0x10 /* Tx Header Priority to Switch Pri Mapping */ 1919750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TS_CTL 0x14 /* Time Sync Control */ 1929750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TS_SEQ_LTYPE 0x18 /* Time Sync Sequence ID Offset and Msg Type */ 1939750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW1_TS_VLAN 0x1c /* Time Sync VLAN1 and VLAN2 */ 1949750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 1959750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V2 */ 1969750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_CONTROL 0x00 /* Control Register */ 1979750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_MAX_BLKS 0x08 /* Maximum FIFO Blocks */ 1989750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_BLK_CNT 0x0c /* FIFO Block Usage Count (Read Only) */ 1999750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_TX_IN_CTL 0x10 /* Transmit FIFO Control */ 2009750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_PORT_VLAN 0x14 /* VLAN Register */ 2019750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */ 2029750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */ 2039750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2049750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V1 and V2 */ 2059750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define SA_LO 0x20 /* CPGMAC_SL Source Address Low */ 2069750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define SA_HI 0x24 /* CPGMAC_SL Source Address High */ 2079750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define SEND_PERCENT 0x28 /* Transmit Queue Send Percentages */ 2089750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2099750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* CPSW_PORT_V2 only */ 2109750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP0 0x30 /* Rx DSCP Priority to Rx Packet Mapping */ 2119750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP1 0x34 /* Rx DSCP Priority to Rx Packet Mapping */ 2129750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP2 0x38 /* Rx DSCP Priority to Rx Packet Mapping */ 2139750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP3 0x3c /* Rx DSCP Priority to Rx Packet Mapping */ 2149750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP4 0x40 /* Rx DSCP Priority to Rx Packet Mapping */ 2159750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP5 0x44 /* Rx DSCP Priority to Rx Packet Mapping */ 2169750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP6 0x48 /* Rx DSCP Priority to Rx Packet Mapping */ 2179750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define RX_DSCP_PRI_MAP7 0x4c /* Rx DSCP Priority to Rx Packet Mapping */ 2189750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2199750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* Bit definitions for the CPSW2_CONTROL register */ 2209750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define PASS_PRI_TAGGED (1<<24) /* Pass Priority Tagged */ 2219750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define VLAN_LTYPE2_EN (1<<21) /* VLAN LTYPE 2 enable */ 2229750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define VLAN_LTYPE1_EN (1<<20) /* VLAN LTYPE 1 enable */ 2239750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define DSCP_PRI_EN (1<<16) /* DSCP Priority Enable */ 2249750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_320 (1<<14) /* Time Sync Dest Port 320 enable */ 2259750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_319 (1<<13) /* Time Sync Dest Port 319 enable */ 2269750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_132 (1<<12) /* Time Sync Dest IP Addr 132 enable */ 2279750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_131 (1<<11) /* Time Sync Dest IP Addr 131 enable */ 2289750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_130 (1<<10) /* Time Sync Dest IP Addr 130 enable */ 2299750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_129 (1<<9) /* Time Sync Dest IP Addr 129 enable */ 2309750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_BIT8 (1<<8) /* ts_ttl_nonzero? */ 2319750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_ANNEX_D_EN (1<<4) /* Time Sync Annex D enable */ 2329750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_LTYPE2_EN (1<<3) /* Time Sync LTYPE 2 enable */ 2339750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_LTYPE1_EN (1<<2) /* Time Sync LTYPE 1 enable */ 2349750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_TX_EN (1<<1) /* Time Sync Transmit Enable */ 2359750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_RX_EN (1<<0) /* Time Sync Receive Enable */ 2369750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2379750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_TS_BITS \ 2389750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran (TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \ 2399750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran TS_ANNEX_D_EN | TS_LTYPE1_EN) 2409750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2419750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN) 2429750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_TX_TS_BITS (CTRL_TS_BITS | TS_TX_EN) 2439750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define CTRL_RX_TS_BITS (CTRL_TS_BITS | TS_RX_EN) 2449750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2459750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* Bit definitions for the CPSW2_TS_SEQ_MTYPE register */ 2469750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_SEQ_ID_OFFSET_SHIFT (16) /* Time Sync Sequence ID Offset */ 2479750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_SEQ_ID_OFFSET_MASK (0x3f) 2489750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_MSG_TYPE_EN_SHIFT (0) /* Time Sync Message Type Enable */ 2499750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define TS_MSG_TYPE_EN_MASK (0xffff) 2509750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 2519750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */ 2529750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3)) 253df828598a755732e717b0adca82f884e44d37576Mugunthan V N 2542e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran/* Bit definitions for the CPSW1_TS_CTL register */ 2552e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_TS_RX_EN BIT(0) 2562e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_TS_TX_EN BIT(4) 2572e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_MSG_TYPE_OFS 16 2582e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 2592e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran/* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */ 2602e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#define CPSW_V1_SEQ_ID_OFS_SHIFT 16 2612e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 262df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_host_regs { 263df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 max_blks; 264df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 blk_cnt; 265d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 tx_in_ctl; 266df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 port_vlan; 267df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 tx_pri_map; 268df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 cpdma_tx_pri_map; 269df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 cpdma_rx_chan_map; 270df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 271df828598a755732e717b0adca82f884e44d37576Mugunthan V N 272df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_sliver_regs { 273df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 id_ver; 274df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_control; 275df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_status; 276df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 soft_reset; 277df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_maxlen; 278df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 __reserved_0; 279df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_pause; 280df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 tx_pause; 281df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 __reserved_1; 282df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 rx_pri_map; 283df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 284df828598a755732e717b0adca82f884e44d37576Mugunthan V N 285df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_slave { 2869750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran void __iomem *regs; 287df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_sliver_regs __iomem *sliver; 288df828598a755732e717b0adca82f884e44d37576Mugunthan V N int slave_num; 289df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_control; 290df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_slave_data *data; 291df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct phy_device *phy; 292d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct net_device *ndev; 293d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 port_vlan; 294d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 open_stat; 295df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 296df828598a755732e717b0adca82f884e44d37576Mugunthan V N 2979750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochranstatic inline u32 slave_read(struct cpsw_slave *slave, u32 offset) 2989750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran{ 2999750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran return __raw_readl(slave->regs + offset); 3009750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran} 3019750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 3029750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochranstatic inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset) 3039750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran{ 3049750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran __raw_writel(val, slave->regs + offset); 3059750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran} 3069750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 307df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstruct cpsw_priv { 308df828598a755732e717b0adca82f884e44d37576Mugunthan V N spinlock_t lock; 309df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct platform_device *pdev; 310df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev; 311df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct resource *cpsw_res; 312a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran struct resource *cpsw_wr_res; 313df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct napi_struct napi; 314df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct device *dev; 315df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_platform_data data; 316996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran struct cpsw_ss_regs __iomem *regs; 317996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran struct cpsw_wr_regs __iomem *wr_regs; 318df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_host_regs __iomem *host_port_regs; 319df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 msg_enable; 320e90cfac6c281da3c8b89dba0eb783c23872705b1Richard Cochran u32 version; 321df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device_stats stats; 322df828598a755732e717b0adca82f884e44d37576Mugunthan V N int rx_packet_max; 323df828598a755732e717b0adca82f884e44d37576Mugunthan V N int host_port; 324df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct clk *clk; 325df828598a755732e717b0adca82f884e44d37576Mugunthan V N u8 mac_addr[ETH_ALEN]; 326df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_slave *slaves; 327df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpdma_ctlr *dma; 328df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpdma_chan *txch, *rxch; 329df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_ale *ale; 330df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* snapshot of IRQ numbers */ 331df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 irqs_table[4]; 332df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 num_irqs; 3339232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N struct cpts *cpts; 334d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 emac_port; 335df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 336df828598a755732e717b0adca82f884e44d37576Mugunthan V N 337df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi) 338d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define for_each_slave(priv, func, arg...) \ 339d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N do { \ 340d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N int idx; \ 341d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) \ 342d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N (func)((priv)->slaves + priv->emac_port, ##arg);\ 343d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else \ 344d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (idx = 0; idx < (priv)->data.slaves; idx++) \ 345d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N (func)((priv)->slaves + idx, ##arg); \ 346d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } while (0) 347d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_get_slave_ndev(priv, __slave_no__) \ 348d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N (priv->slaves[__slave_no__].ndev) 349d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_get_slave_priv(priv, __slave_no__) \ 350d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ((priv->slaves[__slave_no__].ndev) ? \ 351d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N netdev_priv(priv->slaves[__slave_no__].ndev) : NULL) \ 352d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 353d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb) \ 354d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N do { \ 355d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) \ 356d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N break; \ 357d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (CPDMA_RX_SOURCE_PORT(status) == 1) { \ 358d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev = cpsw_get_slave_ndev(priv, 0); \ 359d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv = netdev_priv(ndev); \ 360d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->dev = ndev; \ 361d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else if (CPDMA_RX_SOURCE_PORT(status) == 2) { \ 362d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev = cpsw_get_slave_ndev(priv, 1); \ 363d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv = netdev_priv(ndev); \ 364d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->dev = ndev; \ 365d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } \ 366df828598a755732e717b0adca82f884e44d37576Mugunthan V N } while (0) 367d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N#define cpsw_add_mcast(priv, addr) \ 368d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N do { \ 369d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) { \ 370d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_slave *slave = priv->slaves + \ 371d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->emac_port; \ 372d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N int slave_port = cpsw_get_slave_port(priv, \ 373d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave->slave_num); \ 374d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, addr, \ 375d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1 << slave_port | 1 << priv->host_port, \ 376d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ALE_VLAN, slave->port_vlan, 0); \ 377d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { \ 378d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, addr, \ 379d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ALE_ALL_PORTS << priv->host_port, \ 380d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 0, 0, 0); \ 381d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } \ 382d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } while (0) 383d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 384d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num) 385d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 386d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->host_port == 0) 387d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return slave_num + 1; 388d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 389d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return slave_num; 390d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 391df828598a755732e717b0adca82f884e44d37576Mugunthan V N 3925c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V Nstatic void cpsw_ndo_set_rx_mode(struct net_device *ndev) 3935c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N{ 3945c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 3955c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 3965c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N if (ndev->flags & IFF_PROMISC) { 3975c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N /* Enable promiscuous mode */ 3985c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N dev_err(priv->dev, "Ignoring Promiscuous mode\n"); 3995c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N return; 4005c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N } 4015c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 4025c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N /* Clear all mcast from ALE */ 4035c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port); 4045c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 4055c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N if (!netdev_mc_empty(ndev)) { 4065c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N struct netdev_hw_addr *ha; 4075c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 4085c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N /* program multicast address list into ALE register */ 4095c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N netdev_for_each_mc_addr(ha, ndev) { 410d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_add_mcast(priv, (u8 *)ha->addr); 4115c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N } 4125c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N } 4135c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N} 4145c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N 415df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_intr_enable(struct cpsw_priv *priv) 416df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 417996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0xFF, &priv->wr_regs->tx_en); 418996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0xFF, &priv->wr_regs->rx_en); 419df828598a755732e717b0adca82f884e44d37576Mugunthan V N 420df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, true); 421df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 422df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 423df828598a755732e717b0adca82f884e44d37576Mugunthan V N 424df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_intr_disable(struct cpsw_priv *priv) 425df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 426996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0, &priv->wr_regs->tx_en); 427996a5c27880e40a7e5be2687ee9e486c09bbb29cRichard Cochran __raw_writel(0, &priv->wr_regs->rx_en); 428df828598a755732e717b0adca82f884e44d37576Mugunthan V N 429df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 430df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 431df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 432df828598a755732e717b0adca82f884e44d37576Mugunthan V N 433df828598a755732e717b0adca82f884e44d37576Mugunthan V Nvoid cpsw_tx_handler(void *token, int len, int status) 434df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 435df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct sk_buff *skb = token; 436df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = skb->dev; 437df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 438df828598a755732e717b0adca82f884e44d37576Mugunthan V N 439fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N /* Check whether the queue is stopped due to stalled tx dma, if the 440fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N * queue is stopped then start the queue as we have free desc for tx 441fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N */ 442df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(netif_queue_stopped(ndev))) 443df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_start_queue(ndev); 4449232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N cpts_tx_timestamp(priv->cpts, skb); 445df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_packets++; 446df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_bytes += len; 447df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_kfree_skb_any(skb); 448df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 449df828598a755732e717b0adca82f884e44d37576Mugunthan V N 450df828598a755732e717b0adca82f884e44d37576Mugunthan V Nvoid cpsw_rx_handler(void *token, int len, int status) 451df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 452df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct sk_buff *skb = token; 453df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = skb->dev; 454df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 455df828598a755732e717b0adca82f884e44d37576Mugunthan V N int ret = 0; 456df828598a755732e717b0adca82f884e44d37576Mugunthan V N 457d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_dual_emac_src_port_detect(status, priv, ndev, skb); 458d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 459df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* free and bail if we are shutting down */ 460df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(!netif_running(ndev)) || 461df828598a755732e717b0adca82f884e44d37576Mugunthan V N unlikely(!netif_carrier_ok(ndev))) { 462df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_kfree_skb_any(skb); 463df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 464df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 465df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (likely(status >= 0)) { 466df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb_put(skb, len); 4679232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N cpts_rx_timestamp(priv->cpts, skb); 468df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb->protocol = eth_type_trans(skb, ndev); 469df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_receive_skb(skb); 470df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.rx_bytes += len; 471df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.rx_packets++; 472df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb = NULL; 473df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 474df828598a755732e717b0adca82f884e44d37576Mugunthan V N 475df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(!netif_running(ndev))) { 476df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (skb) 477df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_kfree_skb_any(skb); 478df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 479df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 480df828598a755732e717b0adca82f884e44d37576Mugunthan V N 481df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (likely(!skb)) { 482df828598a755732e717b0adca82f884e44d37576Mugunthan V N skb = netdev_alloc_skb_ip_align(ndev, priv->rx_packet_max); 483df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (WARN_ON(!skb)) 484df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 485df828598a755732e717b0adca82f884e44d37576Mugunthan V N 486df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = cpdma_chan_submit(priv->rxch, skb, skb->data, 487f6e135c81eeb648c6addc6aeff2ee80f28ea413bMugunthan V N skb_tailroom(skb), 0, GFP_KERNEL); 488df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 489df828598a755732e717b0adca82f884e44d37576Mugunthan V N WARN_ON(ret < 0); 490df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 491df828598a755732e717b0adca82f884e44d37576Mugunthan V N 492df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic irqreturn_t cpsw_interrupt(int irq, void *dev_id) 493df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 494df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = dev_id; 495df828598a755732e717b0adca82f884e44d37576Mugunthan V N 496df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (likely(netif_running(priv->ndev))) { 497df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_disable(priv); 498df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_disable_irq(priv); 499df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_schedule(&priv->napi); 500d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { 501d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv = cpsw_get_slave_priv(priv, 1); 502d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (likely(priv) && likely(netif_running(priv->ndev))) { 503d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_intr_disable(priv); 504d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_disable_irq(priv); 505d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N napi_schedule(&priv->napi); 506d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 507df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 508df828598a755732e717b0adca82f884e44d37576Mugunthan V N return IRQ_HANDLED; 509df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 510df828598a755732e717b0adca82f884e44d37576Mugunthan V N 511df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_poll(struct napi_struct *napi, int budget) 512df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 513df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = napi_to_priv(napi); 514df828598a755732e717b0adca82f884e44d37576Mugunthan V N int num_tx, num_rx; 515df828598a755732e717b0adca82f884e44d37576Mugunthan V N 516df828598a755732e717b0adca82f884e44d37576Mugunthan V N num_tx = cpdma_chan_process(priv->txch, 128); 517510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N if (num_tx) 518510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); 519df828598a755732e717b0adca82f884e44d37576Mugunthan V N 520510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N num_rx = cpdma_chan_process(priv->rxch, budget); 521df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (num_rx < budget) { 522df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_complete(napi); 523df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 524510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); 525df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_enable_irq(priv); 526df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 527df828598a755732e717b0adca82f884e44d37576Mugunthan V N 528510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N if (num_rx || num_tx) 529510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n", 530510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N num_rx, num_tx); 531510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N 532df828598a755732e717b0adca82f884e44d37576Mugunthan V N return num_rx; 533df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 534df828598a755732e717b0adca82f884e44d37576Mugunthan V N 535df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic inline void soft_reset(const char *module, void __iomem *reg) 536df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 537df828598a755732e717b0adca82f884e44d37576Mugunthan V N unsigned long timeout = jiffies + HZ; 538df828598a755732e717b0adca82f884e44d37576Mugunthan V N 539df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(1, reg); 540df828598a755732e717b0adca82f884e44d37576Mugunthan V N do { 541df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpu_relax(); 542df828598a755732e717b0adca82f884e44d37576Mugunthan V N } while ((__raw_readl(reg) & 1) && time_after(timeout, jiffies)); 543df828598a755732e717b0adca82f884e44d37576Mugunthan V N 544df828598a755732e717b0adca82f884e44d37576Mugunthan V N WARN(__raw_readl(reg) & 1, "failed to soft-reset %s\n", module); 545df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 546df828598a755732e717b0adca82f884e44d37576Mugunthan V N 547df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \ 548df828598a755732e717b0adca82f884e44d37576Mugunthan V N ((mac)[2] << 16) | ((mac)[3] << 24)) 549df828598a755732e717b0adca82f884e44d37576Mugunthan V N#define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8)) 550df828598a755732e717b0adca82f884e44d37576Mugunthan V N 551df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_set_slave_mac(struct cpsw_slave *slave, 552df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv) 553df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 5549750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, mac_hi(priv->mac_addr), SA_HI); 5559750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, mac_lo(priv->mac_addr), SA_LO); 556df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 557df828598a755732e717b0adca82f884e44d37576Mugunthan V N 558df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void _cpsw_adjust_link(struct cpsw_slave *slave, 559df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv, bool *link) 560df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 561df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct phy_device *phy = slave->phy; 562df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 mac_control = 0; 563df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 slave_port; 564df828598a755732e717b0adca82f884e44d37576Mugunthan V N 565df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!phy) 566df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 567df828598a755732e717b0adca82f884e44d37576Mugunthan V N 568df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave_port = cpsw_get_slave_port(priv, slave->slave_num); 569df828598a755732e717b0adca82f884e44d37576Mugunthan V N 570df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (phy->link) { 571df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control = priv->data.mac_control; 572df828598a755732e717b0adca82f884e44d37576Mugunthan V N 573df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* enable forwarding */ 574df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_control_set(priv->ale, slave_port, 575df828598a755732e717b0adca82f884e44d37576Mugunthan V N ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 576df828598a755732e717b0adca82f884e44d37576Mugunthan V N 577df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (phy->speed == 1000) 578df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control |= BIT(7); /* GIGABITEN */ 579df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (phy->duplex) 580df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control |= BIT(0); /* FULLDUPLEXEN */ 581342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack 582342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack /* set speed_in input in case RMII mode is used in 100Mbps */ 583342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack if (phy->speed == 100) 584342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack mac_control |= BIT(15); 585342b7b741d76bc8aadeff844634348bb2a343d19Daniel Mack 586df828598a755732e717b0adca82f884e44d37576Mugunthan V N *link = true; 587df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 588df828598a755732e717b0adca82f884e44d37576Mugunthan V N mac_control = 0; 589df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* disable forwarding */ 590df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_control_set(priv->ale, slave_port, 591df828598a755732e717b0adca82f884e44d37576Mugunthan V N ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); 592df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 593df828598a755732e717b0adca82f884e44d37576Mugunthan V N 594df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (mac_control != slave->mac_control) { 595df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_print_status(phy); 596df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(mac_control, &slave->sliver->mac_control); 597df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 598df828598a755732e717b0adca82f884e44d37576Mugunthan V N 599df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->mac_control = mac_control; 600df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 601df828598a755732e717b0adca82f884e44d37576Mugunthan V N 602df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_adjust_link(struct net_device *ndev) 603df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 604df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 605df828598a755732e717b0adca82f884e44d37576Mugunthan V N bool link = false; 606df828598a755732e717b0adca82f884e44d37576Mugunthan V N 607df828598a755732e717b0adca82f884e44d37576Mugunthan V N for_each_slave(priv, _cpsw_adjust_link, priv, &link); 608df828598a755732e717b0adca82f884e44d37576Mugunthan V N 609df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (link) { 610df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_on(ndev); 611df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_running(ndev)) 612df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_wake_queue(ndev); 613df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 614df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_off(ndev); 615df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_stop_queue(ndev); 616df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 617df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 618df828598a755732e717b0adca82f884e44d37576Mugunthan V N 619df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic inline int __show_stat(char *buf, int maxlen, const char *name, u32 val) 620df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 621df828598a755732e717b0adca82f884e44d37576Mugunthan V N static char *leader = "........................................"; 622df828598a755732e717b0adca82f884e44d37576Mugunthan V N 623df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!val) 624df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 625df828598a755732e717b0adca82f884e44d37576Mugunthan V N else 626df828598a755732e717b0adca82f884e44d37576Mugunthan V N return snprintf(buf, maxlen, "%s %s %10d\n", name, 627df828598a755732e717b0adca82f884e44d37576Mugunthan V N leader + strlen(name), val); 628df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 629df828598a755732e717b0adca82f884e44d37576Mugunthan V N 630d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic int cpsw_common_res_usage_state(struct cpsw_priv *priv) 631d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 632d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 i; 633d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 usage_count = 0; 634d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 635d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) 636d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return 0; 637d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 638d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (i = 0; i < priv->data.slaves; i++) 639d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->slaves[i].open_stat) 640d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N usage_count++; 641d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 642d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return usage_count; 643d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 644d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 645d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic inline int cpsw_tx_packet_submit(struct net_device *ndev, 646d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv, struct sk_buff *skb) 647d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 648d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) 649d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return cpdma_chan_submit(priv->txch, skb, skb->data, 650d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->len, 0, GFP_KERNEL); 651d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 652d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (ndev == cpsw_get_slave_ndev(priv, 0)) 653d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return cpdma_chan_submit(priv->txch, skb, skb->data, 654d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->len, 1, GFP_KERNEL); 655d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 656d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return cpdma_chan_submit(priv->txch, skb, skb->data, 657d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb->len, 2, GFP_KERNEL); 658d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 659d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 660d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic inline void cpsw_add_dual_emac_def_ale_entries( 661d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv, struct cpsw_slave *slave, 662d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 slave_port) 663d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 664d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 port_mask = 1 << slave_port | 1 << priv->host_port; 665d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 666d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->version == CPSW_VERSION_1) 667d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN); 668d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 669d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN); 670d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask, 671d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N port_mask, port_mask, 0); 672d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 673d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N port_mask, ALE_VLAN, slave->port_vlan, 0); 674d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_ucast(priv->ale, priv->mac_addr, 675d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->host_port, ALE_VLAN, slave->port_vlan); 676d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 677d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 678df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) 679df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 680df828598a755732e717b0adca82f884e44d37576Mugunthan V N char name[32]; 681df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 slave_port; 682df828598a755732e717b0adca82f884e44d37576Mugunthan V N 683df828598a755732e717b0adca82f884e44d37576Mugunthan V N sprintf(name, "slave-%d", slave->slave_num); 684df828598a755732e717b0adca82f884e44d37576Mugunthan V N 685df828598a755732e717b0adca82f884e44d37576Mugunthan V N soft_reset(name, &slave->sliver->soft_reset); 686df828598a755732e717b0adca82f884e44d37576Mugunthan V N 687df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* setup priority mapping */ 688df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(RX_PRIORITY_MAPPING, &slave->sliver->rx_pri_map); 6899750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran 6909750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran switch (priv->version) { 6919750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran case CPSW_VERSION_1: 6929750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP); 6939750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran break; 6949750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran case CPSW_VERSION_2: 6959750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP); 6969750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran break; 6979750a3ade7b635a18f04371b4fddad0de0b4e6d8Richard Cochran } 698df828598a755732e717b0adca82f884e44d37576Mugunthan V N 699df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* setup max packet size, and mac address */ 700df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(priv->rx_packet_max, &slave->sliver->rx_maxlen); 701df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_set_slave_mac(slave, priv); 702df828598a755732e717b0adca82f884e44d37576Mugunthan V N 703df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->mac_control = 0; /* no link yet */ 704df828598a755732e717b0adca82f884e44d37576Mugunthan V N 705df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave_port = cpsw_get_slave_port(priv, slave->slave_num); 706df828598a755732e717b0adca82f884e44d37576Mugunthan V N 707d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 708d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port); 709d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 710d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 711d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1 << slave_port, 0, 0, ALE_MCAST_FWD_2); 712df828598a755732e717b0adca82f884e44d37576Mugunthan V N 713df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy = phy_connect(priv->ndev, slave->data->phy_id, 714f9a8f83b04e0c362a2fc660dbad980d24af209fcFlorian Fainelli &cpsw_adjust_link, slave->data->phy_if); 715df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (IS_ERR(slave->phy)) { 716df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "phy %s not found on slave %d\n", 717df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->data->phy_id, slave->slave_num); 718df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy = NULL; 719df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 720df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_info(priv->dev, "phy found : id is : 0x%x\n", 721df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy->phy_id); 722df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_start(slave->phy); 723df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 724df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 725df828598a755732e717b0adca82f884e44d37576Mugunthan V N 7263b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic inline void cpsw_add_default_vlan(struct cpsw_priv *priv) 7273b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 7283b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N const int vlan = priv->data.default_vlan; 7293b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N const int port = priv->host_port; 7303b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N u32 reg; 7313b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N int i; 7323b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7333b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN : 7343b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N CPSW2_PORT_VLAN; 7353b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7363b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N writel(vlan, &priv->host_port_regs->port_vlan); 7373b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7380237c11044b3670adcbe80cd6dd721285347f497Daniel Mack for (i = 0; i < priv->data.slaves; i++) 7393b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N slave_write(priv->slaves + i, vlan, reg); 7403b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 7413b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, 7423b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_ALL_PORTS << port, ALE_ALL_PORTS << port, 7433b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N (ALE_PORT_1 | ALE_PORT_2) << port); 7443b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 7453b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 746df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_init_host_port(struct cpsw_priv *priv) 747df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 7483b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N u32 control_reg; 749d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N u32 fifo_mode; 7503b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 751df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* soft reset the controller and initialize ale */ 752df828598a755732e717b0adca82f884e44d37576Mugunthan V N soft_reset("cpsw", &priv->regs->soft_reset); 753df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_start(priv->ale); 754df828598a755732e717b0adca82f884e44d37576Mugunthan V N 755df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* switch to vlan unaware mode */ 7563b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_control_set(priv->ale, priv->host_port, ALE_VLAN_AWARE, 7573b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N CPSW_ALE_VLAN_AWARE); 7583b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N control_reg = readl(&priv->regs->control); 7593b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N control_reg |= CPSW_VLAN_AWARE; 7603b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N writel(control_reg, &priv->regs->control); 761d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE : 762d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N CPSW_FIFO_NORMAL_MODE; 763d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N writel(fifo_mode, &priv->host_port_regs->tx_in_ctl); 764df828598a755732e717b0adca82f884e44d37576Mugunthan V N 765df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* setup host port priority mapping */ 766df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(CPDMA_TX_PRIORITY_MAP, 767df828598a755732e717b0adca82f884e44d37576Mugunthan V N &priv->host_port_regs->cpdma_tx_pri_map); 768df828598a755732e717b0adca82f884e44d37576Mugunthan V N __raw_writel(0, &priv->host_port_regs->cpdma_rx_chan_map); 769df828598a755732e717b0adca82f884e44d37576Mugunthan V N 770df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_control_set(priv->ale, priv->host_port, 771df828598a755732e717b0adca82f884e44d37576Mugunthan V N ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 772df828598a755732e717b0adca82f884e44d37576Mugunthan V N 773d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) { 774d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 775d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 0, 0); 776d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 777d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2); 778d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 779df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 780df828598a755732e717b0adca82f884e44d37576Mugunthan V N 781df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_ndo_open(struct net_device *ndev) 782df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 783df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 784df828598a755732e717b0adca82f884e44d37576Mugunthan V N int i, ret; 785df828598a755732e717b0adca82f884e44d37576Mugunthan V N u32 reg; 786df828598a755732e717b0adca82f884e44d37576Mugunthan V N 787d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!cpsw_common_res_usage_state(priv)) 788d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_intr_disable(priv); 789df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_off(ndev); 790df828598a755732e717b0adca82f884e44d37576Mugunthan V N 791f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_get_sync(&priv->pdev->dev); 792df828598a755732e717b0adca82f884e44d37576Mugunthan V N 793549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran reg = priv->version; 794df828598a755732e717b0adca82f884e44d37576Mugunthan V N 795df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_info(priv->dev, "initializing cpsw version %d.%d (%d)\n", 796df828598a755732e717b0adca82f884e44d37576Mugunthan V N CPSW_MAJOR_VERSION(reg), CPSW_MINOR_VERSION(reg), 797df828598a755732e717b0adca82f884e44d37576Mugunthan V N CPSW_RTL_VERSION(reg)); 798df828598a755732e717b0adca82f884e44d37576Mugunthan V N 799df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* initialize host and slave ports */ 800d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!cpsw_common_res_usage_state(priv)) 801d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_init_host_port(priv); 802df828598a755732e717b0adca82f884e44d37576Mugunthan V N for_each_slave(priv, cpsw_slave_open, priv); 803df828598a755732e717b0adca82f884e44d37576Mugunthan V N 8043b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N /* Add default VLAN */ 805d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!priv->data.dual_emac) 806d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_add_default_vlan(priv); 8073b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 808d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!cpsw_common_res_usage_state(priv)) { 809d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* setup tx dma to fixed prio and zero offset */ 810d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1); 811d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0); 812df828598a755732e717b0adca82f884e44d37576Mugunthan V N 813d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* disable priority elevation */ 814d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N __raw_writel(0, &priv->regs->ptype); 815df828598a755732e717b0adca82f884e44d37576Mugunthan V N 816d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* enable statistics collection only on all ports */ 817d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N __raw_writel(0x7, &priv->regs->stat_port_en); 818df828598a755732e717b0adca82f884e44d37576Mugunthan V N 819d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (WARN_ON(!priv->data.rx_descs)) 820d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->data.rx_descs = 128; 821df828598a755732e717b0adca82f884e44d37576Mugunthan V N 822d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (i = 0; i < priv->data.rx_descs; i++) { 823d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct sk_buff *skb; 824df828598a755732e717b0adca82f884e44d37576Mugunthan V N 825d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = -ENOMEM; 826d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N skb = netdev_alloc_skb_ip_align(priv->ndev, 827d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->rx_packet_max); 828d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!skb) 829d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N break; 830d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = cpdma_chan_submit(priv->rxch, skb, skb->data, 831f6e135c81eeb648c6addc6aeff2ee80f28ea413bMugunthan V N skb_tailroom(skb), 0, GFP_KERNEL); 832d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (WARN_ON(ret < 0)) 833d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N break; 834d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 835d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* continue even if we didn't manage to submit all 836d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N * receive descs 837d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N */ 838d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i); 839df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 840df828598a755732e717b0adca82f884e44d37576Mugunthan V N 841df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_start(priv->dma); 842df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 843df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_enable(&priv->napi); 844510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); 845510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); 846df828598a755732e717b0adca82f884e44d37576Mugunthan V N 847d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 848d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[priv->emac_port].open_stat = true; 849df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 850df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 851df828598a755732e717b0adca82f884e44d37576Mugunthan V N 852df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv) 853df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 854df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!slave->phy) 855df828598a755732e717b0adca82f884e44d37576Mugunthan V N return; 856df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_stop(slave->phy); 857df828598a755732e717b0adca82f884e44d37576Mugunthan V N phy_disconnect(slave->phy); 858df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->phy = NULL; 859df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 860df828598a755732e717b0adca82f884e44d37576Mugunthan V N 861df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_ndo_stop(struct net_device *ndev) 862df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 863df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 864df828598a755732e717b0adca82f884e44d37576Mugunthan V N 865df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_info(priv, ifdown, "shutting down cpsw device\n"); 866df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_stop_queue(priv->ndev); 867df828598a755732e717b0adca82f884e44d37576Mugunthan V N napi_disable(&priv->napi); 868df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_carrier_off(priv->ndev); 869d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 870d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (cpsw_common_res_usage_state(priv) <= 1) { 871d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_intr_disable(priv); 872d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 873d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpdma_ctlr_stop(priv->dma); 874d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_ale_stop(priv->ale); 875d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 876df828598a755732e717b0adca82f884e44d37576Mugunthan V N for_each_slave(priv, cpsw_slave_stop, priv); 877f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_put_sync(&priv->pdev->dev); 878d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 879d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[priv->emac_port].open_stat = false; 880df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 881df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 882df828598a755732e717b0adca82f884e44d37576Mugunthan V N 883df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, 884df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev) 885df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 886df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 887df828598a755732e717b0adca82f884e44d37576Mugunthan V N int ret; 888df828598a755732e717b0adca82f884e44d37576Mugunthan V N 889df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev->trans_start = jiffies; 890df828598a755732e717b0adca82f884e44d37576Mugunthan V N 891df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (skb_padto(skb, CPSW_MIN_PACKET_SIZE)) { 892df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_err(priv, tx_err, "packet pad failed\n"); 893df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_dropped++; 894df828598a755732e717b0adca82f884e44d37576Mugunthan V N return NETDEV_TX_OK; 895df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 896df828598a755732e717b0adca82f884e44d37576Mugunthan V N 8979232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && 8989232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts->tx_enable) 8992e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 9002e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9012e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran skb_tx_timestamp(skb); 9022e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 903d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = cpsw_tx_packet_submit(ndev, priv, skb); 904df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (unlikely(ret != 0)) { 905df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_err(priv, tx_err, "desc submit failed\n"); 906df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto fail; 907df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 908df828598a755732e717b0adca82f884e44d37576Mugunthan V N 909fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N /* If there is no more tx desc left free then we need to 910fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N * tell the kernel to stop sending us tx frames. 911fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N */ 912fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N if (unlikely(cpdma_check_free_tx_desc(priv->txch))) 913fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N netif_stop_queue(ndev); 914fae50823d0ee579e006a7ba2b20880e354388b25Mugunthan V N 915df828598a755732e717b0adca82f884e44d37576Mugunthan V N return NETDEV_TX_OK; 916df828598a755732e717b0adca82f884e44d37576Mugunthan V Nfail: 917df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_dropped++; 918df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_stop_queue(ndev); 919df828598a755732e717b0adca82f884e44d37576Mugunthan V N return NETDEV_TX_BUSY; 920df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 921df828598a755732e717b0adca82f884e44d37576Mugunthan V N 922df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags) 923df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 924df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* 925df828598a755732e717b0adca82f884e44d37576Mugunthan V N * The switch cannot operate in promiscuous mode without substantial 926df828598a755732e717b0adca82f884e44d37576Mugunthan V N * headache. For promiscuous mode to work, we would need to put the 927df828598a755732e717b0adca82f884e44d37576Mugunthan V N * ALE in bypass mode and route all traffic to the host port. 928df828598a755732e717b0adca82f884e44d37576Mugunthan V N * Subsequently, the host will need to operate as a "bridge", learn, 929df828598a755732e717b0adca82f884e44d37576Mugunthan V N * and flood as needed. For now, we simply complain here and 930df828598a755732e717b0adca82f884e44d37576Mugunthan V N * do nothing about it :-) 931df828598a755732e717b0adca82f884e44d37576Mugunthan V N */ 932df828598a755732e717b0adca82f884e44d37576Mugunthan V N if ((flags & IFF_PROMISC) && (ndev->flags & IFF_PROMISC)) 933df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(&ndev->dev, "promiscuity ignored!\n"); 934df828598a755732e717b0adca82f884e44d37576Mugunthan V N 935df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* 936df828598a755732e717b0adca82f884e44d37576Mugunthan V N * The switch cannot filter multicast traffic unless it is configured 937df828598a755732e717b0adca82f884e44d37576Mugunthan V N * in "VLAN Aware" mode. Unfortunately, VLAN awareness requires a 938df828598a755732e717b0adca82f884e44d37576Mugunthan V N * whole bunch of additional logic that this driver does not implement 939df828598a755732e717b0adca82f884e44d37576Mugunthan V N * at present. 940df828598a755732e717b0adca82f884e44d37576Mugunthan V N */ 941df828598a755732e717b0adca82f884e44d37576Mugunthan V N if ((flags & IFF_ALLMULTI) && !(ndev->flags & IFF_ALLMULTI)) 942df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n"); 943df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 944df828598a755732e717b0adca82f884e44d37576Mugunthan V N 9452e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#ifdef CONFIG_TI_CPTS 9462e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9472e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic void cpsw_hwtstamp_v1(struct cpsw_priv *priv) 9482e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 949e86ac13b031cf71d8f40ff513e627aac80e6b765Mugunthan V N struct cpsw_slave *slave = &priv->slaves[priv->data.active_slave]; 9502e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran u32 ts_en, seq_id; 9512e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9529232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (!priv->cpts->tx_enable && !priv->cpts->rx_enable) { 9532e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, 0, CPSW1_TS_CTL); 9542e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return; 9552e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 9562e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9572e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588; 9582e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS; 9592e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9609232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->tx_enable) 9612e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ts_en |= CPSW_V1_TS_TX_EN; 9622e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9639232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->rx_enable) 9642e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ts_en |= CPSW_V1_TS_RX_EN; 9652e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9662e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, ts_en, CPSW1_TS_CTL); 9672e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, seq_id, CPSW1_TS_SEQ_LTYPE); 9682e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 9692e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9702e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic void cpsw_hwtstamp_v2(struct cpsw_priv *priv) 9712e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 972d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_slave *slave; 9732e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran u32 ctrl, mtype; 9742e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 975d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) 976d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave = &priv->slaves[priv->emac_port]; 977d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N else 978e86ac13b031cf71d8f40ff513e627aac80e6b765Mugunthan V N slave = &priv->slaves[priv->data.active_slave]; 979d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 9802e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl = slave_read(slave, CPSW2_CONTROL); 9812e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl &= ~CTRL_ALL_TS_MASK; 9822e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9839232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->tx_enable) 9842e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl |= CTRL_TX_TS_BITS; 9852e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9869232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (priv->cpts->rx_enable) 9872e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran ctrl |= CTRL_RX_TS_BITS; 9882e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9892e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS; 9902e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9912e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE); 9922e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran slave_write(slave, ctrl, CPSW2_CONTROL); 9932e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran __raw_writel(ETH_P_1588, &priv->regs->ts_ltype); 9942e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 9952e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 9963177bf6f922f62743133abbcbbbb5545f4133b2dMugunthan V Nstatic int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 9972e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 9983177bf6f922f62743133abbcbbbb5545f4133b2dMugunthan V N struct cpsw_priv *priv = netdev_priv(dev); 9999232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N struct cpts *cpts = priv->cpts; 10002e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran struct hwtstamp_config cfg; 10012e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10022e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) 10032e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -EFAULT; 10042e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10052e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran /* reserved for future extensions */ 10062e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (cfg.flags) 10072e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -EINVAL; 10082e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10092e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran switch (cfg.tx_type) { 10102e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_TX_OFF: 10112e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->tx_enable = 0; 10122e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10132e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_TX_ON: 10142e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->tx_enable = 1; 10152e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10162e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran default: 10172e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ERANGE; 10182e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 10192e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10202e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran switch (cfg.rx_filter) { 10212e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_NONE: 10222e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->rx_enable = 0; 10232e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10242e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_ALL: 10252e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 10262e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 10272e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 10282e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ERANGE; 10292e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 10302e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 10312e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 10322e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 10332e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 10342e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 10352e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_EVENT: 10362e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_SYNC: 10372e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 10382e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpts->rx_enable = 1; 10392e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 10402e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10412e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran default: 10422e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ERANGE; 10432e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 10442e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10452e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran switch (priv->version) { 10462e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case CPSW_VERSION_1: 10472e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpsw_hwtstamp_v1(priv); 10482e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10492e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran case CPSW_VERSION_2: 10502e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran cpsw_hwtstamp_v2(priv); 10512e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran break; 10522e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran default: 10532e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ENOTSUPP; 10542e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran } 10552e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10562e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 10572e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 10582e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10592e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#endif /*CONFIG_TI_CPTS*/ 10602e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10612e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) 10622e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 10632e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (!netif_running(dev)) 10642e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -EINVAL; 10652e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 10662e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#ifdef CONFIG_TI_CPTS 10672e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran if (cmd == SIOCSHWTSTAMP) 10683177bf6f922f62743133abbcbbbb5545f4133b2dMugunthan V N return cpsw_hwtstamp_ioctl(dev, req); 10692e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#endif 10702e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return -ENOTSUPP; 10712e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 10722e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 1073df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_ndo_tx_timeout(struct net_device *ndev) 1074df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1075df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1076df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1077df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_err(priv, tx_err, "transmit timeout, restarting dma\n"); 1078df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->stats.tx_errors++; 1079df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_disable(priv); 1080df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 1081df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_stop(priv->txch); 1082df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_start(priv->txch); 1083df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, true); 1084df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 1085510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); 1086510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); 1087510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N 1088df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1089df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1090df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev) 1091df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1092df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1093df828598a755732e717b0adca82f884e44d37576Mugunthan V N return &priv->stats; 1094df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1095df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1096df828598a755732e717b0adca82f884e44d37576Mugunthan V N#ifdef CONFIG_NET_POLL_CONTROLLER 1097df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_ndo_poll_controller(struct net_device *ndev) 1098df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1099df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1100df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1101df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_disable(priv); 1102df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, false); 1103df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_interrupt(ndev->irq, priv); 1104df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_int_ctrl(priv->dma, true); 1105df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_intr_enable(priv); 1106510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); 1107510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); 1108510a1e7249298f6bbd049e1ec98041ddf5ef6452Mugunthan V N 1109df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1110df828598a755732e717b0adca82f884e44d37576Mugunthan V N#endif 1111df828598a755732e717b0adca82f884e44d37576Mugunthan V N 11123b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, 11133b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N unsigned short vid) 11143b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 11153b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N int ret; 11163b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11173b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_add_vlan(priv->ale, vid, 11183b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_ALL_PORTS << priv->host_port, 11193b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 0, ALE_ALL_PORTS << priv->host_port, 11203b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N (ALE_PORT_1 | ALE_PORT_2) << priv->host_port); 11213b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11223b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11233b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11243b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_add_ucast(priv->ale, priv->mac_addr, 11253b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N priv->host_port, ALE_VLAN, vid); 11263b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11273b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N goto clean_vid; 11283b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11293b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 11303b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_ALL_PORTS << priv->host_port, 11313b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ALE_VLAN, vid, 0); 11323b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11333b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N goto clean_vlan_ucast; 11343b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return 0; 11353b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11363b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nclean_vlan_ucast: 11373b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_del_ucast(priv->ale, priv->mac_addr, 11383b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N priv->host_port, ALE_VLAN, vid); 11393b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nclean_vid: 11403b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N cpsw_ale_del_vlan(priv->ale, vid, 0); 11413b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11423b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 11433b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11443b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, 11453b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N unsigned short vid) 11463b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 11473b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 11483b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11493b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (vid == priv->data.default_vlan) 11503b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return 0; 11513b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11523b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid); 11533b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return cpsw_add_vlan_ale_entry(priv, vid); 11543b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 11553b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11563b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V Nstatic int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, 11573b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N unsigned short vid) 11583b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N{ 11593b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 11603b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N int ret; 11613b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11623b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (vid == priv->data.default_vlan) 11633b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return 0; 11643b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11653b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid); 11663b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_del_vlan(priv->ale, vid, 0); 11673b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11683b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11693b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11703b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ret = cpsw_ale_del_ucast(priv->ale, priv->mac_addr, 11713b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N priv->host_port, ALE_VLAN, vid); 11723b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N if (ret != 0) 11733b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return ret; 11743b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 11753b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N return cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 11763b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 0, ALE_VLAN, vid); 11773b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N} 11783b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N 1179df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic const struct net_device_ops cpsw_netdev_ops = { 1180df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_open = cpsw_ndo_open, 1181df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_stop = cpsw_ndo_stop, 1182df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_start_xmit = cpsw_ndo_start_xmit, 1183df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_change_rx_flags = cpsw_ndo_change_rx_flags, 11842e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran .ndo_do_ioctl = cpsw_ndo_ioctl, 1185df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_validate_addr = eth_validate_addr, 11865c473ed26dba609622c9a625f896f8f59d86066cDavid S. Miller .ndo_change_mtu = eth_change_mtu, 1187df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_tx_timeout = cpsw_ndo_tx_timeout, 1188df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_get_stats = cpsw_ndo_get_stats, 11895c50a856d550b3bf6a731f6e33a794ed5c519817Mugunthan V N .ndo_set_rx_mode = cpsw_ndo_set_rx_mode, 1190df828598a755732e717b0adca82f884e44d37576Mugunthan V N#ifdef CONFIG_NET_POLL_CONTROLLER 1191df828598a755732e717b0adca82f884e44d37576Mugunthan V N .ndo_poll_controller = cpsw_ndo_poll_controller, 1192df828598a755732e717b0adca82f884e44d37576Mugunthan V N#endif 11933b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid, 11943b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid, 1195df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1196df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1197df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_get_drvinfo(struct net_device *ndev, 1198df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct ethtool_drvinfo *info) 1199df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1200df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 12017826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko 12027826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko strlcpy(info->driver, "TI CPSW Driver v1.0", sizeof(info->driver)); 12037826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko strlcpy(info->version, "1.0", sizeof(info->version)); 12047826d43f2db45c9305a6e0ba165650e1a203f517Jiri Pirko strlcpy(info->bus_info, priv->pdev->name, sizeof(info->bus_info)); 1205df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1206df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1207df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic u32 cpsw_get_msglevel(struct net_device *ndev) 1208df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1209df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1210df828598a755732e717b0adca82f884e44d37576Mugunthan V N return priv->msg_enable; 1211df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1212df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1213df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void cpsw_set_msglevel(struct net_device *ndev, u32 value) 1214df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1215df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1216df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->msg_enable = value; 1217df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1218df828598a755732e717b0adca82f884e44d37576Mugunthan V N 12192e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochranstatic int cpsw_get_ts_info(struct net_device *ndev, 12202e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran struct ethtool_ts_info *info) 12212e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran{ 12222e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#ifdef CONFIG_TI_CPTS 12232e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran struct cpsw_priv *priv = netdev_priv(ndev); 12242e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 12252e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->so_timestamping = 12262e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_TX_HARDWARE | 12272e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_TX_SOFTWARE | 12282e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RX_HARDWARE | 12292e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RX_SOFTWARE | 12302e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_SOFTWARE | 12312e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RAW_HARDWARE; 12329232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N info->phc_index = priv->cpts->phc_index; 12332e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->tx_types = 12342e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_TX_OFF) | 12352e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_TX_ON); 12362e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->rx_filters = 12372e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_FILTER_NONE) | 12382e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); 12392e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#else 12402e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->so_timestamping = 12412e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_TX_SOFTWARE | 12422e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_RX_SOFTWARE | 12432e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran SOF_TIMESTAMPING_SOFTWARE; 12442e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->phc_index = -1; 12452e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->tx_types = 0; 12462e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran info->rx_filters = 0; 12472e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran#endif 12482e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran return 0; 12492e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran} 12502e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 1251d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V Nstatic int cpsw_get_settings(struct net_device *ndev, 1252d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N struct ethtool_cmd *ecmd) 1253d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N{ 1254d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1255d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N int slave_no = cpsw_slave_index(priv); 1256d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N 1257d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N if (priv->slaves[slave_no].phy) 1258d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N return phy_ethtool_gset(priv->slaves[slave_no].phy, ecmd); 1259d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N else 1260d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N return -EOPNOTSUPP; 1261d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N} 1262d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N 1263d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V Nstatic int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) 1264d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N{ 1265d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1266d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N int slave_no = cpsw_slave_index(priv); 1267d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N 1268d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N if (priv->slaves[slave_no].phy) 1269d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N return phy_ethtool_sset(priv->slaves[slave_no].phy, ecmd); 1270d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N else 1271d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N return -EOPNOTSUPP; 1272d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N} 1273d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N 1274df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic const struct ethtool_ops cpsw_ethtool_ops = { 1275df828598a755732e717b0adca82f884e44d37576Mugunthan V N .get_drvinfo = cpsw_get_drvinfo, 1276df828598a755732e717b0adca82f884e44d37576Mugunthan V N .get_msglevel = cpsw_get_msglevel, 1277df828598a755732e717b0adca82f884e44d37576Mugunthan V N .set_msglevel = cpsw_set_msglevel, 1278df828598a755732e717b0adca82f884e44d37576Mugunthan V N .get_link = ethtool_op_get_link, 12792e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran .get_ts_info = cpsw_get_ts_info, 1280d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N .get_settings = cpsw_get_settings, 1281d3bb9c58b567d240eaaa2dc8bd778696eaed5fbdMugunthan V N .set_settings = cpsw_set_settings, 1282df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1283df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1284549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochranstatic void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv, 1285549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran u32 slave_reg_ofs, u32 sliver_reg_ofs) 1286df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1287df828598a755732e717b0adca82f884e44d37576Mugunthan V N void __iomem *regs = priv->regs; 1288df828598a755732e717b0adca82f884e44d37576Mugunthan V N int slave_num = slave->slave_num; 1289df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_slave_data *data = priv->data.slave_data + slave_num; 1290df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1291df828598a755732e717b0adca82f884e44d37576Mugunthan V N slave->data = data; 1292549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave->regs = regs + slave_reg_ofs; 1293549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave->sliver = regs + sliver_reg_ofs; 1294d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave->port_vlan = data->dual_emac_res_vlan; 1295df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1296df828598a755732e717b0adca82f884e44d37576Mugunthan V N 12972eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V Nstatic int cpsw_probe_dt(struct cpsw_platform_data *data, 12982eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct platform_device *pdev) 12992eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N{ 13002eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct device_node *node = pdev->dev.of_node; 13012eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct device_node *slave_node; 13022eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N int i = 0, ret; 13032eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N u32 prop; 13042eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13052eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (!node) 13062eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return -EINVAL; 13072eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13082eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "slaves", &prop)) { 13092eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing slaves property in the DT.\n"); 13102eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return -EINVAL; 13112eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13122eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->slaves = prop; 13132eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1314e86ac13b031cf71d8f40ff513e627aac80e6b765Mugunthan V N if (of_property_read_u32(node, "active_slave", &prop)) { 1315e86ac13b031cf71d8f40ff513e627aac80e6b765Mugunthan V N pr_err("Missing active_slave property in the DT.\n"); 131678ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran ret = -EINVAL; 131778ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran goto error_ret; 131878ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran } 1319e86ac13b031cf71d8f40ff513e627aac80e6b765Mugunthan V N data->active_slave = prop; 132078ca0b287314ad6b7b06161b3ff9b13e8a8bcce0Richard Cochran 132100ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran if (of_property_read_u32(node, "cpts_clock_mult", &prop)) { 132200ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran pr_err("Missing cpts_clock_mult property in the DT.\n"); 132300ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran ret = -EINVAL; 132400ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran goto error_ret; 132500ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran } 132600ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran data->cpts_clock_mult = prop; 132700ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran 132800ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran if (of_property_read_u32(node, "cpts_clock_shift", &prop)) { 132900ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran pr_err("Missing cpts_clock_shift property in the DT.\n"); 133000ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran ret = -EINVAL; 133100ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran goto error_ret; 133200ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran } 133300ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran data->cpts_clock_shift = prop; 133400ab94eeaf6c1ad38ad7368c5148fed31403c8a2Richard Cochran 1335b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches data->slave_data = kcalloc(data->slaves, sizeof(struct cpsw_slave_data), 1336b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches GFP_KERNEL); 1337b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches if (!data->slave_data) 13382eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return -EINVAL; 13392eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13402eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "cpdma_channels", &prop)) { 13412eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing cpdma_channels property in the DT.\n"); 13422eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13432eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13442eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13452eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->channels = prop; 13462eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13472eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "ale_entries", &prop)) { 13482eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing ale_entries property in the DT.\n"); 13492eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13502eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13512eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13522eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->ale_entries = prop; 13532eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13542eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "bd_ram_size", &prop)) { 13552eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing bd_ram_size property in the DT.\n"); 13562eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13572eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13582eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13592eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->bd_ram_size = prop; 13602eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13612eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "rx_descs", &prop)) { 13622eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing rx_descs property in the DT.\n"); 13632eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13642eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13652eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13662eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->rx_descs = prop; 13672eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 13682eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (of_property_read_u32(node, "mac_control", &prop)) { 13692eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing mac_control property in the DT.\n"); 13702eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13712eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 13722eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 13732eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data->mac_control = prop; 13742eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1375d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!of_property_read_u32(node, "dual_emac", &prop)) 1376d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N data->dual_emac = prop; 1377d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1378549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran /* 1379549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran * Populate all the child nodes here... 1380549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran */ 1381549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ret = of_platform_populate(node, NULL, NULL, &pdev->dev); 1382549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran /* We do not want to force this, as in some cases may not have child */ 1383549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if (ret) 1384549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran pr_warn("Doesn't have any child node\n"); 1385549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 13861fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath for_each_node_by_name(slave_node, "slave") { 13872eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N struct cpsw_slave_data *slave_data = data->slave_data + i; 13882eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N const void *mac_addr = NULL; 1389549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran u32 phyid; 1390549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran int lenp; 1391549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran const __be32 *parp; 1392549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran struct device_node *mdio_node; 1393549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran struct platform_device *mdio; 1394549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 1395549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran parp = of_get_property(slave_node, "phy_id", &lenp); 1396549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) { 13972eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("Missing slave[%d] phy_id property\n", i); 13982eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -EINVAL; 13992eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto error_ret; 14002eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 1401549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); 1402549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran phyid = be32_to_cpup(parp+1); 1403549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran mdio = of_find_device_by_node(mdio_node); 1404549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), 1405549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran PHY_ID_FMT, mdio->name, phyid); 14062eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 14072eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N mac_addr = of_get_mac_address(slave_node); 14082eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (mac_addr) 14092eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); 14102eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1411d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (data->dual_emac) { 1412d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (of_property_read_u32(node, "dual_emac_res_vlan", 1413d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N &prop)) { 1414d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("Missing dual_emac_res_vlan in DT.\n"); 1415d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_data->dual_emac_res_vlan = i+1; 1416d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("Using %d as Reserved VLAN for %d slave\n", 1417d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_data->dual_emac_res_vlan, i); 1418d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { 1419d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N slave_data->dual_emac_res_vlan = prop; 1420d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1421d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1422d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 14232eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N i++; 14242eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 14252eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 14262eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return 0; 14272eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 14282eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V Nerror_ret: 14292eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N kfree(data->slave_data); 14302eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N return ret; 14312eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N} 14322eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1433d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V Nstatic int cpsw_probe_dual_emac(struct platform_device *pdev, 1434d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv) 1435d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N{ 1436d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_platform_data *data = &priv->data; 1437d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct net_device *ndev; 1438d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N struct cpsw_priv *priv_sl2; 1439d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N int ret = 0, i; 1440d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1441d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev = alloc_etherdev(sizeof(struct cpsw_priv)); 1442d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (!ndev) { 1443d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("cpsw: error allocating net_device\n"); 1444d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return -ENOMEM; 1445d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1446d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1447d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2 = netdev_priv(ndev); 1448d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N spin_lock_init(&priv_sl2->lock); 1449d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->data = *data; 1450d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->pdev = pdev; 1451d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->ndev = ndev; 1452d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->dev = &ndev->dev; 1453d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); 1454d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->rx_packet_max = max(rx_packet_max, 128); 1455d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1456d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (is_valid_ether_addr(data->slave_data[1].mac_addr)) { 1457d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr, 1458d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ETH_ALEN); 1459d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr); 1460d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } else { 1461d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N random_ether_addr(priv_sl2->mac_addr); 1462d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr); 1463d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1464d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN); 1465d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1466d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->slaves = priv->slaves; 1467d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->clk = priv->clk; 1468d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1469d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->cpsw_res = priv->cpsw_res; 1470d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->regs = priv->regs; 1471d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->host_port = priv->host_port; 1472d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->host_port_regs = priv->host_port_regs; 1473d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->wr_regs = priv->wr_regs; 1474d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->dma = priv->dma; 1475d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->txch = priv->txch; 1476d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->rxch = priv->rxch; 1477d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->ale = priv->ale; 1478d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->emac_port = 1; 1479d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[1].ndev = ndev; 1480d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->cpts = priv->cpts; 1481d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->version = priv->version; 1482d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1483d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N for (i = 0; i < priv->num_irqs; i++) { 1484d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->irqs_table[i] = priv->irqs_table[i]; 1485d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv_sl2->num_irqs = priv->num_irqs; 1486d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1487d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1488d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev->features |= NETIF_F_HW_VLAN_FILTER; 1489d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1490d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ndev->netdev_ops = &cpsw_netdev_ops; 1491d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops); 1492d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT); 1493d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1494d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N /* register the network device */ 1495d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N SET_NETDEV_DEV(ndev, &pdev->dev); 1496d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = register_netdev(ndev); 1497d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (ret) { 1498d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N pr_err("cpsw: error registering net device\n"); 1499d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N free_netdev(ndev); 1500d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = -ENODEV; 1501d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1502d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1503d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N return ret; 1504d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N} 1505d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1506663e12e61d8764ce342588325d1050d9cb5460c0Bill Pembertonstatic int cpsw_probe(struct platform_device *pdev) 1507df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1508df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_platform_data *data = pdev->dev.platform_data; 1509df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev; 1510df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv; 1511df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpdma_params dma_params; 1512df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_ale_params ale_params; 1513549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran void __iomem *ss_regs, *wr_regs; 1514df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct resource *res; 1515549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran u32 slave_offset, sliver_offset, slave_size; 1516df828598a755732e717b0adca82f884e44d37576Mugunthan V N int ret = 0, i, k = 0; 1517df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1518df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev = alloc_etherdev(sizeof(struct cpsw_priv)); 1519df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!ndev) { 1520df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_err("error allocating net_device\n"); 1521df828598a755732e717b0adca82f884e44d37576Mugunthan V N return -ENOMEM; 1522df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1523df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1524df828598a755732e717b0adca82f884e44d37576Mugunthan V N platform_set_drvdata(pdev, ndev); 1525df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv = netdev_priv(ndev); 1526df828598a755732e717b0adca82f884e44d37576Mugunthan V N spin_lock_init(&priv->lock); 1527df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->pdev = pdev; 1528df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->ndev = ndev; 1529df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->dev = &ndev->dev; 1530df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); 1531df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->rx_packet_max = max(rx_packet_max, 128); 15329232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL); 15339232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (!ndev) { 15349232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N pr_err("error allocating cpts\n"); 15359232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N goto clean_ndev_ret; 15369232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N } 1537df828598a755732e717b0adca82f884e44d37576Mugunthan V N 15381fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath /* 15391fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath * This may be required here for child devices. 15401fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath */ 15411fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath pm_runtime_enable(&pdev->dev); 15421fb19aa730e400e474b562c55227849060549733Vaibhav Hiremath 15432eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N if (cpsw_probe_dt(&priv->data, pdev)) { 15442eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N pr_err("cpsw: platform data missing\n"); 15452eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N ret = -ENODEV; 15462eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N goto clean_ndev_ret; 15472eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N } 15482eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N data = &priv->data; 15492eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1550df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (is_valid_ether_addr(data->slave_data[0].mac_addr)) { 1551df828598a755732e717b0adca82f884e44d37576Mugunthan V N memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN); 1552df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_info("Detected MACID = %pM", priv->mac_addr); 1553df828598a755732e717b0adca82f884e44d37576Mugunthan V N } else { 15547efd26d0db5917b9e53d72e76e52338b2600ae20Joe Perches eth_random_addr(priv->mac_addr); 1555df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_info("Random MACID = %pM", priv->mac_addr); 1556df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1557df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1558df828598a755732e717b0adca82f884e44d37576Mugunthan V N memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN); 1559df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1560df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->slaves = kzalloc(sizeof(struct cpsw_slave) * data->slaves, 1561df828598a755732e717b0adca82f884e44d37576Mugunthan V N GFP_KERNEL); 1562df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->slaves) { 1563df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -EBUSY; 1564df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_ndev_ret; 1565df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1566df828598a755732e717b0adca82f884e44d37576Mugunthan V N for (i = 0; i < data->slaves; i++) 1567df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->slaves[i].slave_num = i; 1568df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1569d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->slaves[0].ndev = ndev; 1570d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N priv->emac_port = 0; 1571d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1572f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N priv->clk = clk_get(&pdev->dev, "fck"); 1573df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (IS_ERR(priv->clk)) { 1574f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N dev_err(&pdev->dev, "fck is not found\n"); 1575f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N ret = -ENODEV; 1576f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N goto clean_slave_ret; 1577df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1578df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1579df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1580df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->cpsw_res) { 1581df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error getting i/o resource\n"); 1582df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOENT; 1583df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_clk_ret; 1584df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1585df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!request_mem_region(priv->cpsw_res->start, 1586df828598a755732e717b0adca82f884e44d37576Mugunthan V N resource_size(priv->cpsw_res), ndev->name)) { 1587df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "failed request i/o region\n"); 1588df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENXIO; 1589df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_clk_ret; 1590df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1591549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res)); 1592549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if (!ss_regs) { 1593df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "unable to map i/o region\n"); 1594df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_cpsw_iores_ret; 1595df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1596549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->regs = ss_regs; 1597549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->version = __raw_readl(&priv->regs->id_ver); 1598549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->host_port = HOST_PORT_NUM; 1599df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1600a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1601a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran if (!priv->cpsw_wr_res) { 1602df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error getting i/o resource\n"); 1603df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOENT; 16045250c9694fa879532470d87ebf6a485be1124221Richard Cochran goto clean_iomap_ret; 1605df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1606a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran if (!request_mem_region(priv->cpsw_wr_res->start, 1607a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res), ndev->name)) { 1608df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "failed request i/o region\n"); 1609df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENXIO; 16105250c9694fa879532470d87ebf6a485be1124221Richard Cochran goto clean_iomap_ret; 1611df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1612549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran wr_regs = ioremap(priv->cpsw_wr_res->start, 1613a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res)); 1614549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran if (!wr_regs) { 1615df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "unable to map i/o region\n"); 1616a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran goto clean_cpsw_wr_iores_ret; 1617df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1618549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->wr_regs = wr_regs; 1619df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1620df828598a755732e717b0adca82f884e44d37576Mugunthan V N memset(&dma_params, 0, sizeof(dma_params)); 1621549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran memset(&ale_params, 0, sizeof(ale_params)); 1622549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 1623549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran switch (priv->version) { 1624549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran case CPSW_VERSION_1: 1625549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET; 16269232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts->reg = ss_regs + CPSW1_CPTS_OFFSET; 1627549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.dmaregs = ss_regs + CPSW1_CPDMA_OFFSET; 1628549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.txhdp = ss_regs + CPSW1_STATERAM_OFFSET; 1629549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ale_params.ale_regs = ss_regs + CPSW1_ALE_OFFSET; 1630549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_offset = CPSW1_SLAVE_OFFSET; 1631549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_size = CPSW1_SLAVE_SIZE; 1632549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran sliver_offset = CPSW1_SLIVER_OFFSET; 1633549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.desc_mem_phys = 0; 1634549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran break; 1635549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran case CPSW_VERSION_2: 1636549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET; 16379232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N priv->cpts->reg = ss_regs + CPSW2_CPTS_OFFSET; 1638549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.dmaregs = ss_regs + CPSW2_CPDMA_OFFSET; 1639549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.txhdp = ss_regs + CPSW2_STATERAM_OFFSET; 1640549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ale_params.ale_regs = ss_regs + CPSW2_ALE_OFFSET; 1641549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_offset = CPSW2_SLAVE_OFFSET; 1642549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_size = CPSW2_SLAVE_SIZE; 1643549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran sliver_offset = CPSW2_SLIVER_OFFSET; 1644549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.desc_mem_phys = 1645549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET; 1646549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran break; 1647549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran default: 1648549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dev_err(priv->dev, "unknown version 0x%08x\n", priv->version); 1649549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran ret = -ENODEV; 1650549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran goto clean_cpsw_wr_iores_ret; 1651549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran } 1652549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran for (i = 0; i < priv->data.slaves; i++) { 1653549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran struct cpsw_slave *slave = &priv->slaves[i]; 1654549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran cpsw_slave_init(slave, priv, slave_offset, sliver_offset); 1655549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran slave_offset += slave_size; 1656549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran sliver_offset += SLIVER_SIZE; 1657549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran } 1658549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran 1659df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.dev = &pdev->dev; 1660549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxthresh = dma_params.dmaregs + CPDMA_RXTHRESH; 1661549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxfree = dma_params.dmaregs + CPDMA_RXFREE; 1662549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxhdp = dma_params.txhdp + CPDMA_RXHDP; 1663549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.txcp = dma_params.txhdp + CPDMA_TXCP; 1664549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.rxcp = dma_params.txhdp + CPDMA_RXCP; 1665df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1666df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.num_chan = data->channels; 1667df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.has_soft_reset = true; 1668df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.min_packet_size = CPSW_MIN_PACKET_SIZE; 1669df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.desc_mem_size = data->bd_ram_size; 1670df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.desc_align = 16; 1671df828598a755732e717b0adca82f884e44d37576Mugunthan V N dma_params.has_ext_regs = true; 1672549985ee9c723fea8fd7759b5046fb8249896d50Richard Cochran dma_params.desc_hw_addr = dma_params.desc_mem_phys; 1673df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1674df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->dma = cpdma_ctlr_create(&dma_params); 1675df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->dma) { 1676df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error initializing dma\n"); 1677df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOMEM; 16785250c9694fa879532470d87ebf6a485be1124221Richard Cochran goto clean_wr_iomap_ret; 1679df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1680df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1681df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0), 1682df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_tx_handler); 1683df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->rxch = cpdma_chan_create(priv->dma, rx_chan_num(0), 1684df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_rx_handler); 1685df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1686df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (WARN_ON(!priv->txch || !priv->rxch)) { 1687df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error initializing dma channels\n"); 1688df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOMEM; 1689df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_dma_ret; 1690df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1691df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1692df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.dev = &ndev->dev; 1693df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.ale_ageout = ale_ageout; 1694df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.ale_entries = data->ale_entries; 1695df828598a755732e717b0adca82f884e44d37576Mugunthan V N ale_params.ale_ports = data->slaves; 1696df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1697df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->ale = cpsw_ale_create(&ale_params); 1698df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (!priv->ale) { 1699df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error initializing ale engine\n"); 1700df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENODEV; 1701df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_dma_ret; 1702df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1703df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1704df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev->irq = platform_get_irq(pdev, 0); 1705df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (ndev->irq < 0) { 1706df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error getting irq resource\n"); 1707df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENOENT; 1708df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_ale_ret; 1709df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1710df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1711df828598a755732e717b0adca82f884e44d37576Mugunthan V N while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { 1712df828598a755732e717b0adca82f884e44d37576Mugunthan V N for (i = res->start; i <= res->end; i++) { 1713df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (request_irq(i, cpsw_interrupt, IRQF_DISABLED, 1714df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_name(&pdev->dev), priv)) { 1715df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error attaching irq\n"); 1716df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_ale_ret; 1717df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1718df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->irqs_table[k] = i; 1719df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->num_irqs = k; 1720df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1721df828598a755732e717b0adca82f884e44d37576Mugunthan V N k++; 1722df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1723df828598a755732e717b0adca82f884e44d37576Mugunthan V N 17243b72c2fe0c6bbec42ed7f899931daef227b80322Mugunthan V N ndev->features |= NETIF_F_HW_VLAN_FILTER; 1725df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1726df828598a755732e717b0adca82f884e44d37576Mugunthan V N ndev->netdev_ops = &cpsw_netdev_ops; 1727df828598a755732e717b0adca82f884e44d37576Mugunthan V N SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops); 1728df828598a755732e717b0adca82f884e44d37576Mugunthan V N netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT); 1729df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1730df828598a755732e717b0adca82f884e44d37576Mugunthan V N /* register the network device */ 1731df828598a755732e717b0adca82f884e44d37576Mugunthan V N SET_NETDEV_DEV(ndev, &pdev->dev); 1732df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = register_netdev(ndev); 1733df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (ret) { 1734df828598a755732e717b0adca82f884e44d37576Mugunthan V N dev_err(priv->dev, "error registering net device\n"); 1735df828598a755732e717b0adca82f884e44d37576Mugunthan V N ret = -ENODEV; 1736df828598a755732e717b0adca82f884e44d37576Mugunthan V N goto clean_irq_ret; 1737df828598a755732e717b0adca82f884e44d37576Mugunthan V N } 1738df828598a755732e717b0adca82f884e44d37576Mugunthan V N 17399232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N if (cpts_register(&pdev->dev, priv->cpts, 17402e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran data->cpts_clock_mult, data->cpts_clock_shift)) 17412e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran dev_err(priv->dev, "error registering cpts device\n"); 17422e5b38abcfad3049608a051826a5aaec2122cdacRichard Cochran 1743df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n", 1744df828598a755732e717b0adca82f884e44d37576Mugunthan V N priv->cpsw_res->start, ndev->irq); 1745df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1746d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (priv->data.dual_emac) { 1747d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N ret = cpsw_probe_dual_emac(pdev, priv); 1748d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N if (ret) { 1749d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N cpsw_err(priv, probe, "error probe slave 2 emac interface\n"); 1750d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N goto clean_irq_ret; 1751d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1752d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N } 1753d9ba8f9e6298af71ec1c1fd3d88c3ef68abd0ec3Mugunthan V N 1754df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1755df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1756df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_irq_ret: 1757df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_irq(ndev->irq, priv); 1758df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_ale_ret: 1759df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_destroy(priv->ale); 1760df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_dma_ret: 1761df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->txch); 1762df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->rxch); 1763df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_destroy(priv->dma); 17645250c9694fa879532470d87ebf6a485be1124221Richard Cochranclean_wr_iomap_ret: 17655250c9694fa879532470d87ebf6a485be1124221Richard Cochran iounmap(priv->wr_regs); 1766a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochranclean_cpsw_wr_iores_ret: 1767a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran release_mem_region(priv->cpsw_wr_res->start, 1768a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res)); 17695250c9694fa879532470d87ebf6a485be1124221Richard Cochranclean_iomap_ret: 17705250c9694fa879532470d87ebf6a485be1124221Richard Cochran iounmap(priv->regs); 1771df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_cpsw_iores_ret: 1772df828598a755732e717b0adca82f884e44d37576Mugunthan V N release_mem_region(priv->cpsw_res->start, 1773df828598a755732e717b0adca82f884e44d37576Mugunthan V N resource_size(priv->cpsw_res)); 1774df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_clk_ret: 1775df828598a755732e717b0adca82f884e44d37576Mugunthan V N clk_put(priv->clk); 1776f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V Nclean_slave_ret: 1777f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_disable(&pdev->dev); 1778df828598a755732e717b0adca82f884e44d37576Mugunthan V N kfree(priv->slaves); 1779df828598a755732e717b0adca82f884e44d37576Mugunthan V Nclean_ndev_ret: 1780df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_netdev(ndev); 1781df828598a755732e717b0adca82f884e44d37576Mugunthan V N return ret; 1782df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1783df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1784663e12e61d8764ce342588325d1050d9cb5460c0Bill Pembertonstatic int cpsw_remove(struct platform_device *pdev) 1785df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1786df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = platform_get_drvdata(pdev); 1787df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct cpsw_priv *priv = netdev_priv(ndev); 1788df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1789df828598a755732e717b0adca82f884e44d37576Mugunthan V N pr_info("removing device"); 1790df828598a755732e717b0adca82f884e44d37576Mugunthan V N platform_set_drvdata(pdev, NULL); 1791df828598a755732e717b0adca82f884e44d37576Mugunthan V N 17929232b16df2167c8afcb89de39ee85f5091ebacffMugunthan V N cpts_unregister(priv->cpts); 1793df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_irq(ndev->irq, priv); 1794df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ale_destroy(priv->ale); 1795df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->txch); 1796df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_chan_destroy(priv->rxch); 1797df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpdma_ctlr_destroy(priv->dma); 1798df828598a755732e717b0adca82f884e44d37576Mugunthan V N iounmap(priv->regs); 1799df828598a755732e717b0adca82f884e44d37576Mugunthan V N release_mem_region(priv->cpsw_res->start, 1800df828598a755732e717b0adca82f884e44d37576Mugunthan V N resource_size(priv->cpsw_res)); 18015250c9694fa879532470d87ebf6a485be1124221Richard Cochran iounmap(priv->wr_regs); 1802a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran release_mem_region(priv->cpsw_wr_res->start, 1803a65dd5b236053fbafb1926b7694fcdb2482b2f73Richard Cochran resource_size(priv->cpsw_wr_res)); 1804f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_disable(&pdev->dev); 1805df828598a755732e717b0adca82f884e44d37576Mugunthan V N clk_put(priv->clk); 1806df828598a755732e717b0adca82f884e44d37576Mugunthan V N kfree(priv->slaves); 1807df828598a755732e717b0adca82f884e44d37576Mugunthan V N free_netdev(ndev); 1808df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1809df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1810df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1811df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1812df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_suspend(struct device *dev) 1813df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1814df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct platform_device *pdev = to_platform_device(dev); 1815df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = platform_get_drvdata(pdev); 1816df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1817df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_running(ndev)) 1818df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ndo_stop(ndev); 1819f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_put_sync(&pdev->dev); 1820f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N 1821df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1822df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1823df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1824df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int cpsw_resume(struct device *dev) 1825df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1826df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct platform_device *pdev = to_platform_device(dev); 1827df828598a755732e717b0adca82f884e44d37576Mugunthan V N struct net_device *ndev = platform_get_drvdata(pdev); 1828df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1829f150bd7f8cf742c4cdd0c929aa494ef72f7f5b13Mugunthan V N pm_runtime_get_sync(&pdev->dev); 1830df828598a755732e717b0adca82f884e44d37576Mugunthan V N if (netif_running(ndev)) 1831df828598a755732e717b0adca82f884e44d37576Mugunthan V N cpsw_ndo_open(ndev); 1832df828598a755732e717b0adca82f884e44d37576Mugunthan V N return 0; 1833df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1834df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1835df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic const struct dev_pm_ops cpsw_pm_ops = { 1836df828598a755732e717b0adca82f884e44d37576Mugunthan V N .suspend = cpsw_suspend, 1837df828598a755732e717b0adca82f884e44d37576Mugunthan V N .resume = cpsw_resume, 1838df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1839df828598a755732e717b0adca82f884e44d37576Mugunthan V N 18402eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V Nstatic const struct of_device_id cpsw_of_mtable[] = { 18412eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N { .compatible = "ti,cpsw", }, 18422eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N { /* sentinel */ }, 18432eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N}; 18442eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N 1845df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic struct platform_driver cpsw_driver = { 1846df828598a755732e717b0adca82f884e44d37576Mugunthan V N .driver = { 1847df828598a755732e717b0adca82f884e44d37576Mugunthan V N .name = "cpsw", 1848df828598a755732e717b0adca82f884e44d37576Mugunthan V N .owner = THIS_MODULE, 1849df828598a755732e717b0adca82f884e44d37576Mugunthan V N .pm = &cpsw_pm_ops, 18502eb32b0a6f9d73fafc6b2c00ac0b705de13ae143Mugunthan V N .of_match_table = of_match_ptr(cpsw_of_mtable), 1851df828598a755732e717b0adca82f884e44d37576Mugunthan V N }, 1852df828598a755732e717b0adca82f884e44d37576Mugunthan V N .probe = cpsw_probe, 1853663e12e61d8764ce342588325d1050d9cb5460c0Bill Pemberton .remove = cpsw_remove, 1854df828598a755732e717b0adca82f884e44d37576Mugunthan V N}; 1855df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1856df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic int __init cpsw_init(void) 1857df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1858df828598a755732e717b0adca82f884e44d37576Mugunthan V N return platform_driver_register(&cpsw_driver); 1859df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1860df828598a755732e717b0adca82f884e44d37576Mugunthan V Nlate_initcall(cpsw_init); 1861df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1862df828598a755732e717b0adca82f884e44d37576Mugunthan V Nstatic void __exit cpsw_exit(void) 1863df828598a755732e717b0adca82f884e44d37576Mugunthan V N{ 1864df828598a755732e717b0adca82f884e44d37576Mugunthan V N platform_driver_unregister(&cpsw_driver); 1865df828598a755732e717b0adca82f884e44d37576Mugunthan V N} 1866df828598a755732e717b0adca82f884e44d37576Mugunthan V Nmodule_exit(cpsw_exit); 1867df828598a755732e717b0adca82f884e44d37576Mugunthan V N 1868df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_LICENSE("GPL"); 1869df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_AUTHOR("Cyril Chemparathy <cyril@ti.com>"); 1870df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_AUTHOR("Mugunthan V N <mugunthanvnm@ti.com>"); 1871df828598a755732e717b0adca82f884e44d37576Mugunthan V NMODULE_DESCRIPTION("TI CPSW Ethernet driver"); 1872