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