#include <common.h>
#include <command.h>
+#include <cpsw.h>
#include <net.h>
#include <miiphy.h>
#include <malloc.h>
#include <asm/arch/cpu.h>
#define BITMASK(bits) (BIT(bits) - 1)
+
#define PHY_REG_MASK 0x1f
#define PHY_ID_MASK 0x1f
#define NUM_DESCS (PKTBUFSRX * 2)
#define PKT_MIN 60
#define PKT_MAX (1500 + 14 + 4 + 4)
#define CLEAR_BIT 1
+
+/* MAC_CONTROL register bits */
#define GIGABITEN BIT(7)
#define FULLDUPLEXEN BIT(0)
+#define MAC_CTRL_CMD_IDLE BIT(11)
#define MIIEN BIT(15)
+/* MAC_STATUS register bits */
+#define MAC_STAT_IDLE BIT(31)
+
/* DMA Registers */
#define CPDMA_TXCONTROL 0x004
#define CPDMA_RXCONTROL 0x014
#define CPDMA_SOFTRESET 0x01c
+#define CPDMA_DMACONTROL 0x020
+#define CPDMA_DMASTATUS 0x024
#define CPDMA_RXFREE 0x0e0
#define CPDMA_TXHDP_VER1 0x100
#define CPDMA_TXHDP_VER2 0x200
#define CPDMA_RXCP_VER1 0x160
#define CPDMA_RXCP_VER2 0x260
-#define CPDMA_RAM_ADDR 0x4a102000
+#define DMACONTROL_CMD_IDLE BIT(3)
+
+#define DMASTATUS_IDLE BIT(31)
/* Descriptor mode bits */
#define CPDMA_DESC_SOP BIT(31)
u32 flow_thresh;
u32 port_vlan;
u32 tx_pri_map;
+#ifdef CONFIG_AM33XX
u32 gap_thresh;
+#elif defined(CONFIG_TI814X)
+ u32 ts_ctl;
+ u32 ts_seq_ltype;
+ u32 ts_vlan;
+#endif
u32 sa_lo;
u32 sa_hi;
};
#define chan_read(chan, fld) __raw_readl((chan)->fld)
#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)
#define for_each_slave(slave, priv) \
for (slave = (priv)->slaves; slave != (priv)->slaves + \
(priv)->data->slaves; slave++)
struct cpsw_slave *slaves;
struct phy_device *phydev;
struct mii_dev *bus;
+
+ u32 phy_mask;
};
static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
}
-static inline void cpsw_ale_set_addr(u32 *ale_entry, u8 *addr)
+static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
{
int i;
return idx;
}
-static int cpsw_ale_match_addr(struct cpsw_priv *priv, u8* addr)
+static int cpsw_ale_match_addr(struct cpsw_priv *priv, const u8 *addr)
{
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
return -ENOENT;
}
-static int cpsw_ale_add_ucast(struct cpsw_priv *priv, u8 *addr,
+static int cpsw_ale_add_ucast(struct cpsw_priv *priv, const u8 *addr,
int port, int flags)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
return 0;
}
-static int cpsw_ale_add_mcast(struct cpsw_priv *priv, u8 *addr, int port_mask)
+static int cpsw_ale_add_mcast(struct cpsw_priv *priv, const u8 *addr,
+ int port_mask)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx, mask;
static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
int dev_addr, int phy_reg)
{
- unsigned short data;
+ int data;
u32 reg;
if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
int link = 0;
struct cpsw_slave *slave;
- for_each_slave(slave, priv)
+ for_active_slave(slave, priv)
cpsw_slave_update_link(slave, priv, &link);
return link;
}
-static inline u32 cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+static inline u32 cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
{
if (priv->host_port == 0)
return slave_num + 1;
slave_port = cpsw_get_slave_port(priv, slave->slave_num);
cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD);
- cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << slave_port);
+ cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << slave_port);
+
+ priv->phy_mask |= 1 << slave->data->phy_addr;
}
static void cpdma_desc_get(struct cpsw_desc *desc)
/* enable statistics collection only on the host port */
__raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);
+ __raw_writel(0x7, &priv->regs->stat_port_en);
cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);
cpsw_ale_add_ucast(priv, priv->dev->enetaddr, priv->host_port,
ALE_SECURE);
- cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << priv->host_port);
+ cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << priv->host_port);
- for_each_slave(slave, priv)
+ for_active_slave(slave, priv)
cpsw_slave_init(slave, priv);
cpsw_update_link(priv);
/* submit rx descs */
for (i = 0; i < PKTBUFSRX; i++) {
- ret = cpdma_submit(priv, &priv->rx_chan, NetRxPackets[i],
+ ret = cpdma_submit(priv, &priv->rx_chan, net_rx_packets[i],
PKTSIZE);
if (ret < 0) {
printf("error %d submitting rx desc\n", ret);
static void cpsw_halt(struct eth_device *dev)
{
struct cpsw_priv *priv = dev->priv;
+ struct cpsw_slave *slave;
+ int idle = 0;
+ int timeout = 1000000;
+
+ __raw_writel(DMACONTROL_CMD_IDLE, priv->dma_regs + CPDMA_DMACONTROL);
+ while (!(__raw_readl(priv->dma_regs + CPDMA_DMASTATUS) &
+ DMASTATUS_IDLE) && (--timeout >= 0))
+ udelay(1);
+
+ timeout = 1000000;
+ while (!idle) {
+ idle = 1;
+ for_each_slave(slave, priv) {
+ if (!(__raw_readl(&slave->sliver->mac_status) &
+ MAC_STAT_IDLE)) {
+ idle = 0;
+ break;
+ }
+ }
+ if (idle || --timeout < 0)
+ break;
+ udelay(1);
+ }
+ if (!idle)
+ printf("CPSW: Aborting DMA transfers; packets may be lost\n");
writel(0, priv->dma_regs + CPDMA_TXCONTROL);
writel(0, priv->dma_regs + CPDMA_RXCONTROL);
void *buffer;
int len;
- debug("%s@%d: sending packet %p..%p\n", __func__, __LINE__,
- packet, packet + length - 1);
-
- if (!priv->data->mac_control && !cpsw_update_link(priv)) {
- printf("%s: Cannot send packet; link is down\n", __func__);
- return -EIO;
- }
/* first reap completed packets */
while (cpdma_process(priv, &priv->tx_chan, &buffer, &len) == 0)
while (cpdma_process(priv, &priv->rx_chan, &buffer, &len) == 0) {
if (buffer) {
- NetReceive(buffer, len);
+ net_process_received_packet(buffer, len);
cpdma_submit(priv, &priv->rx_chan, buffer, PKTSIZE);
} else {
printf("NULL buffer returned from cpdma_process\n");
{
struct cpsw_priv *priv = (struct cpsw_priv *)dev->priv;
struct phy_device *phydev;
- u32 supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full);
+ u32 supported = PHY_GBIT_FEATURES;
- if (slave->data->phy_id < 0) {
+ if (slave->data->phy_addr < 0) {
u32 phy_addr;
for (phy_addr = 0; phy_addr < 32; phy_addr++) {
}
} else {
phydev = phy_connect(priv->bus,
- slave->data->phy_id,
+ slave->data->phy_addr,
dev,
slave->data->phy_if);
}
return -EINVAL;
}
+ if (!phydev)
+ return -1;
+
phydev->supported &= supported;
phydev->advertising = phydev->supported;
struct cpsw_slave *slave;
void *regs = (void *)data->cpsw_base;
struct eth_device *dev;
- int i;
int idx = 0;
debug("%s@%d\n", __func__, __LINE__);
return -ENOMEM;
}
- for (i = 0; i < NUM_DESCS; i++) {
- priv->descs[i].dma_desc = memalign(CONFIG_SYS_CACHELINE_SIZE,
- sizeof(struct cpsw_desc) * NUM_DESCS);
- if (!priv->descs[i].dma_desc) {
- while (--i >= 0) {
- free(priv->descs[i].dma_desc);
- }
- free(priv->slaves);
- free(priv);
- free(dev);
- return -ENOMEM;
- }
- debug("DMA desc[%d] allocated @ %p desc_size %u\n",
- i, priv->descs[i].dma_desc,
- sizeof(*priv->descs[i].dma_desc));
- }
-
priv->host_port = data->host_port_num;
priv->regs = regs;
priv->host_port_regs = regs + data->host_port_reg_ofs;
cpsw_mdio_init(dev->name, data->mdio_base, data->mdio_div);
priv->bus = miiphy_get_dev_by_name(dev->name);
- for_each_slave(slave, priv) {
+ for_active_slave(slave, priv)
ret = cpsw_phy_init(dev, slave);
- if (ret < 0)
- break;
- }
+
return ret;
}