mirror of
				https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
				synced 2025-10-31 16:18:51 +01:00 
			
		
		
		
	Fixed MTP to work with TWRP
This commit is contained in:
		
						commit
						f6dfaef42e
					
				
					 50820 changed files with 20846062 additions and 0 deletions
				
			
		
							
								
								
									
										10
									
								
								drivers/net/ethernet/apm/xgene/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								drivers/net/ethernet/apm/xgene/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| config NET_XGENE | ||||
| 	tristate "APM X-Gene SoC Ethernet Driver" | ||||
| 	depends on HAS_DMA | ||||
| 	select PHYLIB | ||||
| 	help | ||||
| 	  This is the Ethernet driver for the on-chip ethernet interface on the | ||||
| 	  APM X-Gene SoC. | ||||
| 
 | ||||
| 	  To compile this driver as a module, choose M here. This module will | ||||
| 	  be called xgene_enet. | ||||
							
								
								
									
										7
									
								
								drivers/net/ethernet/apm/xgene/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								drivers/net/ethernet/apm/xgene/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| #
 | ||||
| # Makefile for APM X-Gene Ethernet Driver.
 | ||||
| #
 | ||||
| 
 | ||||
| xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \
 | ||||
| 		   xgene_enet_main.o xgene_enet_ethtool.o | ||||
| obj-$(CONFIG_NET_XGENE) += xgene-enet.o | ||||
							
								
								
									
										150
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,150 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/ethtool.h> | ||||
| #include "xgene_enet_main.h" | ||||
| 
 | ||||
| struct xgene_gstrings_stats { | ||||
| 	char name[ETH_GSTRING_LEN]; | ||||
| 	int offset; | ||||
| }; | ||||
| 
 | ||||
| #define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) } | ||||
| 
 | ||||
| static const struct xgene_gstrings_stats gstrings_stats[] = { | ||||
| 	XGENE_STAT(rx_packets), | ||||
| 	XGENE_STAT(tx_packets), | ||||
| 	XGENE_STAT(rx_bytes), | ||||
| 	XGENE_STAT(tx_bytes), | ||||
| 	XGENE_STAT(rx_errors), | ||||
| 	XGENE_STAT(tx_errors), | ||||
| 	XGENE_STAT(rx_length_errors), | ||||
| 	XGENE_STAT(rx_crc_errors), | ||||
| 	XGENE_STAT(rx_frame_errors), | ||||
| 	XGENE_STAT(rx_fifo_errors) | ||||
| }; | ||||
| 
 | ||||
| #define XGENE_STATS_LEN		ARRAY_SIZE(gstrings_stats) | ||||
| 
 | ||||
| static void xgene_get_drvinfo(struct net_device *ndev, | ||||
| 			      struct ethtool_drvinfo *info) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = netdev_priv(ndev); | ||||
| 	struct platform_device *pdev = pdata->pdev; | ||||
| 
 | ||||
| 	strcpy(info->driver, "xgene_enet"); | ||||
| 	strcpy(info->version, XGENE_DRV_VERSION); | ||||
| 	snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A"); | ||||
| 	sprintf(info->bus_info, "%s", pdev->name); | ||||
| } | ||||
| 
 | ||||
| static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = netdev_priv(ndev); | ||||
| 	struct phy_device *phydev = pdata->phy_dev; | ||||
| 
 | ||||
| 	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { | ||||
| 		if (phydev == NULL) | ||||
| 			return -ENODEV; | ||||
| 
 | ||||
| 		return phy_ethtool_gset(phydev, cmd); | ||||
| 	} else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) { | ||||
| 		cmd->supported = SUPPORTED_1000baseT_Full | | ||||
| 				 SUPPORTED_Autoneg | SUPPORTED_MII; | ||||
| 		cmd->advertising = cmd->supported; | ||||
| 		ethtool_cmd_speed_set(cmd, SPEED_1000); | ||||
| 		cmd->duplex = DUPLEX_FULL; | ||||
| 		cmd->port = PORT_MII; | ||||
| 		cmd->transceiver = XCVR_INTERNAL; | ||||
| 		cmd->autoneg = AUTONEG_ENABLE; | ||||
| 	} else { | ||||
| 		cmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE; | ||||
| 		cmd->advertising = cmd->supported; | ||||
| 		ethtool_cmd_speed_set(cmd, SPEED_10000); | ||||
| 		cmd->duplex = DUPLEX_FULL; | ||||
| 		cmd->port = PORT_FIBRE; | ||||
| 		cmd->transceiver = XCVR_INTERNAL; | ||||
| 		cmd->autoneg = AUTONEG_DISABLE; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = netdev_priv(ndev); | ||||
| 	struct phy_device *phydev = pdata->phy_dev; | ||||
| 
 | ||||
| 	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { | ||||
| 		if (phydev == NULL) | ||||
| 			return -ENODEV; | ||||
| 
 | ||||
| 		return phy_ethtool_sset(phydev, cmd); | ||||
| 	} | ||||
| 
 | ||||
| 	return -EINVAL; | ||||
| } | ||||
| 
 | ||||
| static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data) | ||||
| { | ||||
| 	int i; | ||||
| 	u8 *p = data; | ||||
| 
 | ||||
| 	if (stringset != ETH_SS_STATS) | ||||
| 		return; | ||||
| 
 | ||||
| 	for (i = 0; i < XGENE_STATS_LEN; i++) { | ||||
| 		memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); | ||||
| 		p += ETH_GSTRING_LEN; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int xgene_get_sset_count(struct net_device *ndev, int sset) | ||||
| { | ||||
| 	if (sset != ETH_SS_STATS) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	return XGENE_STATS_LEN; | ||||
| } | ||||
| 
 | ||||
| static void xgene_get_ethtool_stats(struct net_device *ndev, | ||||
| 				    struct ethtool_stats *dummy, | ||||
| 				    u64 *data) | ||||
| { | ||||
| 	void *pdata = netdev_priv(ndev); | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < XGENE_STATS_LEN; i++) | ||||
| 		*data++ = *(u64 *)(pdata + gstrings_stats[i].offset); | ||||
| } | ||||
| 
 | ||||
| static const struct ethtool_ops xgene_ethtool_ops = { | ||||
| 	.get_drvinfo = xgene_get_drvinfo, | ||||
| 	.get_settings = xgene_get_settings, | ||||
| 	.set_settings = xgene_set_settings, | ||||
| 	.get_link = ethtool_op_get_link, | ||||
| 	.get_strings = xgene_get_strings, | ||||
| 	.get_sset_count = xgene_get_sset_count, | ||||
| 	.get_ethtool_stats = xgene_get_ethtool_stats | ||||
| }; | ||||
| 
 | ||||
| void xgene_enet_set_ethtool_ops(struct net_device *ndev) | ||||
| { | ||||
| 	ndev->ethtool_ops = &xgene_ethtool_ops; | ||||
| } | ||||
							
								
								
									
										759
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										759
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,759 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  *	    Ravi Patel <rapatel@apm.com> | ||||
|  *	    Keyur Chudgar <kchudgar@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include "xgene_enet_main.h" | ||||
| #include "xgene_enet_hw.h" | ||||
| 
 | ||||
| static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	u32 *ring_cfg = ring->state; | ||||
| 	u64 addr = ring->dma; | ||||
| 	enum xgene_enet_ring_cfgsize cfgsize = ring->cfgsize; | ||||
| 
 | ||||
| 	ring_cfg[4] |= (1 << SELTHRSH_POS) & | ||||
| 			CREATE_MASK(SELTHRSH_POS, SELTHRSH_LEN); | ||||
| 	ring_cfg[3] |= ACCEPTLERR; | ||||
| 	ring_cfg[2] |= QCOHERENT; | ||||
| 
 | ||||
| 	addr >>= 8; | ||||
| 	ring_cfg[2] |= (addr << RINGADDRL_POS) & | ||||
| 			CREATE_MASK_ULL(RINGADDRL_POS, RINGADDRL_LEN); | ||||
| 	addr >>= RINGADDRL_LEN; | ||||
| 	ring_cfg[3] |= addr & CREATE_MASK_ULL(RINGADDRH_POS, RINGADDRH_LEN); | ||||
| 	ring_cfg[3] |= ((u32)cfgsize << RINGSIZE_POS) & | ||||
| 			CREATE_MASK(RINGSIZE_POS, RINGSIZE_LEN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	u32 *ring_cfg = ring->state; | ||||
| 	bool is_bufpool; | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	is_bufpool = xgene_enet_is_bufpool(ring->id); | ||||
| 	val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR; | ||||
| 	ring_cfg[4] |= (val << RINGTYPE_POS) & | ||||
| 			CREATE_MASK(RINGTYPE_POS, RINGTYPE_LEN); | ||||
| 
 | ||||
| 	if (is_bufpool) { | ||||
| 		ring_cfg[3] |= (BUFPOOL_MODE << RINGMODE_POS) & | ||||
| 				CREATE_MASK(RINGMODE_POS, RINGMODE_LEN); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	u32 *ring_cfg = ring->state; | ||||
| 
 | ||||
| 	ring_cfg[3] |= RECOMBBUF; | ||||
| 	ring_cfg[3] |= (0xf << RECOMTIMEOUTL_POS) & | ||||
| 			CREATE_MASK(RECOMTIMEOUTL_POS, RECOMTIMEOUTL_LEN); | ||||
| 	ring_cfg[4] |= 0x7 & CREATE_MASK(RECOMTIMEOUTH_POS, RECOMTIMEOUTH_LEN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring, | ||||
| 				 u32 offset, u32 data) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); | ||||
| 
 | ||||
| 	iowrite32(data, pdata->ring_csr_addr + offset); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring, | ||||
| 				 u32 offset, u32 *data) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); | ||||
| 
 | ||||
| 	*data = ioread32(pdata->ring_csr_addr + offset); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num); | ||||
| 	for (i = 0; i < NUM_RING_CONFIG; i++) { | ||||
| 		xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4), | ||||
| 				     ring->state[i]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG); | ||||
| 	xgene_enet_write_ring_state(ring); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	xgene_enet_ring_set_type(ring); | ||||
| 
 | ||||
| 	if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0) | ||||
| 		xgene_enet_ring_set_recombbuf(ring); | ||||
| 
 | ||||
| 	xgene_enet_ring_init(ring); | ||||
| 	xgene_enet_write_ring_state(ring); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	u32 ring_id_val, ring_id_buf; | ||||
| 	bool is_bufpool; | ||||
| 
 | ||||
