diff options
Diffstat (limited to 'drivers/net/ti/cpsw.c')
-rw-r--r-- | drivers/net/ti/cpsw.c | 202 |
1 files changed, 95 insertions, 107 deletions
diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c index f5fd02efe1a..20ddb44dd89 100644 --- a/drivers/net/ti/cpsw.c +++ b/drivers/net/ti/cpsw.c @@ -33,24 +33,6 @@ DECLARE_GLOBAL_DATA_PTR; #define GIGABITEN BIT(7) #define FULLDUPLEXEN BIT(0) #define MIIEN BIT(15) - -/* reg offset */ -#define CPSW_HOST_PORT_OFFSET 0x108 -#define CPSW_SLAVE0_OFFSET 0x208 -#define CPSW_SLAVE1_OFFSET 0x308 -#define CPSW_SLAVE_SIZE 0x100 -#define CPSW_CPDMA_OFFSET 0x800 -#define CPSW_HW_STATS 0x900 -#define CPSW_STATERAM_OFFSET 0xa00 -#define CPSW_CPTS_OFFSET 0xc00 -#define CPSW_ALE_OFFSET 0xd00 -#define CPSW_SLIVER0_OFFSET 0xd80 -#define CPSW_SLIVER1_OFFSET 0xdc0 -#define CPSW_BD_OFFSET 0x2000 -#define CPSW_MDIO_DIV 0xff - -#define AM335X_GMII_SEL_OFFSET 0x630 - /* DMA Registers */ #define CPDMA_TXCONTROL 0x004 #define CPDMA_RXCONTROL 0x014 @@ -209,10 +191,10 @@ struct cpdma_chan { #define chan_read_ptr(chan, fld) ((void *)__raw_readl((chan)->fld)) #define for_active_slave(slave, priv) \ - slave = (priv)->slaves + (priv)->data.active_slave; if (slave) + slave = (priv)->slaves + ((priv)->data)->active_slave; if (slave) #define for_each_slave(slave, priv) \ for (slave = (priv)->slaves; slave != (priv)->slaves + \ - (priv)->data.slaves; slave++) + ((priv)->data)->slaves; slave++) struct cpsw_priv { #ifdef CONFIG_DM_ETH @@ -220,7 +202,7 @@ struct cpsw_priv { #else struct eth_device *dev; #endif - struct cpsw_platform_data data; + struct cpsw_platform_data *data; int host_port; struct cpsw_regs *regs; @@ -327,7 +309,7 @@ static int cpsw_ale_match_addr(struct cpsw_priv *priv, const u8 *addr) u32 ale_entry[ALE_ENTRY_WORDS]; int type, idx; - for (idx = 0; idx < priv->data.ale_entries; idx++) { + for (idx = 0; idx < priv->data->ale_entries; idx++) { u8 entry_addr[6]; cpsw_ale_read(priv, idx, ale_entry); @@ -346,7 +328,7 @@ static int cpsw_ale_match_free(struct cpsw_priv *priv) u32 ale_entry[ALE_ENTRY_WORDS]; int type, idx; - for (idx = 0; idx < priv->data.ale_entries; idx++) { + for (idx = 0; idx < priv->data->ale_entries; idx++) { cpsw_ale_read(priv, idx, ale_entry); type = cpsw_ale_get_entry_type(ale_entry); if (type == ALE_TYPE_FREE) @@ -360,7 +342,7 @@ static int cpsw_ale_find_ageable(struct cpsw_priv *priv) u32 ale_entry[ALE_ENTRY_WORDS]; int type, idx; - for (idx = 0; idx < priv->data.ale_entries; idx++) { + for (idx = 0; idx < priv->data->ale_entries; idx++) { cpsw_ale_read(priv, idx, ale_entry); type = cpsw_ale_get_entry_type(ale_entry); if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR) @@ -500,7 +482,7 @@ static int cpsw_slave_update_link(struct cpsw_slave *slave, *link = phy->link; if (phy->link) { /* link up */ - mac_control = priv->data.mac_control; + mac_control = priv->data->mac_control; if (phy->speed == 1000) mac_control |= GIGABITEN; if (phy->duplex == DUPLEX_FULL) @@ -710,7 +692,7 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) priv->desc_free = &priv->descs[0]; /* initialize channels */ - if (priv->data.version == CPSW_CTRL_VERSION_2) { + if (priv->data->version == CPSW_CTRL_VERSION_2) { memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan)); priv->rx_chan.hdp = priv->dma_regs + CPDMA_RXHDP_VER2; priv->rx_chan.cp = priv->dma_regs + CPDMA_RXCP_VER2; @@ -733,8 +715,8 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) /* clear dma state */ setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET); - if (priv->data.version == CPSW_CTRL_VERSION_2) { - for (i = 0; i < priv->data.channels; i++) { + if (priv->data->version == CPSW_CTRL_VERSION_2) { + for (i = 0; i < priv->data->channels; i++) { __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4 * i); __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4 @@ -747,7 +729,7 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) * i); } } else { - for (i = 0; i < priv->data.channels; i++) { + for (i = 0; i < priv->data->channels; i++) { __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4 * i); __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4 @@ -843,7 +825,7 @@ static void cpsw_slave_setup(struct cpsw_slave *slave, int slave_num, struct cpsw_priv *priv) { void *regs = priv->regs; - struct cpsw_slave_data *data = priv->data.slave_data + slave_num; + struct cpsw_slave_data *data = priv->data->slave_data + slave_num; slave->slave_num = slave_num; slave->data = data; slave->regs = regs + data->slave_reg_ofs; @@ -879,7 +861,7 @@ static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave) static void cpsw_phy_addr_update(struct cpsw_priv *priv) { - struct cpsw_platform_data *data = &priv->data; + struct cpsw_platform_data *data = priv->data; u16 alive = cpsw_mdio_get_alive(priv->bus); int active = data->active_slave; int new_addr = ffs(alive) - 1; @@ -899,7 +881,7 @@ static void cpsw_phy_addr_update(struct cpsw_priv *priv) int _cpsw_register(struct cpsw_priv *priv) { struct cpsw_slave *slave; - struct cpsw_platform_data *data = &priv->data; + struct cpsw_platform_data *data = priv->data; void *regs = (void *)data->cpsw_base; priv->slaves = malloc(sizeof(struct cpsw_slave) * data->slaves); @@ -988,7 +970,7 @@ int cpsw_register(struct cpsw_platform_data *data) } priv->dev = dev; - priv->data = *data; + priv->data = data; strcpy(dev->name, "cpsw"); dev->iobase = 0; @@ -1048,16 +1030,6 @@ static void cpsw_eth_stop(struct udevice *dev) return _cpsw_halt(priv); } - -static int cpsw_eth_probe(struct udevice *dev) -{ - struct cpsw_priv *priv = dev_get_priv(dev); - - priv->dev = dev; - - return _cpsw_register(priv); -} - static const struct eth_ops cpsw_eth_ops = { .start = cpsw_eth_start, .send = cpsw_eth_send, @@ -1079,9 +1051,9 @@ static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, u32 mask; u32 mode = 0; bool rgmii_id = false; - int slave = priv->data.active_slave; + int slave = priv->data->active_slave; - reg = readl(priv->data.gmii_sel); + reg = readl(priv->data->gmii_sel); switch (phy_mode) { case PHY_INTERFACE_MODE_RMII: @@ -1107,7 +1079,7 @@ static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6); mode <<= slave * 2; - if (priv->data.rmii_clock_external) { + if (priv->data->rmii_clock_external) { if (slave == 0) mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN; else @@ -1124,7 +1096,7 @@ static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, reg &= ~mask; reg |= mode; - writel(reg, priv->data.gmii_sel); + writel(reg, priv->data->gmii_sel); } static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, @@ -1133,9 +1105,9 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, u32 reg; u32 mask; u32 mode = 0; - int slave = priv->data.active_slave; + int slave = priv->data->active_slave; - reg = readl(priv->data.gmii_sel); + reg = readl(priv->data->gmii_sel); switch (phy_mode) { case PHY_INTERFACE_MODE_RMII: @@ -1168,13 +1140,13 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, return; } - if (priv->data.rmii_clock_external) + if (priv->data->rmii_clock_external) dev_err(priv->dev, "RMII External clock is not supported\n"); reg &= ~mask; reg |= mode; - writel(reg, priv->data.gmii_sel); + writel(reg, priv->data->gmii_sel); } static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, @@ -1188,13 +1160,28 @@ static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, cpsw_gmii_sel_dra7xx(priv, phy_mode); } +static int cpsw_eth_probe(struct udevice *dev) +{ + struct cpsw_priv *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + priv->dev = dev; + priv->data = pdata->priv_pdata; + ti_cm_get_macid(dev, priv->data, pdata->enetaddr); + /* Select phy interface in control module */ + cpsw_phy_sel(priv, priv->data->phy_sel_compat, + pdata->phy_interface); + + return _cpsw_register(priv); +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); - struct cpsw_priv *priv = dev_get_priv(dev); + struct cpsw_platform_data *data; struct gpio_desc *mode_gpios; const char *phy_mode; - const char *phy_sel_compat = NULL; const void *fdt = gd->fdt_blob; int node = dev_of_offset(dev); int subnode; @@ -1203,45 +1190,47 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) int num_mode_gpios; int ret; + data = calloc(1, sizeof(struct cpsw_platform_data)); + pdata->priv_pdata = data; pdata->iobase = devfdt_get_addr(dev); - priv->data.version = CPSW_CTRL_VERSION_2; - priv->data.bd_ram_ofs = CPSW_BD_OFFSET; - priv->data.ale_reg_ofs = CPSW_ALE_OFFSET; - priv->data.cpdma_reg_ofs = CPSW_CPDMA_OFFSET; - priv->data.mdio_div = CPSW_MDIO_DIV; - priv->data.host_port_reg_ofs = CPSW_HOST_PORT_OFFSET, + data->version = CPSW_CTRL_VERSION_2; + data->bd_ram_ofs = CPSW_BD_OFFSET; + data->ale_reg_ofs = CPSW_ALE_OFFSET; + data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET; + data->mdio_div = CPSW_MDIO_DIV; + data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET, pdata->phy_interface = -1; - priv->data.cpsw_base = pdata->iobase; - priv->data.channels = fdtdec_get_int(fdt, node, "cpdma_channels", -1); - if (priv->data.channels <= 0) { + data->cpsw_base = pdata->iobase; + data->channels = fdtdec_get_int(fdt, node, "cpdma_channels", -1); + if (data->channels <= 0) { printf("error: cpdma_channels not found in dt\n"); return -ENOENT; } - priv->data.slaves = fdtdec_get_int(fdt, node, "slaves", -1); - if (priv->data.slaves <= 0) { + data->slaves = fdtdec_get_int(fdt, node, "slaves", -1); + if (data->slaves <= 0) { printf("error: slaves not found in dt\n"); return -ENOENT; } - priv->data.slave_data = malloc(sizeof(struct cpsw_slave_data) * - priv->data.slaves); + data->slave_data = malloc(sizeof(struct cpsw_slave_data) * + data->slaves); - priv->data.ale_entries = fdtdec_get_int(fdt, node, "ale_entries", -1); - if (priv->data.ale_entries <= 0) { + data->ale_entries = fdtdec_get_int(fdt, node, "ale_entries", -1); + if (data->ale_entries <= 0) { printf("error: ale_entries not found in dt\n"); return -ENOENT; } - priv->data.bd_ram_ofs = fdtdec_get_int(fdt, node, "bd_ram_size", -1); - if (priv->data.bd_ram_ofs <= 0) { + data->bd_ram_ofs = fdtdec_get_int(fdt, node, "bd_ram_size", -1); + if (data->bd_ram_ofs <= 0) { printf("error: bd_ram_size not found in dt\n"); return -ENOENT; } - priv->data.mac_control = fdtdec_get_int(fdt, node, "mac_control", -1); - if (priv->data.mac_control <= 0) { + data->mac_control = fdtdec_get_int(fdt, node, "mac_control", -1); + if (data->mac_control <= 0) { printf("error: ale_entries not found in dt\n"); return -ENOENT; } @@ -1256,7 +1245,7 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) } active_slave = fdtdec_get_int(fdt, node, "active_slave", 0); - priv->data.active_slave = active_slave; + data->active_slave = active_slave; fdt_for_each_subnode(subnode, fdt, node) { int len; @@ -1271,108 +1260,107 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) pr_err("Not able to get MDIO address space\n"); return -ENOENT; } - priv->data.mdio_base = mdio_base; + data->mdio_base = mdio_base; } if (!strncmp(name, "slave", 5)) { u32 phy_id[2]; - if (slave_index >= priv->data.slaves) + if (slave_index >= data->slaves) continue; phy_mode = fdt_getprop(fdt, subnode, "phy-mode", NULL); if (phy_mode) - priv->data.slave_data[slave_index].phy_if = + data->slave_data[slave_index].phy_if = phy_get_interface_by_name(phy_mode); - priv->data.slave_data[slave_index].phy_of_handle = + data->slave_data[slave_index].phy_of_handle = fdtdec_lookup_phandle(fdt, subnode, "phy-handle"); - if (priv->data.slave_data[slave_index].phy_of_handle >= 0) { - priv->data.slave_data[slave_index].phy_addr = + if (data->slave_data[slave_index].phy_of_handle >= 0) { + data->slave_data[slave_index].phy_addr = fdtdec_get_int(gd->fdt_blob, - priv->data.slave_data[slave_index].phy_of_handle, + data->slave_data[slave_index].phy_of_handle, "reg", -1); } else { fdtdec_get_int_array(fdt, subnode, "phy_id", phy_id, 2); - priv->data.slave_data[slave_index].phy_addr = + data->slave_data[slave_index].phy_addr = phy_id[1]; } slave_index++; } if (!strncmp(name, "cpsw-phy-sel", 12)) { - priv->data.gmii_sel = cpsw_get_addr_by_node(fdt, - subnode); + data->gmii_sel = cpsw_get_addr_by_node(fdt, subnode); - if (priv->data.gmii_sel == FDT_ADDR_T_NONE) { + if (data->gmii_sel == FDT_ADDR_T_NONE) { pr_err("Not able to get gmii_sel reg address\n"); return -ENOENT; } if (fdt_get_property(fdt, subnode, "rmii-clock-ext", NULL)) - priv->data.rmii_clock_external = true; + data->rmii_clock_external = true; - phy_sel_compat = fdt_getprop(fdt, subnode, "compatible", - NULL); - if (!phy_sel_compat) { + data->phy_sel_compat = fdt_getprop(fdt, subnode, + "compatible", NULL); + if (!data->phy_sel_compat) { pr_err("Not able to get gmii_sel compatible\n"); return -ENOENT; } } } - priv->data.slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET; - priv->data.slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET; + data->slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET; + data->slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET; - if (priv->data.slaves == 2) { - priv->data.slave_data[1].slave_reg_ofs = CPSW_SLAVE1_OFFSET; - priv->data.slave_data[1].sliver_reg_ofs = CPSW_SLIVER1_OFFSET; + if (data->slaves == 2) { + data->slave_data[1].slave_reg_ofs = CPSW_SLAVE1_OFFSET; + data->slave_data[1].sliver_reg_ofs = CPSW_SLIVER1_OFFSET; } - ret = ti_cm_get_macid(dev, active_slave, pdata->enetaddr); + ret = ti_cm_get_macid_addr(dev, active_slave, data); if (ret < 0) { pr_err("cpsw read efuse mac failed\n"); return ret; } - pdata->phy_interface = priv->data.slave_data[active_slave].phy_if; + pdata->phy_interface = data->slave_data[active_slave].phy_if; if (pdata->phy_interface == -1) { debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); return -EINVAL; } - /* Select phy interface in control module */ - cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface); - return 0; } +static const struct udevice_id cpsw_eth_ids[] = { + { .compatible = "ti,cpsw" }, + { .compatible = "ti,am335x-cpsw" }, + { } +}; +#endif + int cpsw_get_slave_phy_addr(struct udevice *dev, int slave) { struct cpsw_priv *priv = dev_get_priv(dev); - struct cpsw_platform_data *data = &priv->data; + struct cpsw_platform_data *data = priv->data; return data->slave_data[slave].phy_addr; } -static const struct udevice_id cpsw_eth_ids[] = { - { .compatible = "ti,cpsw" }, - { .compatible = "ti,am335x-cpsw" }, - { } -}; - U_BOOT_DRIVER(eth_cpsw) = { .name = "eth_cpsw", .id = UCLASS_ETH, +#if CONFIG_IS_ENABLED(OF_CONTROL) .of_match = cpsw_eth_ids, .ofdata_to_platdata = cpsw_eth_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +#endif .probe = cpsw_eth_probe, .ops = &cpsw_eth_ops, .priv_auto_alloc_size = sizeof(struct cpsw_priv), - .platdata_auto_alloc_size = sizeof(struct eth_pdata), - .flags = DM_FLAG_ALLOC_PRIV_DMA, + .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_PRE_RELOC, }; #endif /* CONFIG_DM_ETH */ |