1e6a84624SGrygorii Strashko // SPDX-License-Identifier: GPL-2.0
2e6a84624SGrygorii Strashko /*
3e6a84624SGrygorii Strashko  * Texas Instruments Ethernet Switch Driver
4e6a84624SGrygorii Strashko  *
5e6a84624SGrygorii Strashko  * Copyright (C) 2019 Texas Instruments
6e6a84624SGrygorii Strashko  */
7e6a84624SGrygorii Strashko 
8e6a84624SGrygorii Strashko #include <linux/if_ether.h>
9e6a84624SGrygorii Strashko #include <linux/if_vlan.h>
10e6a84624SGrygorii Strashko #include <linux/module.h>
11e6a84624SGrygorii Strashko #include <linux/netdevice.h>
12e6a84624SGrygorii Strashko #include <linux/phy.h>
13e6a84624SGrygorii Strashko #include <linux/platform_device.h>
14e6a84624SGrygorii Strashko #include <linux/skbuff.h>
15e6a84624SGrygorii Strashko 
16e6a84624SGrygorii Strashko #include "cpts.h"
17e6a84624SGrygorii Strashko #include "cpsw_ale.h"
18e6a84624SGrygorii Strashko #include "cpsw_priv.h"
19e6a84624SGrygorii Strashko #include "davinci_cpdma.h"
20e6a84624SGrygorii Strashko 
21e6a84624SGrygorii Strashko int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs,
22e6a84624SGrygorii Strashko 		     int ale_ageout, phys_addr_t desc_mem_phys,
23e6a84624SGrygorii Strashko 		     int descs_pool_size)
24e6a84624SGrygorii Strashko {
25e6a84624SGrygorii Strashko 	u32 slave_offset, sliver_offset, slave_size;
26e6a84624SGrygorii Strashko 	struct cpsw_ale_params ale_params;
27e6a84624SGrygorii Strashko 	struct cpsw_platform_data *data;
28e6a84624SGrygorii Strashko 	struct cpdma_params dma_params;
29e6a84624SGrygorii Strashko 	struct device *dev = cpsw->dev;
30e6a84624SGrygorii Strashko 	void __iomem *cpts_regs;
31e6a84624SGrygorii Strashko 	int ret = 0, i;
32e6a84624SGrygorii Strashko 
33e6a84624SGrygorii Strashko 	data = &cpsw->data;
34e6a84624SGrygorii Strashko 	cpsw->rx_ch_num = 1;
35e6a84624SGrygorii Strashko 	cpsw->tx_ch_num = 1;
36e6a84624SGrygorii Strashko 
37e6a84624SGrygorii Strashko 	cpsw->version = readl(&cpsw->regs->id_ver);
38e6a84624SGrygorii Strashko 
39e6a84624SGrygorii Strashko 	memset(&dma_params, 0, sizeof(dma_params));
40e6a84624SGrygorii Strashko 	memset(&ale_params, 0, sizeof(ale_params));
41e6a84624SGrygorii Strashko 
42e6a84624SGrygorii Strashko 	switch (cpsw->version) {
43e6a84624SGrygorii Strashko 	case CPSW_VERSION_1:
44e6a84624SGrygorii Strashko 		cpsw->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
45e6a84624SGrygorii Strashko 		cpts_regs	     = ss_regs + CPSW1_CPTS_OFFSET;
46e6a84624SGrygorii Strashko 		cpsw->hw_stats	     = ss_regs + CPSW1_HW_STATS;
47e6a84624SGrygorii Strashko 		dma_params.dmaregs   = ss_regs + CPSW1_CPDMA_OFFSET;
48e6a84624SGrygorii Strashko 		dma_params.txhdp     = ss_regs + CPSW1_STATERAM_OFFSET;
49e6a84624SGrygorii Strashko 		ale_params.ale_regs  = ss_regs + CPSW1_ALE_OFFSET;
50e6a84624SGrygorii Strashko 		slave_offset         = CPSW1_SLAVE_OFFSET;
51e6a84624SGrygorii Strashko 		slave_size           = CPSW1_SLAVE_SIZE;
52e6a84624SGrygorii Strashko 		sliver_offset        = CPSW1_SLIVER_OFFSET;
53e6a84624SGrygorii Strashko 		dma_params.desc_mem_phys = 0;
54e6a84624SGrygorii Strashko 		break;
55e6a84624SGrygorii Strashko 	case CPSW_VERSION_2:
56e6a84624SGrygorii Strashko 	case CPSW_VERSION_3:
57e6a84624SGrygorii Strashko 	case CPSW_VERSION_4:
58e6a84624SGrygorii Strashko 		cpsw->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
59e6a84624SGrygorii Strashko 		cpts_regs	     = ss_regs + CPSW2_CPTS_OFFSET;
60e6a84624SGrygorii Strashko 		cpsw->hw_stats	     = ss_regs + CPSW2_HW_STATS;
61e6a84624SGrygorii Strashko 		dma_params.dmaregs   = ss_regs + CPSW2_CPDMA_OFFSET;
62e6a84624SGrygorii Strashko 		dma_params.txhdp     = ss_regs + CPSW2_STATERAM_OFFSET;
63e6a84624SGrygorii Strashko 		ale_params.ale_regs  = ss_regs + CPSW2_ALE_OFFSET;
64e6a84624SGrygorii Strashko 		slave_offset         = CPSW2_SLAVE_OFFSET;
65e6a84624SGrygorii Strashko 		slave_size           = CPSW2_SLAVE_SIZE;
66e6a84624SGrygorii Strashko 		sliver_offset        = CPSW2_SLIVER_OFFSET;
67e6a84624SGrygorii Strashko 		dma_params.desc_mem_phys = desc_mem_phys;
68e6a84624SGrygorii Strashko 		break;
69e6a84624SGrygorii Strashko 	default:
70e6a84624SGrygorii Strashko 		dev_err(dev, "unknown version 0x%08x\n", cpsw->version);
71e6a84624SGrygorii Strashko 		return -ENODEV;
72e6a84624SGrygorii Strashko 	}
73e6a84624SGrygorii Strashko 
74e6a84624SGrygorii Strashko 	for (i = 0; i < cpsw->data.slaves; i++) {
75e6a84624SGrygorii Strashko 		struct cpsw_slave *slave = &cpsw->slaves[i];
76e6a84624SGrygorii Strashko 		void __iomem		*regs = cpsw->regs;
77e6a84624SGrygorii Strashko 
78e6a84624SGrygorii Strashko 		slave->slave_num = i;
79e6a84624SGrygorii Strashko 		slave->data	= &cpsw->data.slave_data[i];
80e6a84624SGrygorii Strashko 		slave->regs	= regs + slave_offset;
81e6a84624SGrygorii Strashko 		slave->sliver	= regs + sliver_offset;
82e6a84624SGrygorii Strashko 		slave->port_vlan = slave->data->dual_emac_res_vlan;
83e6a84624SGrygorii Strashko 
84e6a84624SGrygorii Strashko 		slave_offset  += slave_size;
85e6a84624SGrygorii Strashko 		sliver_offset += SLIVER_SIZE;
86e6a84624SGrygorii Strashko 	}
87e6a84624SGrygorii Strashko 
88e6a84624SGrygorii Strashko 	ale_params.dev			= dev;
89e6a84624SGrygorii Strashko 	ale_params.ale_ageout		= ale_ageout;
90e6a84624SGrygorii Strashko 	ale_params.ale_entries		= data->ale_entries;
91e6a84624SGrygorii Strashko 	ale_params.ale_ports		= CPSW_ALE_PORTS_NUM;
92e6a84624SGrygorii Strashko 
93e6a84624SGrygorii Strashko 	cpsw->ale = cpsw_ale_create(&ale_params);
94e6a84624SGrygorii Strashko 	if (!cpsw->ale) {
95e6a84624SGrygorii Strashko 		dev_err(dev, "error initializing ale engine\n");
96e6a84624SGrygorii Strashko 		return -ENODEV;
97e6a84624SGrygorii Strashko 	}
98e6a84624SGrygorii Strashko 
99e6a84624SGrygorii Strashko 	dma_params.dev		= dev;
100e6a84624SGrygorii Strashko 	dma_params.rxthresh	= dma_params.dmaregs + CPDMA_RXTHRESH;
101e6a84624SGrygorii Strashko 	dma_params.rxfree	= dma_params.dmaregs + CPDMA_RXFREE;
102e6a84624SGrygorii Strashko 	dma_params.rxhdp	= dma_params.txhdp + CPDMA_RXHDP;
103e6a84624SGrygorii Strashko 	dma_params.txcp		= dma_params.txhdp + CPDMA_TXCP;
104e6a84624SGrygorii Strashko 	dma_params.rxcp		= dma_params.txhdp + CPDMA_RXCP;
105e6a84624SGrygorii Strashko 
106e6a84624SGrygorii Strashko 	dma_params.num_chan		= data->channels;
107e6a84624SGrygorii Strashko 	dma_params.has_soft_reset	= true;
108e6a84624SGrygorii Strashko 	dma_params.min_packet_size	= CPSW_MIN_PACKET_SIZE;
109e6a84624SGrygorii Strashko 	dma_params.desc_mem_size	= data->bd_ram_size;
110e6a84624SGrygorii Strashko 	dma_params.desc_align		= 16;
111e6a84624SGrygorii Strashko 	dma_params.has_ext_regs		= true;
112e6a84624SGrygorii Strashko 	dma_params.desc_hw_addr         = dma_params.desc_mem_phys;
113e6a84624SGrygorii Strashko 	dma_params.bus_freq_mhz		= cpsw->bus_freq_mhz;
114e6a84624SGrygorii Strashko 	dma_params.descs_pool_size	= descs_pool_size;
115e6a84624SGrygorii Strashko 
116e6a84624SGrygorii Strashko 	cpsw->dma = cpdma_ctlr_create(&dma_params);
117e6a84624SGrygorii Strashko 	if (!cpsw->dma) {
118e6a84624SGrygorii Strashko 		dev_err(dev, "error initializing dma\n");
119e6a84624SGrygorii Strashko 		return -ENOMEM;
120e6a84624SGrygorii Strashko 	}
121e6a84624SGrygorii Strashko 
122e6a84624SGrygorii Strashko 	cpsw->cpts = cpts_create(cpsw->dev, cpts_regs, cpsw->dev->of_node);
123e6a84624SGrygorii Strashko 	if (IS_ERR(cpsw->cpts)) {
124e6a84624SGrygorii Strashko 		ret = PTR_ERR(cpsw->cpts);
125e6a84624SGrygorii Strashko 		cpdma_ctlr_destroy(cpsw->dma);
126e6a84624SGrygorii Strashko 	}
127e6a84624SGrygorii Strashko 
128e6a84624SGrygorii Strashko 	return ret;
129e6a84624SGrygorii Strashko }
130