| 	is_bufpool = xgene_enet_is_bufpool(ring->id); | ||||
| 
 | ||||
| 	ring_id_val = ring->id & GENMASK(9, 0); | ||||
| 	ring_id_val |= OVERWRITE; | ||||
| 
 | ||||
| 	ring_id_buf = (ring->num << 9) & GENMASK(18, 9); | ||||
| 	ring_id_buf |= PREFETCH_BUF_EN; | ||||
| 	if (is_bufpool) | ||||
| 		ring_id_buf |= IS_BUFFER_POOL; | ||||
| 
 | ||||
| 	xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val); | ||||
| 	xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	u32 ring_id; | ||||
| 
 | ||||
| 	ring_id = ring->id | OVERWRITE; | ||||
| 	xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id); | ||||
| 	xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0); | ||||
| } | ||||
| 
 | ||||
| struct xgene_enet_desc_ring *xgene_enet_setup_ring( | ||||
| 					struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	u32 size = ring->size; | ||||
| 	u32 i, data; | ||||
| 	bool is_bufpool; | ||||
| 
 | ||||
| 	xgene_enet_clr_ring_state(ring); | ||||
| 	xgene_enet_set_ring_state(ring); | ||||
| 	xgene_enet_set_ring_id(ring); | ||||
| 
 | ||||
| 	ring->slots = xgene_enet_get_numslots(ring->id, size); | ||||
| 
 | ||||
| 	is_bufpool = xgene_enet_is_bufpool(ring->id); | ||||
| 	if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU) | ||||
| 		return ring; | ||||
| 
 | ||||
| 	for (i = 0; i < ring->slots; i++) | ||||
| 		xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]); | ||||
| 
 | ||||
| 	xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data); | ||||
| 	data |= BIT(31 - xgene_enet_ring_bufnum(ring->id)); | ||||
| 	xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data); | ||||
| 
 | ||||
| 	return ring; | ||||
| } | ||||
| 
 | ||||
| void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring) | ||||
| { | ||||
| 	u32 data; | ||||
| 	bool is_bufpool; | ||||
| 
 | ||||
| 	is_bufpool = xgene_enet_is_bufpool(ring->id); | ||||
| 	if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data); | ||||
| 	data &= ~BIT(31 - xgene_enet_ring_bufnum(ring->id)); | ||||
| 	xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data); | ||||
| 
 | ||||
| out: | ||||
| 	xgene_enet_clr_desc_ring_id(ring); | ||||
| 	xgene_enet_clr_ring_state(ring); | ||||
| } | ||||
| 
 | ||||
| void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, | ||||
| 			    struct xgene_enet_pdata *pdata, | ||||
| 			    enum xgene_enet_err_code status) | ||||
| { | ||||
| 	struct rtnl_link_stats64 *stats = &pdata->stats; | ||||
| 
 | ||||
| 	switch (status) { | ||||
| 	case INGRESS_CRC: | ||||
| 		stats->rx_crc_errors++; | ||||
| 		break; | ||||
| 	case INGRESS_CHECKSUM: | ||||
| 	case INGRESS_CHECKSUM_COMPUTE: | ||||
| 		stats->rx_errors++; | ||||
| 		break; | ||||
| 	case INGRESS_TRUNC_FRAME: | ||||
| 		stats->rx_frame_errors++; | ||||
| 		break; | ||||
| 	case INGRESS_PKT_LEN: | ||||
| 		stats->rx_length_errors++; | ||||
| 		break; | ||||
| 	case INGRESS_PKT_UNDER: | ||||
| 		stats->rx_frame_errors++; | ||||
| 		break; | ||||
| 	case INGRESS_FIFO_OVERRUN: | ||||
| 		stats->rx_fifo_errors++; | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata, | ||||
| 			      u32 offset, u32 val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_csr_addr + offset; | ||||
| 
 | ||||
| 	iowrite32(val, addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata, | ||||
| 				  u32 offset, u32 val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_ring_if_addr + offset; | ||||
| 
 | ||||
| 	iowrite32(val, addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata, | ||||
| 				   u32 offset, u32 val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_diag_csr_addr + offset; | ||||
| 
 | ||||
| 	iowrite32(val, addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, | ||||
| 				  u32 offset, u32 val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->mcx_mac_csr_addr + offset; | ||||
| 
 | ||||
| 	iowrite32(val, addr); | ||||
| } | ||||
| 
 | ||||
| static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, | ||||
| 				   void __iomem *cmd, void __iomem *cmd_done, | ||||
| 				   u32 wr_addr, u32 wr_data) | ||||
| { | ||||
| 	u32 done; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	iowrite32(wr_addr, addr); | ||||
| 	iowrite32(wr_data, wr); | ||||
| 	iowrite32(XGENE_ENET_WR_CMD, cmd); | ||||
| 
 | ||||
| 	/* wait for write command to complete */ | ||||
| 	while (!(done = ioread32(cmd_done)) && wait--) | ||||
| 		udelay(1); | ||||
| 
 | ||||
| 	if (!done) | ||||
| 		return false; | ||||
| 
 | ||||
| 	iowrite32(0, cmd); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata, | ||||
| 				  u32 wr_addr, u32 wr_data) | ||||
| { | ||||
| 	void __iomem *addr, *wr, *cmd, *cmd_done; | ||||
| 
 | ||||
| 	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; | ||||
| 	wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET; | ||||
| 	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; | ||||
| 	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; | ||||
| 
 | ||||
| 	if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data)) | ||||
| 		netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n", | ||||
| 			   wr_addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata, | ||||
| 			      u32 offset, u32 *val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_csr_addr + offset; | ||||
| 
 | ||||
| 	*val = ioread32(addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata, | ||||
| 				   u32 offset, u32 *val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_diag_csr_addr + offset; | ||||
| 
 | ||||
| 	*val = ioread32(addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata, | ||||
| 				  u32 offset, u32 *val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->mcx_mac_csr_addr + offset; | ||||
| 
 | ||||
| 	*val = ioread32(addr); | ||||
| } | ||||
| 
 | ||||
| static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, | ||||
| 				   void __iomem *cmd, void __iomem *cmd_done, | ||||
| 				   u32 rd_addr, u32 *rd_data) | ||||
| { | ||||
| 	u32 done; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	iowrite32(rd_addr, addr); | ||||
| 	iowrite32(XGENE_ENET_RD_CMD, cmd); | ||||
| 
 | ||||
| 	/* wait for read command to complete */ | ||||
| 	while (!(done = ioread32(cmd_done)) && wait--) | ||||
| 		udelay(1); | ||||
| 
 | ||||
| 	if (!done) | ||||
| 		return false; | ||||
| 
 | ||||
| 	*rd_data = ioread32(rd); | ||||
| 	iowrite32(0, cmd); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata, | ||||
| 				  u32 rd_addr, u32 *rd_data) | ||||
| { | ||||
| 	void __iomem *addr, *rd, *cmd, *cmd_done; | ||||
| 
 | ||||
| 	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; | ||||
| 	rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; | ||||
| 	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; | ||||
| 	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; | ||||
| 
 | ||||
| 	if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) | ||||
| 		netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", | ||||
| 			   rd_addr); | ||||
| } | ||||
| 
 | ||||
| static int xgene_mii_phy_write(struct xgene_enet_pdata *pdata, int phy_id, | ||||
| 			       u32 reg, u16 data) | ||||
| { | ||||
| 	u32 addr = 0, wr_data = 0; | ||||
| 	u32 done; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	PHY_ADDR_SET(&addr, phy_id); | ||||
| 	REG_ADDR_SET(&addr, reg); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr); | ||||
| 
 | ||||
| 	PHY_CONTROL_SET(&wr_data, data); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, wr_data); | ||||
| 	do { | ||||
| 		usleep_range(5, 10); | ||||
| 		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done); | ||||
| 	} while ((done & BUSY_MASK) && wait--); | ||||
| 
 | ||||
| 	if (done & BUSY_MASK) { | ||||
| 		netdev_err(pdata->ndev, "MII_MGMT write failed\n"); | ||||
| 		return -EBUSY; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata, | ||||
| 			      u8 phy_id, u32 reg) | ||||
| { | ||||
| 	u32 addr = 0; | ||||
| 	u32 data, done; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	PHY_ADDR_SET(&addr, phy_id); | ||||
| 	REG_ADDR_SET(&addr, reg); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); | ||||
| 	do { | ||||
| 		usleep_range(5, 10); | ||||
| 		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done); | ||||
| 	} while ((done & BUSY_MASK) && wait--); | ||||
| 
 | ||||
| 	if (done & BUSY_MASK) { | ||||
| 		netdev_err(pdata->ndev, "MII_MGMT read failed\n"); | ||||
| 		return -EBUSY; | ||||
| 	} | ||||
| 
 | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0); | ||||
| 
 | ||||
| 	return data; | ||||
| } | ||||
| 
 | ||||
| static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 addr0, addr1; | ||||
| 	u8 *dev_addr = pdata->ndev->dev_addr; | ||||
| 
 | ||||
| 	addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | | ||||
| 		(dev_addr[1] << 8) | dev_addr[0]; | ||||
| 	addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16); | ||||
| 
 | ||||
| 	xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1); | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	struct net_device *ndev = pdata->ndev; | ||||
| 	u32 data; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0); | ||||
| 	do { | ||||
| 		usleep_range(100, 110); | ||||
| 		xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data); | ||||
| 	} while ((data != 0xffffffff) && wait--); | ||||
| 
 | ||||
| 	if (data != 0xffffffff) { | ||||
| 		netdev_err(ndev, "Failed to release memory from shutdown\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void xgene_gmac_reset(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0); | ||||
| } | ||||
| 
 | ||||
| static void xgene_gmac_init(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 value, mc2; | ||||
| 	u32 intf_ctl, rgmii; | ||||
| 	u32 icm0, icm2; | ||||
| 
 | ||||
| 	xgene_gmac_reset(pdata); | ||||
| 
 | ||||
| 	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0); | ||||
| 	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2); | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2); | ||||
| 	xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl); | ||||
| 	xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii); | ||||
| 
 | ||||
