summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/samsung/sxgbe
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/samsung/sxgbe')
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h2
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c22
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c11
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h42
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c13
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c31
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c14
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h4
8 files changed, 100 insertions, 39 deletions
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 6203c7d8550f..45019649bbbd 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -358,6 +358,8 @@ struct sxgbe_core_ops {
/* Enable disable checksum offload operations */
void (*enable_rx_csum)(void __iomem *ioaddr);
void (*disable_rx_csum)(void __iomem *ioaddr);
+ void (*enable_rxqueue)(void __iomem *ioaddr, int queue_num);
+ void (*disable_rxqueue)(void __iomem *ioaddr, int queue_num);
};
const struct sxgbe_core_ops *sxgbe_get_core_ops(void);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
index c4da7a2b002a..58c35692560e 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
@@ -165,6 +165,26 @@ static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed)
writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG);
}
+static void sxgbe_core_enable_rxqueue(void __iomem *ioaddr, int queue_num)
+{
+ u32 reg_val;
+
+ reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);
+ reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);
+ reg_val |= SXGBE_CORE_RXQ_ENABLE;
+ writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);
+}
+
+static void sxgbe_core_disable_rxqueue(void __iomem *ioaddr, int queue_num)
+{
+ u32 reg_val;
+
+ reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);
+ reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);
+ reg_val |= SXGBE_CORE_RXQ_DISABLE;
+ writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);
+}
+
static void sxgbe_set_eee_mode(void __iomem *ioaddr)
{
u32 ctrl;
@@ -254,6 +274,8 @@ static const struct sxgbe_core_ops core_ops = {
.set_eee_pls = sxgbe_set_eee_pls,
.enable_rx_csum = sxgbe_enable_rx_csum,
.disable_rx_csum = sxgbe_disable_rx_csum,
+ .enable_rxqueue = sxgbe_core_enable_rxqueue,
+ .disable_rxqueue = sxgbe_core_disable_rxqueue,
};
const struct sxgbe_core_ops *sxgbe_get_core_ops(void)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
index e896dbbd2e15..2686bb5b6765 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
@@ -45,10 +45,10 @@ static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd,
p->tdes23.tx_rd_des23.first_desc = is_fd;
p->tdes23.tx_rd_des23.buf1_size = buf1_len;
- p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.total_pkt_len = pkt_len;
+ p->tdes23.tx_rd_des23.tx_pkt_len.pkt_len.total_pkt_len = pkt_len;
if (cksum)
- p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.cksum_ctl = cic_full;
+ p->tdes23.tx_rd_des23.cksum_ctl = cic_full;
}
/* Set VLAN control information */
@@ -233,6 +233,12 @@ static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p)
p->rdes23.rx_rd_des23.own_bit = 1;
}
+/* Set Interrupt on completion bit */
+static void sxgbe_set_rx_int_on_com(struct sxgbe_rx_norm_desc *p)
+{
+ p->rdes23.rx_rd_des23.int_on_com = 1;
+}
+
/* Get the receive frame size */
static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p)
{
@@ -498,6 +504,7 @@ static const struct sxgbe_desc_ops desc_ops = {
.init_rx_desc = sxgbe_init_rx_desc,
.get_rx_owner = sxgbe_get_rx_owner,
.set_rx_owner = sxgbe_set_rx_owner,
+ .set_rx_int_on_com = sxgbe_set_rx_int_on_com,
.get_rx_frame_len = sxgbe_get_rx_frame_len,
.get_rx_fd_status = sxgbe_get_rx_fd_status,
.get_rx_ld_status = sxgbe_get_rx_ld_status,
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
index 838cb9fb0ea9..18609324db72 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
@@ -39,22 +39,22 @@ struct sxgbe_tx_norm_desc {
u32 int_on_com:1;
/* TDES3 */
union {
- u32 tcp_payload_len:18;
+ u16 tcp_payload_len;
struct {
u32 total_pkt_len:15;
u32 reserved1:1;
- u32 cksum_ctl:2;
- } cksum_pktlen;
+ } pkt_len;
} tx_pkt_len;
- u32 tse_bit:1;
- u32 tcp_hdr_len:4;
- u32 sa_insert_ctl:3;
- u32 crc_pad_ctl:2;
- u32 last_desc:1;
- u32 first_desc:1;
- u32 ctxt_bit:1;
- u32 own_bit:1;
+ u16 cksum_ctl:2;
+ u16 tse_bit:1;
+ u16 tcp_hdr_len:4;
+ u16 sa_insert_ctl:3;
+ u16 crc_pad_ctl:2;
+ u16 last_desc:1;
+ u16 first_desc:1;
+ u16 ctxt_bit:1;
+ u16 own_bit:1;
} tx_rd_des23;
/* tx write back Desc 2,3 */
@@ -70,25 +70,20 @@ struct sxgbe_tx_norm_desc {
struct sxgbe_rx_norm_desc {
union {
- u32 rdes0; /* buf1 address */
- struct {
+ u64 rdes01; /* buf1 address */
+ union {
u32 out_vlan_tag:16;
u32 in_vlan_tag:16;
- } wb_rx_des0;
- } rd_wb_des0;
-
- union {
- u32 rdes1; /* buf2 address or buf1[63:32] */
- u32 rss_hash; /* Write-back RX */
- } rd_wb_des1;
+ u32 rss_hash;
+ } rx_wb_des01;
+ } rdes01;
union {
/* RX Read format Desc 2,3 */
struct{
/* RDES2 */
- u32 buf2_addr;
+ u64 buf2_addr:62;
/* RDES3 */
- u32 buf2_hi_addr:30;
u32 int_on_com:1;
u32 own_bit:1;
} rx_rd_des23;
@@ -263,6 +258,9 @@ struct sxgbe_desc_ops {
/* Set own bit */
void (*set_rx_owner)(struct sxgbe_rx_norm_desc *p);
+ /* Set Interrupt on completion bit */
+ void (*set_rx_int_on_com)(struct sxgbe_rx_norm_desc *p);
+
/* Get the receive frame size */
int (*get_rx_frame_len)(struct sxgbe_rx_norm_desc *p);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
index 4d989ff6c978..bb9b5b8afc5f 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
@@ -23,21 +23,8 @@
/* DMA core initialization */
static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map)
{
- int retry_count = 10;
u32 reg_val;
- /* reset the DMA */
- writel(SXGBE_DMA_SOFT_RESET, ioaddr + SXGBE_DMA_MODE_REG);
- while (retry_count--) {
- if (!(readl(ioaddr + SXGBE_DMA_MODE_REG) &
- SXGBE_DMA_SOFT_RESET))
- break;
- mdelay(10);
- }
-
- if (retry_count < 0)
- return -EBUSY;
-
reg_val = readl(ioaddr + SXGBE_DMA_SYSBUS_MODE_REG);
/* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register.
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 27e8c824b204..82a9a983869f 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -1076,6 +1076,9 @@ static int sxgbe_open(struct net_device *dev)
/* Initialize the MAC Core */
priv->hw->mac->core_init(priv->ioaddr);
+ SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) {
+ priv->hw->mac->enable_rxqueue(priv->ioaddr, queue_num);
+ }
/* Request the IRQ lines */
ret = devm_request_irq(priv->device, priv->irq, sxgbe_common_interrupt,
@@ -1453,6 +1456,7 @@ static void sxgbe_rx_refill(struct sxgbe_priv_data *priv)
/* Added memory barrier for RX descriptor modification */
wmb();
priv->hw->desc->set_rx_owner(p);
+ priv->hw->desc->set_rx_int_on_com(p);
/* Added memory barrier for RX descriptor modification */
wmb();
}
@@ -2070,6 +2074,24 @@ static int sxgbe_hw_init(struct sxgbe_priv_data * const priv)
return 0;
}
+static int sxgbe_sw_reset(void __iomem *addr)
+{
+ int retry_count = 10;
+
+ writel(SXGBE_DMA_SOFT_RESET, addr + SXGBE_DMA_MODE_REG);
+ while (retry_count--) {
+ if (!(readl(addr + SXGBE_DMA_MODE_REG) &
+ SXGBE_DMA_SOFT_RESET))
+ break;
+ mdelay(10);
+ }
+
+ if (retry_count < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
/**
* sxgbe_drv_probe
* @device: device pointer
@@ -2102,6 +2124,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
priv->plat = plat_dat;
priv->ioaddr = addr;
+ ret = sxgbe_sw_reset(priv->ioaddr);
+ if (ret)
+ goto error_free_netdev;
+
/* Verify driver arguments */
sxgbe_verify_args();
@@ -2218,9 +2244,14 @@ error_free_netdev:
int sxgbe_drv_remove(struct net_device *ndev)
{
struct sxgbe_priv_data *priv = netdev_priv(ndev);
+ u8 queue_num;
netdev_info(ndev, "%s: removing driver\n", __func__);
+ SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) {
+ priv->hw->mac->disable_rxqueue(priv->ioaddr, queue_num);
+ }
+
priv->hw->dma->stop_rx(priv->ioaddr, SXGBE_RX_QUEUES);
priv->hw->dma->stop_tx(priv->ioaddr, SXGBE_TX_QUEUES);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
index 01af2cbb479d..43ccb4a6de15 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
@@ -27,7 +27,7 @@
#define SXGBE_SMA_PREAD_CMD 0x02 /* post read increament address */
#define SXGBE_SMA_READ_CMD 0x03 /* read command */
#define SXGBE_SMA_SKIP_ADDRFRM 0x00040000 /* skip the address frame */
-#define SXGBE_MII_BUSY 0x00800000 /* mii busy */
+#define SXGBE_MII_BUSY 0x00400000 /* mii busy */
static int sxgbe_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_data)
{
@@ -147,6 +147,7 @@ int sxgbe_mdio_register(struct net_device *ndev)
struct sxgbe_mdio_bus_data *mdio_data = priv->plat->mdio_bus_data;
int err, phy_addr;
int *irqlist;
+ bool phy_found = false;
bool act;
/* allocate the new mdio bus */
@@ -162,7 +163,7 @@ int sxgbe_mdio_register(struct net_device *ndev)
irqlist = priv->mii_irq;
/* assign mii bus fields */
- mdio_bus->name = "samsxgbe";
+ mdio_bus->name = "sxgbe";
mdio_bus->read = &sxgbe_mdio_read;
mdio_bus->write = &sxgbe_mdio_write;
snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x",
@@ -216,13 +217,22 @@ int sxgbe_mdio_register(struct net_device *ndev)
netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n",
phy->phy_id, phy_addr, irq_str,
dev_name(&phy->dev), act ? " active" : "");
+ phy_found = true;
}
}
+ if (!phy_found) {
+ netdev_err(ndev, "PHY not found\n");
+ goto phyfound_err;
+ }
+
priv->mii = mdio_bus;
return 0;
+phyfound_err:
+ err = -ENODEV;
+ mdiobus_unregister(mdio_bus);
mdiobus_err:
mdiobus_free(mdio_bus);
return err;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
index 5a89acb4c505..56f8bf5a3f1b 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
@@ -52,6 +52,10 @@
#define SXGBE_CORE_RX_CTL2_REG 0x00A8
#define SXGBE_CORE_RX_CTL3_REG 0x00AC
+#define SXGBE_CORE_RXQ_ENABLE_MASK 0x0003
+#define SXGBE_CORE_RXQ_ENABLE 0x0002
+#define SXGBE_CORE_RXQ_DISABLE 0x0000
+
/* Interrupt Registers */
#define SXGBE_CORE_INT_STATUS_REG 0x00B0
#define SXGBE_CORE_INT_ENABLE_REG 0x00B4