| 	switch (pdata->phy_speed) { | ||||
| 	case SPEED_10: | ||||
| 		ENET_INTERFACE_MODE2_SET(&mc2, 1); | ||||
| 		CFG_MACMODE_SET(&icm0, 0); | ||||
| 		CFG_WAITASYNCRD_SET(&icm2, 500); | ||||
| 		rgmii &= ~CFG_SPEED_1250; | ||||
| 		break; | ||||
| 	case SPEED_100: | ||||
| 		ENET_INTERFACE_MODE2_SET(&mc2, 1); | ||||
| 		intf_ctl |= ENET_LHD_MODE; | ||||
| 		CFG_MACMODE_SET(&icm0, 1); | ||||
| 		CFG_WAITASYNCRD_SET(&icm2, 80); | ||||
| 		rgmii &= ~CFG_SPEED_1250; | ||||
| 		break; | ||||
| 	default: | ||||
| 		ENET_INTERFACE_MODE2_SET(&mc2, 2); | ||||
| 		intf_ctl |= ENET_GHD_MODE; | ||||
| 		CFG_TXCLK_MUXSEL0_SET(&rgmii, 4); | ||||
| 		xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value); | ||||
| 		value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX; | ||||
| 		xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	mc2 |= FULL_DUPLEX2; | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); | ||||
| 
 | ||||
| 	xgene_gmac_set_mac_addr(pdata); | ||||
| 
 | ||||
| 	/* Adjust MDC clock frequency */ | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value); | ||||
| 	MGMT_CLOCK_SEL_SET(&value, 7); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value); | ||||
| 
 | ||||
| 	/* Enable drop if bufpool not available */ | ||||
| 	xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value); | ||||
| 	value |= CFG_RSIF_FPBUFF_TIMEOUT_EN; | ||||
| 	xgene_enet_wr_csr(pdata, RSIF_CONFIG_REG_ADDR, value); | ||||
| 
 | ||||
| 	/* Rtype should be copied from FP */ | ||||
| 	xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0); | ||||
| 	xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii); | ||||
| 
 | ||||
| 	/* Rx-Tx traffic resume */ | ||||
| 	xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0); | ||||
| 
 | ||||
| 	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0); | ||||
| 	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2); | ||||
| 
 | ||||
| 	xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value); | ||||
| 	value &= ~TX_DV_GATE_EN0; | ||||
| 	value &= ~RX_DV_GATE_EN0; | ||||
| 	value |= RESUME_RX0; | ||||
| 	xgene_enet_wr_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, value); | ||||
| 
 | ||||
| 	xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 val = 0xffffffff; | ||||
| 
 | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, val); | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, val); | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, val); | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata, | ||||
| 				  u32 dst_ring_num, u16 bufpool_id) | ||||
| { | ||||
| 	u32 cb; | ||||
| 	u32 fpsel; | ||||
| 
 | ||||
| 	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; | ||||
| 
 | ||||
| 	xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb); | ||||
| 	cb |= CFG_CLE_BYPASS_EN0; | ||||
| 	CFG_CLE_IP_PROTOCOL0_SET(&cb, 3); | ||||
| 	xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb); | ||||
| 
 | ||||
| 	xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb); | ||||
| 	CFG_CLE_DSTQID0_SET(&cb, dst_ring_num); | ||||
| 	CFG_CLE_FPSEL0_SET(&cb, fpsel); | ||||
| 	xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb); | ||||
| } | ||||
| 
 | ||||
| static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN); | ||||
| } | ||||
| 
 | ||||
| bool xgene_ring_mgr_init(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	if (!ioread32(p->ring_csr_addr + CLKEN_ADDR)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (ioread32(p->ring_csr_addr + SRST_ADDR)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_reset(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	if (!xgene_ring_mgr_init(pdata)) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	clk_prepare_enable(pdata->clk); | ||||
| 	clk_disable_unprepare(pdata->clk); | ||||
| 	clk_prepare_enable(pdata->clk); | ||||
| 	xgene_enet_ecc_init(pdata); | ||||
| 	xgene_enet_config_ring_if_assoc(pdata); | ||||
| 
 | ||||
| 	/* Enable auto-incr for scanning */ | ||||
| 	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val); | ||||
| 	val |= SCAN_AUTO_INCR; | ||||
| 	MGMT_CLOCK_SEL_SET(&val, 1); | ||||
| 	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	clk_disable_unprepare(pdata->clk); | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = bus->priv; | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	val = xgene_mii_phy_read(pdata, mii_id, regnum); | ||||
| 	netdev_dbg(pdata->ndev, "mdio_rd: bus=%d reg=%d val=%x\n", | ||||
| 		   mii_id, regnum, val); | ||||
| 
 | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | ||||
| 				 u16 val) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = bus->priv; | ||||
| 
 | ||||
| 	netdev_dbg(pdata->ndev, "mdio_wr: bus=%d reg=%d val=%x\n", | ||||
| 		   mii_id, regnum, val); | ||||
| 	return xgene_mii_phy_write(pdata, mii_id, regnum, val); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_adjust_link(struct net_device *ndev) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = netdev_priv(ndev); | ||||
| 	struct phy_device *phydev = pdata->phy_dev; | ||||
| 
 | ||||
| 	if (phydev->link) { | ||||
| 		if (pdata->phy_speed != phydev->speed) { | ||||
| 			pdata->phy_speed = phydev->speed; | ||||
| 			xgene_gmac_init(pdata); | ||||
| 			xgene_gmac_rx_enable(pdata); | ||||
| 			xgene_gmac_tx_enable(pdata); | ||||
| 			phy_print_status(phydev); | ||||
| 		} | ||||
| 	} else { | ||||
| 		xgene_gmac_rx_disable(pdata); | ||||
| 		xgene_gmac_tx_disable(pdata); | ||||
| 		pdata->phy_speed = SPEED_UNKNOWN; | ||||
| 		phy_print_status(phydev); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_phy_connect(struct net_device *ndev) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = netdev_priv(ndev); | ||||
| 	struct device_node *phy_np; | ||||
| 	struct phy_device *phy_dev; | ||||
| 	struct device *dev = &pdata->pdev->dev; | ||||
| 
 | ||||
| 	phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0); | ||||
| 	if (!phy_np) { | ||||
| 		netdev_dbg(ndev, "No phy-handle found\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link, | ||||
| 				 0, pdata->phy_mode); | ||||
| 	if (!phy_dev) { | ||||
| 		netdev_err(ndev, "Could not connect to PHY\n"); | ||||
| 		return  -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	pdata->phy_speed = SPEED_UNKNOWN; | ||||
| 	phy_dev->supported &= ~SUPPORTED_10baseT_Half & | ||||
| 			      ~SUPPORTED_100baseT_Half & | ||||
| 			      ~SUPPORTED_1000baseT_Half; | ||||
| 	phy_dev->advertising = phy_dev->supported; | ||||
| 	pdata->phy_dev = phy_dev; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	struct net_device *ndev = pdata->ndev; | ||||
| 	struct device *dev = &pdata->pdev->dev; | ||||
| 	struct device_node *child_np; | ||||
| 	struct device_node *mdio_np = NULL; | ||||
| 	struct mii_bus *mdio_bus; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	for_each_child_of_node(dev->of_node, child_np) { | ||||
| 		if (of_device_is_compatible(child_np, "apm,xgene-mdio")) { | ||||
| 			mdio_np = child_np; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!mdio_np) { | ||||
| 		netdev_dbg(ndev, "No mdio node in the dts\n"); | ||||
| 		return -ENXIO; | ||||
| 	} | ||||
| 
 | ||||
| 	mdio_bus = mdiobus_alloc(); | ||||
| 	if (!mdio_bus) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	mdio_bus->name = "APM X-Gene MDIO bus"; | ||||
| 	mdio_bus->read = xgene_enet_mdio_read; | ||||
| 	mdio_bus->write = xgene_enet_mdio_write; | ||||
| 	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "xgene-mii", | ||||
| 		 ndev->name); | ||||
| 
 | ||||
| 	mdio_bus->priv = pdata; | ||||
| 	mdio_bus->parent = &ndev->dev; | ||||
| 
 | ||||
| 	ret = of_mdiobus_register(mdio_bus, mdio_np); | ||||
| 	if (ret) { | ||||
| 		netdev_err(ndev, "Failed to register MDIO bus\n"); | ||||
| 		mdiobus_free(mdio_bus); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	pdata->mdio_bus = mdio_bus; | ||||
| 
 | ||||
| 	ret = xgene_enet_phy_connect(ndev); | ||||
| 	if (ret) | ||||
| 		xgene_enet_mdio_remove(pdata); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	mdiobus_unregister(pdata->mdio_bus); | ||||
| 	mdiobus_free(pdata->mdio_bus); | ||||
| 	pdata->mdio_bus = NULL; | ||||
| } | ||||
| 
 | ||||
| struct xgene_mac_ops xgene_gmac_ops = { | ||||
| 	.init = xgene_gmac_init, | ||||
| 	.reset = xgene_gmac_reset, | ||||
| 	.rx_enable = xgene_gmac_rx_enable, | ||||
| 	.tx_enable = xgene_gmac_tx_enable, | ||||
| 	.rx_disable = xgene_gmac_rx_disable, | ||||
| 	.tx_disable = xgene_gmac_tx_disable, | ||||
| 	.set_mac_addr = xgene_gmac_set_mac_addr, | ||||
| }; | ||||
| 
 | ||||
| struct xgene_port_ops xgene_gport_ops = { | ||||
| 	.reset = xgene_enet_reset, | ||||
| 	.cle_bypass = xgene_enet_cle_bypass, | ||||
| 	.shutdown = xgene_gport_shutdown, | ||||
| }; | ||||
							
								
								
									
										329
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,329 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  *	    Ravi Patel <rapatel@apm.com> | ||||
|  *	    Keyur Chudgar <kchudgar@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __XGENE_ENET_HW_H__ | ||||
| #define __XGENE_ENET_HW_H__ | ||||
| 
 | ||||
| #include "xgene_enet_main.h" | ||||
| 
 | ||||
| struct xgene_enet_pdata; | ||||
| struct xgene_enet_stats; | ||||
| 
 | ||||
| /* clears and then set bits */ | ||||
| static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len) | ||||
| { | ||||
| 	u32 end = start + len - 1; | ||||
| 	u32 mask = GENMASK(end, start); | ||||
| 
 | ||||
| 	*dst &= ~mask; | ||||
| 	*dst |= (val << start) & mask; | ||||
| } | ||||
| 
 | ||||
| static inline u32 xgene_get_bits(u32 val, u32 start, u32 end) | ||||
| { | ||||
| 	return (val & GENMASK(end, start)) >> start; | ||||
| } | ||||
| 
 | ||||
| enum xgene_enet_rm { | ||||
| 	RM0, | ||||
| 	RM1, | ||||
| 	RM3 = 3 | ||||
| }; | ||||
| 
 | ||||
| #define CSR_RING_ID		0x0008 | ||||
| #define OVERWRITE		BIT(31) | ||||
| #define IS_BUFFER_POOL		BIT(20) | ||||
| #define PREFETCH_BUF_EN		BIT(21) | ||||
| #define CSR_RING_ID_BUF		0x000c | ||||
| #define CSR_RING_NE_INT_MODE	0x017c | ||||
| #define CSR_RING_CONFIG		0x006c | ||||
| #define CSR_RING_WR_BASE	0x0070 | ||||
| #define NUM_RING_CONFIG		5 | ||||
| #define BUFPOOL_MODE		3 | ||||
| #define INC_DEC_CMD_ADDR	0x002c | ||||
| #define UDP_HDR_SIZE		2 | ||||
| #define BUF_LEN_CODE_2K		0x5000 | ||||
| 
 | ||||
| #define CREATE_MASK(pos, len)		GENMASK((pos)+(len)-1, (pos)) | ||||
| #define CREATE_MASK_ULL(pos, len)	GENMASK_ULL((pos)+(len)-1, (pos)) | ||||
| 
 | ||||
| /* Empty slot soft signature */ | ||||
| #define EMPTY_SLOT_INDEX	1 | ||||
| #define EMPTY_SLOT		~0ULL | ||||
| 
 | ||||
| #define WORK_DESC_SIZE		32 | ||||
| #define BUFPOOL_DESC_SIZE	16 | ||||
| 
 | ||||
| #define RING_OWNER_MASK		GENMASK(9, 6) | ||||
| #define RING_BUFNUM_MASK	GENMASK(5, 0) | ||||
| 
 | ||||
| #define SELTHRSH_POS		3 | ||||
| #define SELTHRSH_LEN		3 | ||||
| #define RINGADDRL_POS		5 | ||||
| #define RINGADDRL_LEN		27 | ||||
| #define RINGADDRH_POS		0 | ||||
| #define RINGADDRH_LEN		6 | ||||
| #define RINGSIZE_POS		23 | ||||
| #define RINGSIZE_LEN		3 | ||||
| #define RINGTYPE_POS		19 | ||||
| #define RINGTYPE_LEN		2 | ||||
| #define RINGMODE_POS		20 | ||||
| #define RINGMODE_LEN		3 | ||||
| #define RECOMTIMEOUTL_POS	28 | ||||
| #define RECOMTIMEOUTL_LEN	3 | ||||
| #define RECOMTIMEOUTH_POS	0 | ||||
| #define RECOMTIMEOUTH_LEN	2 | ||||
| #define NUMMSGSINQ_POS		1 | ||||
| #define NUMMSGSINQ_LEN		16 | ||||
| #define ACCEPTLERR		BIT(19) | ||||
| #define QCOHERENT		BIT(4) | ||||
| #define RECOMBBUF		BIT(27) | ||||
| 
 | ||||
| #define BLOCK_ETH_CSR_OFFSET		0x2000 | ||||
| #define BLOCK_ETH_RING_IF_OFFSET	0x9000 | ||||
| #define BLOCK_ETH_DIAG_CSR_OFFSET	0xD000 | ||||
| 
 | ||||
| #define BLOCK_ETH_MAC_OFFSET		0x0000 | ||||
| #define BLOCK_ETH_MAC_CSR_OFFSET	0x2800 | ||||
| 
 | ||||
| #define CLKEN_ADDR			0xc208 | ||||
| #define SRST_ADDR			0xc200 | ||||
| 
 | ||||
| #define MAC_ADDR_REG_OFFSET		0x00 | ||||
| #define MAC_COMMAND_REG_OFFSET		0x04 | ||||
| #define MAC_WRITE_REG_OFFSET		0x08 | ||||
| #define MAC_READ_REG_OFFSET		0x0c | ||||
| #define MAC_COMMAND_DONE_REG_OFFSET	0x10 | ||||
| 
 | ||||
| #define MII_MGMT_CONFIG_ADDR		0x20 | ||||
| #define MII_MGMT_COMMAND_ADDR		0x24 | ||||
| #define MII_MGMT_ADDRESS_ADDR		0x28 | ||||
| #define MII_MGMT_CONTROL_ADDR		0x2c | ||||
| #define MII_MGMT_STATUS_ADDR		0x30 | ||||
| #define MII_MGMT_INDICATORS_ADDR	0x34 | ||||
| 
 | ||||
| #define BUSY_MASK			BIT(0) | ||||
| #define READ_CYCLE_MASK			BIT(0) | ||||
| #define PHY_CONTROL_SET(dst, val)	xgene_set_bits(dst, val, 0, 16) | ||||
| 
 | ||||
| #define ENET_SPARE_CFG_REG_ADDR		0x0750 | ||||
| #define RSIF_CONFIG_REG_ADDR		0x0010 | ||||
| #define RSIF_RAM_DBG_REG0_ADDR		0x0048 | ||||
| #define RGMII_REG_0_ADDR		0x07e0 | ||||
| #define CFG_LINK_AGGR_RESUME_0_ADDR	0x07c8 | ||||
| #define DEBUG_REG_ADDR			0x0700 | ||||
| #define CFG_BYPASS_ADDR			0x0294 | ||||
| #define CLE_BYPASS_REG0_0_ADDR		0x0490 | ||||
| #define CLE_BYPASS_REG1_0_ADDR		0x0494 | ||||
| #define CFG_RSIF_FPBUFF_TIMEOUT_EN	BIT(31) | ||||
| #define RESUME_TX			BIT(0) | ||||
| #define CFG_SPEED_1250			BIT(24) | ||||
| #define TX_PORT0			BIT(0) | ||||
| #define CFG_BYPASS_UNISEC_TX		BIT(2) | ||||
| #define CFG_BYPASS_UNISEC_RX		BIT(1) | ||||
| #define CFG_CLE_BYPASS_EN0		BIT(31) | ||||
| #define CFG_TXCLK_MUXSEL0_SET(dst, val)	xgene_set_bits(dst, val, 29, 3) | ||||
| 
 | ||||
| #define CFG_CLE_IP_PROTOCOL0_SET(dst, val)	xgene_set_bits(dst, val, 16, 2) | ||||
| #define CFG_CLE_DSTQID0_SET(dst, val)		xgene_set_bits(dst, val, 0, 12) | ||||
| #define CFG_CLE_FPSEL0_SET(dst, val)		xgene_set_bits(dst, val, 16, 4) | ||||
| #define CFG_MACMODE_SET(dst, val)		xgene_set_bits(dst, val, 18, 2) | ||||
| #define CFG_WAITASYNCRD_SET(dst, val)		xgene_set_bits(dst, val, 0, 16) | ||||
| #define CFG_CLE_DSTQID0(val)		(val & GENMASK(11, 0)) | ||||
| #define CFG_CLE_FPSEL0(val)		((val << 16) & GENMASK(19, 16)) | ||||
| #define ICM_CONFIG0_REG_0_ADDR		0x0400 | ||||
| #define ICM_CONFIG2_REG_0_ADDR		0x0410 | ||||
| #define RX_DV_GATE_REG_0_ADDR		0x05fc | ||||
| #define TX_DV_GATE_EN0			BIT(2) | ||||
| #define RX_DV_GATE_EN0			BIT(1) | ||||
| #define RESUME_RX0			BIT(0) | ||||
| #define ENET_CFGSSQMIWQASSOC_ADDR		0xe0 | ||||
| #define ENET_CFGSSQMIFPQASSOC_ADDR		0xdc | ||||
| #define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR	0xf0 | ||||
| #define ENET_CFGSSQMIQMLITEWQASSOC_ADDR		0xf4 | ||||
| #define ENET_CFG_MEM_RAM_SHUTDOWN_ADDR		0x70 | ||||
| #define ENET_BLOCK_MEM_RDY_ADDR			0x74 | ||||
| #define MAC_CONFIG_1_ADDR			0x00 | ||||
| #define MAC_CONFIG_2_ADDR			0x04 | ||||
| #define MAX_FRAME_LEN_ADDR			0x10 | ||||
| #define INTERFACE_CONTROL_ADDR			0x38 | ||||
| #define STATION_ADDR0_ADDR			0x40 | ||||
| #define STATION_ADDR1_ADDR			0x44 | ||||
| #define PHY_ADDR_SET(dst, val)			xgene_set_bits(dst, val, 8, 5) | ||||
| #define REG_ADDR_SET(dst, val)			xgene_set_bits(dst, val, 0, 5) | ||||
| #define ENET_INTERFACE_MODE2_SET(dst, val)	xgene_set_bits(dst, val, 8, 2) | ||||
| #define MGMT_CLOCK_SEL_SET(dst, val)		xgene_set_bits(dst, val, 0, 3) | ||||
| #define SOFT_RESET1			BIT(31) | ||||
| #define TX_EN				BIT(0) | ||||
| #define RX_EN				BIT(2) | ||||
| #define ENET_LHD_MODE			BIT(25) | ||||
| #define ENET_GHD_MODE			BIT(26) | ||||
| #define FULL_DUPLEX2			BIT(0) | ||||
| #define SCAN_AUTO_INCR			BIT(5) | ||||
| #define TBYT_ADDR			0x38 | ||||
| #define TPKT_ADDR			0x39 | ||||
| #define TDRP_ADDR			0x45 | ||||
| #define TFCS_ADDR			0x47 | ||||
| #define TUND_ADDR			0x4a | ||||
| 
 | ||||
| #define TSO_IPPROTO_TCP			1 | ||||
| 
 | ||||
| #define USERINFO_POS			0 | ||||
| #define USERINFO_LEN			32 | ||||
| #define FPQNUM_POS			32 | ||||
| #define FPQNUM_LEN			12 | ||||
| #define LERR_POS			60 | ||||
| #define LERR_LEN			3 | ||||
| #define STASH_POS			52 | ||||
| #define STASH_LEN			2 | ||||
| #define BUFDATALEN_POS			48 | ||||
| #define BUFDATALEN_LEN			12 | ||||
| #define DATAADDR_POS			0 | ||||
| #define DATAADDR_LEN			42 | ||||
| #define COHERENT_POS			63 | ||||
| #define HENQNUM_POS			48 | ||||
| #define HENQNUM_LEN			12 | ||||
| #define TYPESEL_POS			44 | ||||
| #define TYPESEL_LEN			4 | ||||
| #define ETHHDR_POS			12 | ||||
| #define ETHHDR_LEN			8 | ||||
| #define IC_POS				35	/* Insert CRC */ | ||||
| #define TCPHDR_POS			0 | ||||
| #define TCPHDR_LEN			6 | ||||
| #define IPHDR_POS			6 | ||||
| #define IPHDR_LEN			6 | ||||
| #define EC_POS				22	/* Enable checksum */ | ||||
| #define EC_LEN				1 | ||||
| #define IS_POS				24	/* IP protocol select */ | ||||
| #define IS_LEN				1 | ||||
| #define TYPE_ETH_WORK_MESSAGE_POS	44 | ||||
| 
 | ||||
| struct xgene_enet_raw_desc { | ||||
| 	__le64 m0; | ||||
| 	__le64 m1; | ||||
| 	__le64 m2; | ||||
| 	__le64 m3; | ||||
| }; | ||||
| 
 | ||||
| struct xgene_enet_raw_desc16 { | ||||
| 	__le64 m0; | ||||
| 	__le64 m1; | ||||
| }; | ||||
| 
 | ||||
| static inline void xgene_enet_mark_desc_slot_empty(void *desc_slot_ptr) | ||||
| { | ||||
| 	__le64 *desc_slot = desc_slot_ptr; | ||||
| 
 | ||||
| 	desc_slot[EMPTY_SLOT_INDEX] = cpu_to_le64(EMPTY_SLOT); | ||||
| } | ||||
| 
 | ||||
| static inline bool xgene_enet_is_desc_slot_empty(void *desc_slot_ptr) | ||||
| { | ||||
| 	__le64 *desc_slot = desc_slot_ptr; | ||||
| 
 | ||||
| 	return (desc_slot[EMPTY_SLOT_INDEX] == cpu_to_le64(EMPTY_SLOT)); | ||||
| } | ||||
| 
 | ||||
| enum xgene_enet_ring_cfgsize { | ||||
| 	RING_CFGSIZE_512B, | ||||
| 	RING_CFGSIZE_2KB, | ||||
| 	RING_CFGSIZE_16KB, | ||||
| 	RING_CFGSIZE_64KB, | ||||
| 	RING_CFGSIZE_512KB, | ||||
| 	RING_CFGSIZE_INVALID | ||||
| }; | ||||
| 
 | ||||
| enum xgene_enet_ring_type { | ||||
| 	RING_DISABLED, | ||||
| 	RING_REGULAR, | ||||
| 	RING_BUFPOOL | ||||
| }; | ||||
| 
 | ||||
| enum xgene_ring_owner { | ||||
| 	RING_OWNER_ETH0, | ||||
| 	RING_OWNER_CPU = 15, | ||||
| 	RING_OWNER_INVALID | ||||
| }; | ||||
| 
 | ||||
| enum xgene_enet_ring_bufnum { | ||||
| 	RING_BUFNUM_REGULAR = 0x0, | ||||
| 	RING_BUFNUM_BUFPOOL = 0x20, | ||||
| 	RING_BUFNUM_INVALID | ||||
| }; | ||||
| 
 | ||||
| enum xgene_enet_cmd { | ||||
| 	XGENE_ENET_WR_CMD = BIT(31), | ||||
| 	XGENE_ENET_RD_CMD = BIT(30) | ||||
| }; | ||||
| 
 | ||||
| enum xgene_enet_err_code { | ||||
| 	HBF_READ_DATA = 3, | ||||
| 	HBF_LL_READ = 4, | ||||
| 	BAD_WORK_MSG = 6, | ||||
| 	BUFPOOL_TIMEOUT = 15, | ||||
| 	INGRESS_CRC = 16, | ||||
| 	INGRESS_CHECKSUM = 17, | ||||
| 	INGRESS_TRUNC_FRAME = 18, | ||||
| 	INGRESS_PKT_LEN = 19, | ||||
| 	INGRESS_PKT_UNDER = 20, | ||||
| 	INGRESS_FIFO_OVERRUN = 21, | ||||
| 	INGRESS_CHECKSUM_COMPUTE = 26, | ||||
| 	ERR_CODE_INVALID | ||||
| }; | ||||
| 
 | ||||
| static inline enum xgene_ring_owner xgene_enet_ring_owner(u16 id) | ||||
| { | ||||
| 	return (id & RING_OWNER_MASK) >> 6; | ||||
| } | ||||
| 
 | ||||
| static inline u8 xgene_enet_ring_bufnum(u16 id) | ||||
| { | ||||
| 	return id & RING_BUFNUM_MASK; | ||||
| } | ||||
| 
 | ||||
| static inline bool xgene_enet_is_bufpool(u16 id) | ||||
| { | ||||
| 	return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false; | ||||
| } | ||||
| 
 | ||||
| static inline u16 xgene_enet_get_numslots(u16 id, u32 size) | ||||
| { | ||||
| 	bool is_bufpool = xgene_enet_is_bufpool(id); | ||||
| 
 | ||||
| 	return (is_bufpool) ? size / BUFPOOL_DESC_SIZE : | ||||
| 		      size / WORK_DESC_SIZE; | ||||
| } | ||||
| 
 | ||||
| struct xgene_enet_desc_ring *xgene_enet_setup_ring( | ||||
| 		struct xgene_enet_desc_ring *ring); | ||||
| void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring); | ||||
| void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, | ||||
| 			    struct xgene_enet_pdata *pdata, | ||||
| 			    enum xgene_enet_err_code status); | ||||
| 
 | ||||
| int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata); | ||||
| void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata); | ||||
| bool xgene_ring_mgr_init(struct xgene_enet_pdata *p); | ||||
| 
 | ||||
| extern struct xgene_mac_ops xgene_gmac_ops; | ||||
| extern struct xgene_port_ops xgene_gport_ops; | ||||
| 
 | ||||
| #endif /* __XGENE_ENET_HW_H__ */ | ||||
							
								
								
									
										1009
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1009
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_main.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										166
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_main.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_main.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,166 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  *	    Ravi Patel <rapatel@apm.com> | ||||
|  *	    Keyur Chudgar <kchudgar@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __XGENE_ENET_MAIN_H__ | ||||
| #define __XGENE_ENET_MAIN_H__ | ||||
| 
 | ||||
| #include <linux/clk.h> | ||||
| #include <linux/of_platform.h> | ||||
| #include <linux/of_net.h> | ||||
| #include <linux/of_mdio.h> | ||||
| #include <linux/module.h> | ||||
| #include <net/ip.h> | ||||
| #include <linux/prefetch.h> | ||||
| #include <linux/if_vlan.h> | ||||
| #include <linux/phy.h> | ||||
| #include "xgene_enet_hw.h" | ||||
| 
 | ||||
| #define XGENE_DRV_VERSION	"v1.0" | ||||
| #define XGENE_ENET_MAX_MTU	1536 | ||||
| #define SKB_BUFFER_SIZE		(XGENE_ENET_MAX_MTU - NET_IP_ALIGN) | ||||
| #define NUM_PKT_BUF	64 | ||||
| #define NUM_BUFPOOL	32 | ||||
| #define START_ETH_BUFNUM	2 | ||||
| #define START_BP_BUFNUM		0x22 | ||||
| #define START_RING_NUM		8 | ||||
| 
 | ||||
| #define PHY_POLL_LINK_ON	(10 * HZ) | ||||
| #define PHY_POLL_LINK_OFF	(PHY_POLL_LINK_ON / 5) | ||||
| 
 | ||||
| /* software context of a descriptor ring */ | ||||
| struct xgene_enet_desc_ring { | ||||
| 	struct net_device *ndev; | ||||
| 	u16 id; | ||||
| 	u16 num; | ||||
| 	u16 head; | ||||
| 	u16 tail; | ||||
| 	u16 slots; | ||||
| 	u16 irq; | ||||
| 	u32 size; | ||||
| 	u32 state[NUM_RING_CONFIG]; | ||||
| 	void __iomem *cmd_base; | ||||
| 	void __iomem *cmd; | ||||
| 	dma_addr_t dma; | ||||
| 	u16 dst_ring_num; | ||||
| 	u8 nbufpool; | ||||
| 	struct sk_buff *(*rx_skb); | ||||
| 	struct sk_buff *(*cp_skb); | ||||
| 	enum xgene_enet_ring_cfgsize cfgsize; | ||||
| 	struct xgene_enet_desc_ring *cp_ring; | ||||
| 	struct xgene_enet_desc_ring *buf_pool; | ||||
| 	struct napi_struct napi; | ||||
| 	union { | ||||
| 		void *desc_addr; | ||||
| 		struct xgene_enet_raw_desc *raw_desc; | ||||
| 		struct xgene_enet_raw_desc16 *raw_desc16; | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| struct xgene_mac_ops { | ||||
| 	void (*init)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*reset)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*tx_enable)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*rx_enable)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*tx_disable)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*rx_disable)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*set_mac_addr)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*link_state)(struct work_struct *work); | ||||
| }; | ||||
| 
 | ||||
| struct xgene_port_ops { | ||||
| 	int (*reset)(struct xgene_enet_pdata *pdata); | ||||
| 	void (*cle_bypass)(struct xgene_enet_pdata *pdata, | ||||
| 			   u32 dst_ring_num, u16 bufpool_id); | ||||
| 	void (*shutdown)(struct xgene_enet_pdata *pdata); | ||||
| }; | ||||
| 
 | ||||
| /* ethernet private data */ | ||||
| struct xgene_enet_pdata { | ||||
| 	struct net_device *ndev; | ||||
| 	struct mii_bus *mdio_bus; | ||||
| 	struct phy_device *phy_dev; | ||||
| 	int phy_speed; | ||||
| 	struct clk *clk; | ||||
| 	struct platform_device *pdev; | ||||
| 	struct xgene_enet_desc_ring *tx_ring; | ||||
| 	struct xgene_enet_desc_ring *rx_ring; | ||||
| 	char *dev_name; | ||||
| 	u32 rx_buff_cnt; | ||||
| 	u32 tx_qcnt_hi; | ||||
| 	u32 cp_qcnt_hi; | ||||
| 	u32 cp_qcnt_low; | ||||
| 	u32 rx_irq; | ||||
| 	void __iomem *eth_csr_addr; | ||||
| 	void __iomem *eth_ring_if_addr; | ||||
| 	void __iomem *eth_diag_csr_addr; | ||||
| 	void __iomem *mcx_mac_addr; | ||||
| 	void __iomem *mcx_mac_csr_addr; | ||||
| 	void __iomem *base_addr; | ||||
| 	void __iomem *ring_csr_addr; | ||||
| 	void __iomem *ring_cmd_addr; | ||||
| 	int phy_mode; | ||||
| 	enum xgene_enet_rm rm; | ||||
| 	struct rtnl_link_stats64 stats; | ||||
| 	struct xgene_mac_ops *mac_ops; | ||||
| 	struct xgene_port_ops *port_ops; | ||||
| 	struct delayed_work link_work; | ||||
| }; | ||||
| 
 | ||||
| struct xgene_indirect_ctl { | ||||
| 	void __iomem *addr; | ||||
| 	void __iomem *ctl; | ||||
| 	void __iomem *cmd; | ||||
| 	void __iomem *cmd_done; | ||||
| }; | ||||
| 
 | ||||
| /* Set the specified value into a bit-field defined by its starting position
 | ||||
|  * and length within a single u64. | ||||
|  */ | ||||
| static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val) | ||||
| { | ||||
| 	return (val & ((1ULL << len) - 1)) << pos; | ||||
| } | ||||
| 
 | ||||
| #define SET_VAL(field, val) \ | ||||
| 		xgene_enet_set_field_value(field ## _POS, field ## _LEN, val) | ||||
| 
 | ||||
| #define SET_BIT(field) \ | ||||
| 		xgene_enet_set_field_value(field ## _POS, 1, 1) | ||||
| 
 | ||||
| /* Get the value from a bit-field defined by its starting position
 | ||||
|  * and length within the specified u64. | ||||
|  */ | ||||
| static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src) | ||||
| { | ||||
| 	return (src >> pos) & ((1ULL << len) - 1); | ||||
| } | ||||
| 
 | ||||
| #define GET_VAL(field, src) \ | ||||
| 		xgene_enet_get_field_value(field ## _POS, field ## _LEN, src) | ||||
| 
 | ||||
| static inline struct device *ndev_to_dev(struct net_device *ndev) | ||||
| { | ||||
| 	return ndev->dev.parent; | ||||
| } | ||||
| 
 | ||||
| void xgene_enet_set_ethtool_ops(struct net_device *netdev); | ||||
| 
 | ||||
| #endif /* __XGENE_ENET_MAIN_H__ */ | ||||
							
								
								
									
										392
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,392 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  *	    Keyur Chudgar <kchudgar@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include "xgene_enet_main.h" | ||||
| #include "xgene_enet_hw.h" | ||||
| #include "xgene_enet_sgmac.h" | ||||
| 
 | ||||
| static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val) | ||||
| { | ||||
| 	iowrite32(val, p->eth_csr_addr + offset); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *p, | ||||
| 				  u32 offset, u32 val) | ||||
| { | ||||
| 	iowrite32(val, p->eth_ring_if_addr + offset); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *p, | ||||
| 				   u32 offset, u32 val) | ||||
| { | ||||
| 	iowrite32(val, p->eth_diag_csr_addr + offset); | ||||
| } | ||||
| 
 | ||||
| static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl, | ||||
| 				   u32 wr_addr, u32 wr_data) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	iowrite32(wr_addr, ctl->addr); | ||||
| 	iowrite32(wr_data, ctl->ctl); | ||||
| 	iowrite32(XGENE_ENET_WR_CMD, ctl->cmd); | ||||
| 
 | ||||
| 	/* wait for write command to complete */ | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		if (ioread32(ctl->cmd_done)) { | ||||
| 			iowrite32(0, ctl->cmd); | ||||
| 			return true; | ||||
| 		} | ||||
| 		udelay(1); | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_mac(struct xgene_enet_pdata *p, | ||||
| 			      u32 wr_addr, u32 wr_data) | ||||
| { | ||||
| 	struct xgene_indirect_ctl ctl = { | ||||
| 		.addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET, | ||||
| 		.ctl = p->mcx_mac_addr + MAC_WRITE_REG_OFFSET, | ||||
| 		.cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET, | ||||
| 		.cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET | ||||
| 	}; | ||||
| 
 | ||||
| 	if (!xgene_enet_wr_indirect(&ctl, wr_addr, wr_data)) | ||||
| 		netdev_err(p->ndev, "mac write failed, addr: %04x\n", wr_addr); | ||||
| } | ||||
| 
 | ||||
| static u32 xgene_enet_rd_csr(struct xgene_enet_pdata *p, u32 offset) | ||||
| { | ||||
| 	return ioread32(p->eth_csr_addr + offset); | ||||
| } | ||||
| 
 | ||||
| static u32 xgene_enet_rd_diag_csr(struct xgene_enet_pdata *p, u32 offset) | ||||
| { | ||||
| 	return ioread32(p->eth_diag_csr_addr + offset); | ||||
| } | ||||
| 
 | ||||
| static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr) | ||||
| { | ||||
| 	u32 rd_data; | ||||
| 	int i; | ||||
| 
 | ||||
| 	iowrite32(rd_addr, ctl->addr); | ||||
| 	iowrite32(XGENE_ENET_RD_CMD, ctl->cmd); | ||||
| 
 | ||||
| 	/* wait for read command to complete */ | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		if (ioread32(ctl->cmd_done)) { | ||||
| 			rd_data = ioread32(ctl->ctl); | ||||
| 			iowrite32(0, ctl->cmd); | ||||
| 
 | ||||
| 			return rd_data; | ||||
| 		} | ||||
| 		udelay(1); | ||||
| 	} | ||||
| 
 | ||||
| 	pr_err("%s: mac read failed, addr: %04x\n", __func__, rd_addr); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr) | ||||
| { | ||||
| 	struct xgene_indirect_ctl ctl = { | ||||
| 		.addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET, | ||||
| 		.ctl = p->mcx_mac_addr + MAC_READ_REG_OFFSET, | ||||
| 		.cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET, | ||||
| 		.cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET | ||||
| 	}; | ||||
| 
 | ||||
| 	return xgene_enet_rd_indirect(&ctl, rd_addr); | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_ecc_init(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	struct net_device *ndev = p->ndev; | ||||
| 	u32 data; | ||||
| 	int i = 0; | ||||
| 
 | ||||
| 	xgene_enet_wr_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0); | ||||
| 	do { | ||||
| 		usleep_range(100, 110); | ||||
| 		data = xgene_enet_rd_diag_csr(p, ENET_BLOCK_MEM_RDY_ADDR); | ||||
| 		if (data == ~0U) | ||||
| 			return 0; | ||||
| 	} while (++i < 10); | ||||
| 
 | ||||
| 	netdev_err(ndev, "Failed to release memory from shutdown\n"); | ||||
| 	return -ENODEV; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	u32 val = 0xffffffff; | ||||
| 
 | ||||
| 	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val); | ||||
| 	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val); | ||||
| } | ||||
| 
 | ||||
| static void xgene_mii_phy_write(struct xgene_enet_pdata *p, u8 phy_id, | ||||
| 				u32 reg, u16 data) | ||||
| { | ||||
| 	u32 addr, wr_data, done; | ||||
| 	int i; | ||||
| 
 | ||||
| 	addr = PHY_ADDR(phy_id) | REG_ADDR(reg); | ||||
| 	xgene_enet_wr_mac(p, MII_MGMT_ADDRESS_ADDR, addr); | ||||
| 
 | ||||
| 	wr_data = PHY_CONTROL(data); | ||||
| 	xgene_enet_wr_mac(p, MII_MGMT_CONTROL_ADDR, wr_data); | ||||
| 
 | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		done = xgene_enet_rd_mac(p, MII_MGMT_INDICATORS_ADDR); | ||||
| 		if (!(done & BUSY_MASK)) | ||||
| 			return; | ||||
| 		usleep_range(10, 20); | ||||
| 	} | ||||
| 
 | ||||
| 	netdev_err(p->ndev, "MII_MGMT write failed\n"); | ||||
| } | ||||
| 
 | ||||
| static u32 xgene_mii_phy_read(struct xgene_enet_pdata *p, u8 phy_id, u32 reg) | ||||
| { | ||||
| 	u32 addr, data, done; | ||||
| 	int i; | ||||
| 
 | ||||
| 	addr = PHY_ADDR(phy_id) | REG_ADDR(reg); | ||||
| 	xgene_enet_wr_mac(p, MII_MGMT_ADDRESS_ADDR, addr); | ||||
| 	xgene_enet_wr_mac(p, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); | ||||
| 
 | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		done = xgene_enet_rd_mac(p, MII_MGMT_INDICATORS_ADDR); | ||||
| 		if (!(done & BUSY_MASK)) { | ||||
| 			data = xgene_enet_rd_mac(p, MII_MGMT_STATUS_ADDR); | ||||
| 			xgene_enet_wr_mac(p, MII_MGMT_COMMAND_ADDR, 0); | ||||
| 
 | ||||
| 			return data; | ||||
| 		} | ||||
| 		usleep_range(10, 20); | ||||
| 	} | ||||
| 
 | ||||
| 	netdev_err(p->ndev, "MII_MGMT read failed\n"); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_reset(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, SOFT_RESET1); | ||||
| 	xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, 0); | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_set_mac_addr(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	u32 addr0, addr1; | ||||
| 	u8 *dev_addr = p->ndev->dev_addr; | ||||
| 
 | ||||
| 	addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | | ||||
| 		(dev_addr[1] << 8) | dev_addr[0]; | ||||
| 	xgene_enet_wr_mac(p, STATION_ADDR0_ADDR, addr0); | ||||
| 
 | ||||
| 	addr1 = xgene_enet_rd_mac(p, STATION_ADDR1_ADDR); | ||||
| 	addr1 |= (dev_addr[5] << 24) | (dev_addr[4] << 16); | ||||
| 	xgene_enet_wr_mac(p, STATION_ADDR1_ADDR, addr1); | ||||
| } | ||||
| 
 | ||||
| static u32 xgene_enet_link_status(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	data = xgene_mii_phy_read(p, INT_PHY_ADDR, | ||||
| 				  SGMII_BASE_PAGE_ABILITY_ADDR >> 2); | ||||
| 
 | ||||
| 	return data & LINK_UP; | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_init(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	u32 data, loop = 10; | ||||
| 
 | ||||
| 	xgene_sgmac_reset(p); | ||||
| 
 | ||||
| 	/* Enable auto-negotiation */ | ||||
| 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000); | ||||
| 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0); | ||||
| 
 | ||||
| 	while (loop--) { | ||||
| 		data = xgene_mii_phy_read(p, INT_PHY_ADDR, | ||||
| 					  SGMII_STATUS_ADDR >> 2); | ||||
| 		if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS)) | ||||
| 			break; | ||||
| 		usleep_range(10, 20); | ||||
| 	} | ||||
| 	if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS)) | ||||
| 		netdev_err(p->ndev, "Auto-negotiation failed\n"); | ||||
| 
 | ||||
| 	data = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR); | ||||
| 	ENET_INTERFACE_MODE2_SET(&data, 2); | ||||
| 	xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2); | ||||
| 	xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE); | ||||
| 
 | ||||
| 	data = xgene_enet_rd_csr(p, ENET_SPARE_CFG_REG_ADDR); | ||||
| 	data |= MPA_IDLE_WITH_QMI_EMPTY; | ||||
| 	xgene_enet_wr_csr(p, ENET_SPARE_CFG_REG_ADDR, data); | ||||
| 
 | ||||
| 	xgene_sgmac_set_mac_addr(p); | ||||
| 
 | ||||
| 	data = xgene_enet_rd_csr(p, DEBUG_REG_ADDR); | ||||
| 	data |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX; | ||||
| 	xgene_enet_wr_csr(p, DEBUG_REG_ADDR, data); | ||||
| 
 | ||||
| 	/* Adjust MDC clock frequency */ | ||||
| 	data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR); | ||||
| 	MGMT_CLOCK_SEL_SET(&data, 7); | ||||
| 	xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data); | ||||
| 
 | ||||
| 	/* Enable drop if bufpool not available */ | ||||
| 	data = xgene_enet_rd_csr(p, RSIF_CONFIG_REG_ADDR); | ||||
| 	data |= CFG_RSIF_FPBUFF_TIMEOUT_EN; | ||||
| 	xgene_enet_wr_csr(p, RSIF_CONFIG_REG_ADDR, data); | ||||
| 
 | ||||
| 	/* Rtype should be copied from FP */ | ||||
| 	xgene_enet_wr_csr(p, RSIF_RAM_DBG_REG0_ADDR, 0); | ||||
| 
 | ||||
| 	/* Bypass traffic gating */ | ||||
| 	xgene_enet_wr_csr(p, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0); | ||||
| 	xgene_enet_wr_csr(p, CFG_BYPASS_ADDR, RESUME_TX); | ||||
| 	xgene_enet_wr_csr(p, SG_RX_DV_GATE_REG_0_ADDR, RESUME_RX0); | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	data = xgene_enet_rd_mac(p, MAC_CONFIG_1_ADDR); | ||||
| 
 | ||||
| 	if (set) | ||||
| 		data |= bits; | ||||
| 	else | ||||
| 		data &= ~bits; | ||||
| 
 | ||||
| 	xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, data); | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_rx_enable(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	xgene_sgmac_rxtx(p, RX_EN, true); | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_tx_enable(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	xgene_sgmac_rxtx(p, TX_EN, true); | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_rx_disable(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	xgene_sgmac_rxtx(p, RX_EN, false); | ||||
| } | ||||
| 
 | ||||
| static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	xgene_sgmac_rxtx(p, TX_EN, false); | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_reset(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	if (!xgene_ring_mgr_init(p)) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	clk_prepare_enable(p->clk); | ||||
| 	clk_disable_unprepare(p->clk); | ||||
| 	clk_prepare_enable(p->clk); | ||||
| 
 | ||||
| 	xgene_enet_ecc_init(p); | ||||
| 	xgene_enet_config_ring_if_assoc(p); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p, | ||||
| 				  u32 dst_ring_num, u16 bufpool_id) | ||||
| { | ||||
| 	u32 data, fpsel; | ||||
| 
 | ||||
| 	data = CFG_CLE_BYPASS_EN0; | ||||
| 	xgene_enet_wr_csr(p, CLE_BYPASS_REG0_0_ADDR, data); | ||||
| 
 | ||||
| 	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; | ||||
| 	data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel); | ||||
| 	xgene_enet_wr_csr(p, CLE_BYPASS_REG1_0_ADDR, data); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_shutdown(struct xgene_enet_pdata *p) | ||||
| { | ||||
| 	clk_disable_unprepare(p->clk); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_link_state(struct work_struct *work) | ||||
| { | ||||
| 	struct xgene_enet_pdata *p = container_of(to_delayed_work(work), | ||||
| 				     struct xgene_enet_pdata, link_work); | ||||
| 	struct net_device *ndev = p->ndev; | ||||
| 	u32 link, poll_interval; | ||||
| 
 | ||||
| 	link = xgene_enet_link_status(p); | ||||
| 	if (link) { | ||||
| 		if (!netif_carrier_ok(ndev)) { | ||||
| 			netif_carrier_on(ndev); | ||||
| 			xgene_sgmac_init(p); | ||||
| 			xgene_sgmac_rx_enable(p); | ||||
| 			xgene_sgmac_tx_enable(p); | ||||
| 			netdev_info(ndev, "Link is Up - 1Gbps\n"); | ||||
| 		} | ||||
| 		poll_interval = PHY_POLL_LINK_ON; | ||||
| 	} else { | ||||
| 		if (netif_carrier_ok(ndev)) { | ||||
| 			xgene_sgmac_rx_disable(p); | ||||
| 			xgene_sgmac_tx_disable(p); | ||||
| 			netif_carrier_off(ndev); | ||||
| 			netdev_info(ndev, "Link is Down\n"); | ||||
| 		} | ||||
| 		poll_interval = PHY_POLL_LINK_OFF; | ||||
| 	} | ||||
| 
 | ||||
| 	schedule_delayed_work(&p->link_work, poll_interval); | ||||
| } | ||||
| 
 | ||||
| struct xgene_mac_ops xgene_sgmac_ops = { | ||||
| 	.init		= xgene_sgmac_init, | ||||
| 	.reset		= xgene_sgmac_reset, | ||||
| 	.rx_enable	= xgene_sgmac_rx_enable, | ||||
| 	.tx_enable	= xgene_sgmac_tx_enable, | ||||
| 	.rx_disable	= xgene_sgmac_rx_disable, | ||||
| 	.tx_disable	= xgene_sgmac_tx_disable, | ||||
| 	.set_mac_addr	= xgene_sgmac_set_mac_addr, | ||||
| 	.link_state	= xgene_enet_link_state | ||||
| }; | ||||
| 
 | ||||
| struct xgene_port_ops xgene_sgport_ops = { | ||||
| 	.reset		= xgene_enet_reset, | ||||
| 	.cle_bypass	= xgene_enet_cle_bypass, | ||||
| 	.shutdown	= xgene_enet_shutdown | ||||
| }; | ||||
							
								
								
									
										41
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  *	    Keyur Chudgar <kchudgar@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __XGENE_ENET_SGMAC_H__ | ||||
| #define __XGENE_ENET_SGMAC_H__ | ||||
| 
 | ||||
| #define PHY_ADDR(src)		(((src)<<8) & GENMASK(12, 8)) | ||||
| #define REG_ADDR(src)		((src) & GENMASK(4, 0)) | ||||
| #define PHY_CONTROL(src)	((src) & GENMASK(15, 0)) | ||||
| #define INT_PHY_ADDR			0x1e | ||||
| #define SGMII_TBI_CONTROL_ADDR		0x44 | ||||
| #define SGMII_CONTROL_ADDR		0x00 | ||||
| #define SGMII_STATUS_ADDR		0x04 | ||||
| #define SGMII_BASE_PAGE_ABILITY_ADDR	0x14 | ||||
| #define AUTO_NEG_COMPLETE		BIT(5) | ||||
| #define LINK_STATUS			BIT(2) | ||||
| #define LINK_UP				BIT(15) | ||||
| #define MPA_IDLE_WITH_QMI_EMPTY		BIT(12) | ||||
| #define SG_RX_DV_GATE_REG_0_ADDR	0x0dfc | ||||
| 
 | ||||
| extern struct xgene_mac_ops xgene_sgmac_ops; | ||||
| extern struct xgene_port_ops xgene_sgport_ops; | ||||
| 
 | ||||
| #endif  /* __XGENE_ENET_SGMAC_H__ */ | ||||
							
								
								
									
										337
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										337
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,337 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  *	    Keyur Chudgar <kchudgar@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include "xgene_enet_main.h" | ||||
| #include "xgene_enet_hw.h" | ||||
| #include "xgene_enet_xgmac.h" | ||||
| 
 | ||||
| static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata, | ||||
| 			      u32 offset, u32 val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_csr_addr + offset; | ||||
| 
 | ||||
| 	iowrite32(val, addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata, | ||||
| 				  u32 offset, u32 val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_ring_if_addr + offset; | ||||
| 
 | ||||
| 	iowrite32(val, addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata, | ||||
| 				   u32 offset, u32 val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_diag_csr_addr + offset; | ||||
| 
 | ||||
| 	iowrite32(val, addr); | ||||
| } | ||||
| 
 | ||||
| static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, | ||||
| 				   void __iomem *cmd, void __iomem *cmd_done, | ||||
| 				   u32 wr_addr, u32 wr_data) | ||||
| { | ||||
| 	u32 done; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	iowrite32(wr_addr, addr); | ||||
| 	iowrite32(wr_data, wr); | ||||
| 	iowrite32(XGENE_ENET_WR_CMD, cmd); | ||||
| 
 | ||||
| 	/* wait for write command to complete */ | ||||
| 	while (!(done = ioread32(cmd_done)) && wait--) | ||||
| 		udelay(1); | ||||
| 
 | ||||
| 	if (!done) | ||||
| 		return false; | ||||
| 
 | ||||
| 	iowrite32(0, cmd); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, | ||||
| 			      u32 wr_addr, u32 wr_data) | ||||
| { | ||||
| 	void __iomem *addr, *wr, *cmd, *cmd_done; | ||||
| 
 | ||||
| 	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; | ||||
| 	wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET; | ||||
| 	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; | ||||
| 	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; | ||||
| 
 | ||||
| 	if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data)) | ||||
| 		netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n", | ||||
| 			   wr_addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata, | ||||
| 			      u32 offset, u32 *val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_csr_addr + offset; | ||||
| 
 | ||||
| 	*val = ioread32(addr); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata, | ||||
| 				   u32 offset, u32 *val) | ||||
| { | ||||
| 	void __iomem *addr = pdata->eth_diag_csr_addr + offset; | ||||
| 
 | ||||
| 	*val = ioread32(addr); | ||||
| } | ||||
| 
 | ||||
| static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, | ||||
| 				   void __iomem *cmd, void __iomem *cmd_done, | ||||
| 				   u32 rd_addr, u32 *rd_data) | ||||
| { | ||||
| 	u32 done; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	iowrite32(rd_addr, addr); | ||||
| 	iowrite32(XGENE_ENET_RD_CMD, cmd); | ||||
| 
 | ||||
| 	/* wait for read command to complete */ | ||||
| 	while (!(done = ioread32(cmd_done)) && wait--) | ||||
| 		udelay(1); | ||||
| 
 | ||||
| 	if (!done) | ||||
| 		return false; | ||||
| 
 | ||||
| 	*rd_data = ioread32(rd); | ||||
| 	iowrite32(0, cmd); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, | ||||
| 			      u32 rd_addr, u32 *rd_data) | ||||
| { | ||||
| 	void __iomem *addr, *rd, *cmd, *cmd_done; | ||||
| 
 | ||||
| 	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; | ||||
| 	rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; | ||||
| 	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; | ||||
| 	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; | ||||
| 
 | ||||
| 	if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) | ||||
| 		netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", | ||||
| 			   rd_addr); | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	struct net_device *ndev = pdata->ndev; | ||||
| 	u32 data; | ||||
| 	u8 wait = 10; | ||||
| 
 | ||||
| 	xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0); | ||||
| 	do { | ||||
| 		usleep_range(100, 110); | ||||
| 		xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data); | ||||
| 	} while ((data != 0xffffffff) && wait--); | ||||
| 
 | ||||
| 	if (data != 0xffffffff) { | ||||
| 		netdev_err(ndev, "Failed to release memory from shutdown\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, 0); | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, 0); | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, 0); | ||||
| 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, 0); | ||||
| } | ||||
| 
 | ||||
| static void xgene_xgmac_reset(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, HSTMACRST); | ||||
| 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, 0); | ||||
| } | ||||
| 
 | ||||
| static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 addr0, addr1; | ||||
| 	u8 *dev_addr = pdata->ndev->dev_addr; | ||||
| 
 | ||||
| 	addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | | ||||
| 		(dev_addr[1] << 8) | dev_addr[0]; | ||||
| 	addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16); | ||||
| 
 | ||||
| 	xgene_enet_wr_mac(pdata, HSTMACADR_LSW_ADDR, addr0); | ||||
| 	xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1); | ||||
| } | ||||
| 
 | ||||
| static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_csr(pdata, XG_LINK_STATUS_ADDR, &data); | ||||
| 
 | ||||
| 	return data; | ||||
| } | ||||
| 
 | ||||
| static void xgene_xgmac_init(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_xgmac_reset(pdata); | ||||
| 
 | ||||
| 	xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); | ||||
| 	data |= HSTPPEN; | ||||
| 	data &= ~HSTLENCHK; | ||||
| 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data); | ||||
| 
 | ||||
| 	xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR, 0x06000600); | ||||
| 	xgene_xgmac_set_mac_addr(pdata); | ||||
| 
 | ||||
| 	xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data); | ||||
| 	data |= CFG_RSIF_FPBUFF_TIMEOUT_EN; | ||||
| 	xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, data); | ||||
| 
 | ||||
| 	xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX); | ||||
| 	xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0); | ||||
| 	xgene_enet_rd_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, &data); | ||||
| 	data |= BIT(12); | ||||
| 	xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, data); | ||||
| 	xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82); | ||||
| } | ||||
| 
 | ||||
| static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); | ||||
| 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTRFEN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_xgmac_tx_enable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); | ||||
| 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTTFEN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_xgmac_rx_disable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); | ||||
| 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTRFEN); | ||||
| } | ||||
| 
 | ||||
| static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); | ||||
| 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN); | ||||
| } | ||||
| 
 | ||||
| static int xgene_enet_reset(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	if (!xgene_ring_mgr_init(pdata)) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	clk_prepare_enable(pdata->clk); | ||||
| 	clk_disable_unprepare(pdata->clk); | ||||
| 	clk_prepare_enable(pdata->clk); | ||||
| 
 | ||||
| 	xgene_enet_ecc_init(pdata); | ||||
| 	xgene_enet_config_ring_if_assoc(pdata); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata, | ||||
| 				    u32 dst_ring_num, u16 bufpool_id) | ||||
| { | ||||
| 	u32 cb, fpsel; | ||||
| 
 | ||||
| 	xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG0_ADDR, &cb); | ||||
| 	cb |= CFG_CLE_BYPASS_EN0; | ||||
| 	CFG_CLE_IP_PROTOCOL0_SET(&cb, 3); | ||||
| 	xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG0_ADDR, cb); | ||||
| 
 | ||||
| 	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; | ||||
| 	xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb); | ||||
| 	CFG_CLE_DSTQID0_SET(&cb, dst_ring_num); | ||||
| 	CFG_CLE_FPSEL0_SET(&cb, fpsel); | ||||
| 	xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata) | ||||
| { | ||||
| 	clk_disable_unprepare(pdata->clk); | ||||
| } | ||||
| 
 | ||||
| static void xgene_enet_link_state(struct work_struct *work) | ||||
| { | ||||
| 	struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work), | ||||
| 					 struct xgene_enet_pdata, link_work); | ||||
| 	struct net_device *ndev = pdata->ndev; | ||||
| 	u32 link_status, poll_interval; | ||||
| 
 | ||||
| 	link_status = xgene_enet_link_status(pdata); | ||||
| 	if (link_status) { | ||||
| 		if (!netif_carrier_ok(ndev)) { | ||||
| 			netif_carrier_on(ndev); | ||||
| 			xgene_xgmac_init(pdata); | ||||
| 			xgene_xgmac_rx_enable(pdata); | ||||
| 			xgene_xgmac_tx_enable(pdata); | ||||
| 			netdev_info(ndev, "Link is Up - 10Gbps\n"); | ||||
| 		} | ||||
| 		poll_interval = PHY_POLL_LINK_ON; | ||||
| 	} else { | ||||
| 		if (netif_carrier_ok(ndev)) { | ||||
| 			xgene_xgmac_rx_disable(pdata); | ||||
| 			xgene_xgmac_tx_disable(pdata); | ||||
| 			netif_carrier_off(ndev); | ||||
| 			netdev_info(ndev, "Link is Down\n"); | ||||
| 		} | ||||
| 		poll_interval = PHY_POLL_LINK_OFF; | ||||
| 	} | ||||
| 
 | ||||
| 	schedule_delayed_work(&pdata->link_work, poll_interval); | ||||
| } | ||||
| 
 | ||||
| struct xgene_mac_ops xgene_xgmac_ops = { | ||||
| 	.init = xgene_xgmac_init, | ||||
| 	.reset = xgene_xgmac_reset, | ||||
| 	.rx_enable = xgene_xgmac_rx_enable, | ||||
| 	.tx_enable = xgene_xgmac_tx_enable, | ||||
| 	.rx_disable = xgene_xgmac_rx_disable, | ||||
| 	.tx_disable = xgene_xgmac_tx_disable, | ||||
| 	.set_mac_addr = xgene_xgmac_set_mac_addr, | ||||
| 	.link_state = xgene_enet_link_state | ||||
| }; | ||||
| 
 | ||||
| struct xgene_port_ops xgene_xgport_ops = { | ||||
| 	.reset = xgene_enet_reset, | ||||
| 	.cle_bypass = xgene_enet_xgcle_bypass, | ||||
| 	.shutdown = xgene_enet_shutdown, | ||||
| }; | ||||
							
								
								
									
										53
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | |||
| /* Applied Micro X-Gene SoC Ethernet Driver
 | ||||
|  * | ||||
|  * Copyright (c) 2014, Applied Micro Circuits Corporation | ||||
|  * Authors: Iyappan Subramanian <isubramanian@apm.com> | ||||
|  *	    Keyur Chudgar <kchudgar@apm.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute  it and/or modify it | ||||
|  * under  the terms of  the GNU General  Public License as published by the | ||||
|  * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __XGENE_ENET_XGMAC_H__ | ||||
| #define __XGENE_ENET_XGMAC_H__ | ||||
| 
 | ||||
| #define BLOCK_AXG_MAC_OFFSET		0x0800 | ||||
| #define BLOCK_AXG_MAC_CSR_OFFSET	0x2000 | ||||
| 
 | ||||
| #define AXGMAC_CONFIG_0			0x0000 | ||||
| #define AXGMAC_CONFIG_1			0x0004 | ||||
| #define HSTMACRST			BIT(31) | ||||
| #define HSTTCTLEN			BIT(31) | ||||
| #define HSTTFEN				BIT(30) | ||||
| #define HSTRCTLEN			BIT(29) | ||||
| #define HSTRFEN				BIT(28) | ||||
| #define HSTPPEN				BIT(7) | ||||
| #define HSTDRPLT64			BIT(5) | ||||
| #define HSTLENCHK			BIT(3) | ||||
| #define HSTMACADR_LSW_ADDR		0x0010 | ||||
| #define HSTMACADR_MSW_ADDR		0x0014 | ||||
| #define HSTMAXFRAME_LENGTH_ADDR		0x0020 | ||||
| 
 | ||||
| #define XG_RSIF_CONFIG_REG_ADDR		0x00a0 | ||||
| #define XCLE_BYPASS_REG0_ADDR           0x0160 | ||||
| #define XCLE_BYPASS_REG1_ADDR           0x0164 | ||||
| #define XG_CFG_BYPASS_ADDR		0x0204 | ||||
| #define XG_LINK_STATUS_ADDR		0x0228 | ||||
| #define XG_ENET_SPARE_CFG_REG_ADDR	0x040c | ||||
| #define XG_ENET_SPARE_CFG_REG_1_ADDR	0x0410 | ||||
| #define XGENET_RX_DV_GATE_REG_0_ADDR	0x0804 | ||||
| 
 | ||||
| extern struct xgene_mac_ops xgene_xgmac_ops; | ||||
| extern struct xgene_port_ops xgene_xgport_ops; | ||||
| 
 | ||||
| #endif /* __XGENE_ENET_XGMAC_H__ */ | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 awab228
						awab228