diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 42 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 48 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 109 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 |
15 files changed, 258 insertions, 53 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 0319d640f728..9e42b5d32cff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -97,6 +97,16 @@ struct stmmac_extra_stats { unsigned long normal_irq_n; }; +/* CSR Frequency Access Defines*/ +#define CSR_F_35M 35000000 +#define CSR_F_60M 60000000 +#define CSR_F_100M 100000000 +#define CSR_F_150M 150000000 +#define CSR_F_250M 250000000 +#define CSR_F_300M 300000000 + +#define MAC_CSR_H_FRQ_MASK 0x20 + #define HASH_TABLE_SIZE 64 #define PAUSE_TIME 0x200 @@ -228,7 +238,7 @@ struct stmmac_desc_ops { int (*get_rx_owner) (struct dma_desc *p); void (*set_rx_owner) (struct dma_desc *p); /* Get the receive frame size */ - int (*get_rx_frame_len) (struct dma_desc *p); + int (*get_rx_frame_len) (struct dma_desc *p, int rx_coe_type); /* Return the reception status looking at the RDES1 */ int (*rx_status) (void *data, struct stmmac_extra_stats *x, struct dma_desc *p); @@ -236,7 +246,8 @@ struct stmmac_desc_ops { struct stmmac_dma_ops { /* DMA core initialization */ - int (*init) (void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx); + int (*init) (void __iomem *ioaddr, int pbl, int fb, int burst_len, + u32 dma_tx, u32 dma_rx); /* Dump DMA registers */ void (*dump_regs) (void __iomem *ioaddr); /* Set tx/rx threshold in the csr6 register @@ -261,8 +272,8 @@ struct stmmac_dma_ops { struct stmmac_ops { /* MAC core initialization */ void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned; - /* Support checksum offload engine */ - int (*rx_coe) (void __iomem *ioaddr); + /* Enable and verify that the IPC module is supported */ + int (*rx_ipc) (void __iomem *ioaddr); /* Dump MAC registers */ void (*dump_regs) (void __iomem *ioaddr); /* Handle extra events on specific interrupts hw dependent */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index cfcef0ea0fa5..54339a78e358 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -142,7 +142,7 @@ enum rx_tx_priority_ratio { #define DMA_BUS_MODE_RPBL_MASK 0x003e0000 /* Rx-Programmable Burst Len */ #define DMA_BUS_MODE_RPBL_SHIFT 17 #define DMA_BUS_MODE_USP 0x00800000 -#define DMA_BUS_MODE_4PBL 0x01000000 +#define DMA_BUS_MODE_PBL 0x01000000 #define DMA_BUS_MODE_AAL 0x02000000 /* DMA CRS Control and Status Register Mapping */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index b1c48b975945..e7cbcd99c2cb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -46,7 +46,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr) #endif } -static int dwmac1000_rx_coe_supported(void __iomem *ioaddr) +static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr) { u32 value = readl(ioaddr + GMAC_CONTROL); @@ -211,7 +211,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr) static const struct stmmac_ops dwmac1000_ops = { .core_init = dwmac1000_core_init, - .rx_coe = dwmac1000_rx_coe_supported, + .rx_ipc = dwmac1000_rx_ipc_enable, .dump_regs = dwmac1000_dump_regs, .host_irq_status = dwmac1000_irq_status, .set_filter = dwmac1000_set_filter, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 4d5402a1d262..3675c5731565 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -30,8 +30,8 @@ #include "dwmac1000.h" #include "dwmac_dma.h" -static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, - u32 dma_rx) +static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, + int burst_len, u32 dma_tx, u32 dma_rx) { u32 value = readl(ioaddr + DMA_BUS_MODE); int limit; @@ -48,15 +48,47 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, if (limit < 0) return -EBUSY; - value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL | - ((pbl << DMA_BUS_MODE_PBL_SHIFT) | - (pbl << DMA_BUS_MODE_RPBL_SHIFT)); + /* + * Set the DMA PBL (Programmable Burst Length) mode + * Before stmmac core 3.50 this mode bit was 4xPBL, and + * post 3.5 mode bit acts as 8*PBL. + * For core rev < 3.5, when the core is set for 4xPBL mode, the + * DMA transfers the data in 4, 8, 16, 32, 64 & 128 beats + * depending on pbl value. + * For core rev > 3.5, when the core is set for 8xPBL mode, the + * DMA transfers the data in 8, 16, 32, 64, 128 & 256 beats + * depending on pbl value. + */ + value = DMA_BUS_MODE_PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) | + (pbl << DMA_BUS_MODE_RPBL_SHIFT)); + + /* Set the Fixed burst mode */ + if (fb) + value |= DMA_BUS_MODE_FB; #ifdef CONFIG_STMMAC_DA value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */ #endif writel(value, ioaddr + DMA_BUS_MODE); + /* In case of GMAC AXI configuration, program the DMA_AXI_BUS_MODE + * for supported bursts. + * + * Note: This is applicable only for revision GMACv3.61a. For + * older version this register is reserved and shall have no + * effect. + * + * Note: + * For Fixed Burst Mode: if we directly write 0xFF to this + * register using the configurations pass from platform code, + * this would ensure that all bursts supported by core are set + * and those which are not supported would remain ineffective. + * + * For Non Fixed Burst Mode: provide the maximum value of the + * burst length. Any burst equal or below the provided burst + * length would be allowed to perform. */ + writel(burst_len, ioaddr + DMA_AXI_BUS_MODE); + /* Mask interrupts by writing to CSR7 */ writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index 138fb8dd1e87..efde50ff03f8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -43,11 +43,6 @@ static void dwmac100_core_init(void __iomem *ioaddr) #endif } -static int dwmac100_rx_coe_supported(void __iomem *ioaddr) -{ - return 0; -} - static void dwmac100_dump_mac_regs(void __iomem *ioaddr) { pr_info("\t----------------------------------------------\n" @@ -72,6 +67,11 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr) readl(ioaddr + MAC_VLAN2)); } +static int dwmac100_rx_ipc_enable(void __iomem *ioaddr) +{ + return 0; +} + static void dwmac100_irq_status(void __iomem *ioaddr) { return; @@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode) static const struct stmmac_ops dwmac100_ops = { .core_init = dwmac100_core_init, - .rx_coe = dwmac100_rx_coe_supported, + .rx_ipc = dwmac100_rx_ipc_enable, .dump_regs = dwmac100_dump_mac_regs, .host_irq_status = dwmac100_irq_status, .set_filter = dwmac100_set_filter, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index bc17fd08b55d..92ed2e07609e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -32,8 +32,8 @@ #include "dwmac100.h" #include "dwmac_dma.h" -static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, - u32 dma_rx) +static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, + int burst_len, u32 dma_tx, u32 dma_rx) { u32 value = readl(ioaddr + DMA_BUS_MODE); int limit; @@ -52,7 +52,7 @@ static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, /* Enable Application Access by writing to DMA CSR0 */ writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT), - ioaddr + DMA_BUS_MODE); + ioaddr + DMA_BUS_MODE); /* Mask interrupts by writing to CSR7 */ writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index 437edacd602e..6e0360f9cfde 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -32,6 +32,7 @@ #define DMA_CONTROL 0x00001018 /* Ctrl (Operational Mode) */ #define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */ #define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */ +#define DMA_AXI_BUS_MODE 0x00001028 /* AXI Bus Mode */ #define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */ #define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */ #define DMA_HW_FEATURE 0x00001058 /* HW Feature Register */ diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index ad1b627f8ec2..2fc8ef95f97a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -22,6 +22,7 @@ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> *******************************************************************************/ +#include <linux/stmmac.h> #include "common.h" #include "descs_com.h" @@ -309,9 +310,17 @@ static void enh_desc_close_tx_desc(struct dma_desc *p) p->des01.etx.interrupt = 1; } -static int enh_desc_get_rx_frame_len(struct dma_desc *p) +static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type) { - return p->des01.erx.frame_length; + /* The type-1 checksum offload engines append the checksum at + * the end of frame and the two bytes of checksum are added in + * the length. + * Adjust for that in the framelen for type-1 checksum offload + * engines. */ + if (rx_coe_type == STMMAC_RX_COE_TYPE1) + return p->des01.erx.frame_length - 2; + else + return p->des01.erx.frame_length; } const struct stmmac_desc_ops enh_desc_ops = { diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index 25953bb45a73..68962c549a2d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -22,6 +22,7 @@ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> *******************************************************************************/ +#include <linux/stmmac.h> #include "common.h" #include "descs_com.h" @@ -201,9 +202,17 @@ static void ndesc_close_tx_desc(struct dma_desc *p) p->des01.tx.interrupt = 1; } -static int ndesc_get_rx_frame_len(struct dma_desc *p) +static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type) { - return p->des01.rx.frame_length; + /* The type-1 checksum offload engines append the checksum at + * the end of frame and the two bytes of checksum are added in + * the length. + * Adjust for that in the framelen for type-1 checksum offload + * engines. */ + if (rx_coe_type == STMMAC_RX_COE_TYPE1) + return p->des01.rx.frame_length - 2; + else + return p->des01.rx.frame_length; } const struct stmmac_desc_ops ndesc_ops = { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index b4b095fdcf29..9f2435c53f57 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -21,7 +21,9 @@ *******************************************************************************/ #define STMMAC_RESOURCE_NAME "stmmaceth" -#define DRV_MODULE_VERSION "Feb_2012" +#define DRV_MODULE_VERSION "March_2012" + +#include <linux/clk.h> #include <linux/stmmac.h> #include <linux/phy.h> #include "common.h" @@ -56,8 +58,6 @@ struct stmmac_priv { struct stmmac_extra_stats xstats; struct napi_struct napi; - - int rx_coe; int no_csum_insertion; struct phy_device *phydev; @@ -81,6 +81,10 @@ struct stmmac_priv { struct stmmac_counters mmc; struct dma_features dma_cap; int hw_cap_support; +#ifdef CONFIG_HAVE_CLK + struct clk *stmmac_clk; +#endif + int clk_csr; }; extern int phyaddr; @@ -99,3 +103,41 @@ int stmmac_dvr_remove(struct net_device *ndev); struct stmmac_priv *stmmac_dvr_probe(struct device *device, struct plat_stmmacenet_data *plat_dat, void __iomem *addr); + +#ifdef CONFIG_HAVE_CLK +static inline int stmmac_clk_enable(struct stmmac_priv *priv) +{ + if (priv->stmmac_clk) + return clk_enable(priv->stmmac_clk); + + return 0; +} + +static inline void stmmac_clk_disable(struct stmmac_priv *priv) +{ + if (priv->stmmac_clk) + clk_disable(priv->stmmac_clk); +} +static inline int stmmac_clk_get(struct stmmac_priv *priv) +{ + priv->stmmac_clk = clk_get(priv->device, NULL); + + if (IS_ERR(priv->stmmac_clk)) { + pr_err("%s: ERROR clk_get failed\n", __func__); + return PTR_ERR(priv->stmmac_clk); + } + return 0; +} +#else +static inline int stmmac_clk_enable(struct stmmac_priv *priv) +{ + return 0; +} +static inline void stmmac_clk_disable(struct stmmac_priv *priv) +{ +} +static inline int stmmac_clk_get(struct stmmac_priv *priv) +{ + return 0; +} +#endif /* CONFIG_HAVE_CLK */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index f98e1511660f..ce431846fc6f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -481,6 +481,7 @@ static const struct ethtool_ops stmmac_ethtool_ops = { .get_wol = stmmac_get_wol, .set_wol = stmmac_set_wol, .get_sset_count = stmmac_get_sset_count, + .get_ts_info = ethtool_op_get_ts_info, }; void stmmac_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 48d56da62f08..a64f0d422e76 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -163,6 +163,35 @@ static void stmmac_verify_args(void) pause = PAUSE_TIME; } +static void stmmac_clk_csr_set(struct stmmac_priv *priv) +{ +#ifdef CONFIG_HAVE_CLK + u32 clk_rate; + + clk_rate = clk_get_rate(priv->stmmac_clk); + + /* Platform provided default clk_csr would be assumed valid + * for all other cases except for the below mentioned ones. */ + if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { + if (clk_rate < CSR_F_35M) + priv->clk_csr = STMMAC_CSR_20_35M; + else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) + priv->clk_csr = STMMAC_CSR_35_60M; + else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) + priv->clk_csr = STMMAC_CSR_60_100M; + else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) + priv->clk_csr = STMMAC_CSR_100_150M; + else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) + priv->clk_csr = STMMAC_CSR_150_250M; + else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M)) + priv->clk_csr = STMMAC_CSR_250_300M; + } /* For values higher than the IEEE 802.3 specified frequency + * we can not estimate the proper divider as it is not known + * the frequency of clk_csr_i. So we do not change the default + * divider. */ +#endif +} + #if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG) static void print_pkt(unsigned char *buf, int len) { @@ -307,7 +336,13 @@ static int stmmac_init_phy(struct net_device *dev) priv->speed = 0; priv->oldduplex = -1; - snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", priv->plat->bus_id); + if (priv->plat->phy_bus_name) + snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x", + priv->plat->phy_bus_name, priv->plat->bus_id); + else + snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", + priv->plat->bus_id); + snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, priv->plat->phy_addr); pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id); @@ -898,6 +933,8 @@ static int stmmac_open(struct net_device *dev) struct stmmac_priv *priv = netdev_priv(dev); int ret; + stmmac_clk_enable(priv); + stmmac_check_ether_addr(priv); /* MDIO bus Registration */ @@ -905,13 +942,15 @@ static int stmmac_open(struct net_device *dev) if (ret < 0) { pr_debug("%s: MDIO bus (id: %d) registration failed", __func__, priv->plat->bus_id); - return ret; + goto open_clk_dis; } #ifdef CONFIG_STMMAC_TIMER priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL); - if (unlikely(priv->tm == NULL)) - return -ENOMEM; + if (unlikely(priv->tm == NULL)) { + ret = -ENOMEM; + goto open_clk_dis; + } priv->tm->freq = tmrate; @@ -938,7 +977,9 @@ static int stmmac_open(struct net_device *dev) init_dma_desc_rings(dev); /* DMA initialization and SW reset */ - ret = priv->hw->dma->init(priv->ioaddr, priv->plat->pbl, + ret = priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg->pbl, + priv->plat->dma_cfg->fixed_burst, + priv->plat->dma_cfg->burst_len, priv->dma_tx_phy, priv->dma_rx_phy); if (ret < 0) { pr_err("%s: DMA initialization failed\n", __func__); @@ -1026,6 +1067,8 @@ open_error: if (priv->phydev) phy_disconnect(priv->phydev); +open_clk_dis: + stmmac_clk_disable(priv); return ret; } @@ -1078,6 +1121,7 @@ static int stmmac_release(struct net_device *dev) stmmac_exit_fs(); #endif stmmac_mdio_unregister(dev); + stmmac_clk_disable(priv); return 0; } @@ -1276,7 +1320,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) struct sk_buff *skb; int frame_len; - frame_len = priv->hw->desc->get_rx_frame_len(p); + frame_len = priv->hw->desc->get_rx_frame_len(p, + priv->plat->rx_coe); /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 * Type frames (LLC/LLC-SNAP) */ if (unlikely(status != llc_snap)) @@ -1312,7 +1357,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) #endif skb->protocol = eth_type_trans(skb, priv->dev); - if (unlikely(!priv->rx_coe)) { + if (unlikely(!priv->plat->rx_coe)) { /* No RX COE for old mac10/100 devices */ skb_checksum_none_assert(skb); netif_receive_skb(skb); @@ -1459,8 +1504,10 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev, { struct stmmac_priv *priv = netdev_priv(dev); - if (!priv->rx_coe) + if (priv->plat->rx_coe == STMMAC_RX_COE_NONE) features &= ~NETIF_F_RXCSUM; + else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1) + features &= ~NETIF_F_IPV6_CSUM; if (!priv->plat->tx_coe) features &= ~NETIF_F_ALL_CSUM; @@ -1765,17 +1812,32 @@ static int stmmac_hw_init(struct stmmac_priv *priv) * register (if supported). */ priv->plat->enh_desc = priv->dma_cap.enh_desc; - priv->plat->tx_coe = priv->dma_cap.tx_coe; priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; + + priv->plat->tx_coe = priv->dma_cap.tx_coe; + + if (priv->dma_cap.rx_coe_type2) + priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; + else if (priv->dma_cap.rx_coe_type1) + priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; + } else pr_info(" No HW DMA feature register supported"); /* Select the enhnaced/normal descriptor structures */ stmmac_selec_desc_mode(priv); - priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); - if (priv->rx_coe) - pr_info(" RX Checksum Offload Engine supported\n"); + /* Enable the IPC (Checksum Offload) and check if the feature has been + * enabled during the core configuration. */ + ret = priv->hw->mac->rx_ipc(priv->ioaddr); + if (!ret) { + pr_warning(" RX IPC Checksum Offload not configured.\n"); + priv->plat->rx_coe = STMMAC_RX_COE_NONE; + } + + if (priv->plat->rx_coe) + pr_info(" RX Checksum Offload Engine supported (type %d)\n", + priv->plat->rx_coe); if (priv->plat->tx_coe) pr_info(" TX Checksum insertion supported\n"); @@ -1856,6 +1918,20 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, goto error; } + if (stmmac_clk_get(priv)) + goto error; + + /* If a specific clk_csr value is passed from the platform + * this means that the CSR Clock Range selection cannot be + * changed at run-time and it is fixed. Viceversa the driver'll try to + * set the MDC clock dynamically according to the csr actual + * clock input. + */ + if (!priv->plat->clk_csr) + stmmac_clk_csr_set(priv); + else + priv->clk_csr = priv->plat->clk_csr; + return priv; error: @@ -1925,9 +2001,11 @@ int stmmac_suspend(struct net_device *ndev) /* Enable Power down mode by programming the PMT regs */ if (device_may_wakeup(priv->device)) priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); - else + else { stmmac_set_mac(priv->ioaddr, false); - + /* Disable clock in case of PWM is off */ + stmmac_clk_disable(priv); + } spin_unlock(&priv->lock); return 0; } @@ -1948,6 +2026,9 @@ int stmmac_resume(struct net_device *ndev) * from another devices (e.g. serial console). */ if (device_may_wakeup(priv->device)) priv->hw->mac->pmt(priv->ioaddr, 0); + else + /* enable the clk prevously disabled */ + stmmac_clk_enable(priv); netif_device_attach(ndev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 73195329aa46..ade108232048 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -34,6 +34,22 @@ #define MII_BUSY 0x00000001 #define MII_WRITE 0x00000002 +static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr) +{ + unsigned long curr; + unsigned long finish = jiffies + 3 * HZ; + + do { + curr = jiffies; + if (readl(ioaddr + mii_addr) & MII_BUSY) + cpu_relax(); + else + return 0; + } while (!time_after_eq(curr, finish)); + + return -EBUSY; +} + /** * stmmac_mdio_read * @bus: points to the mii_bus structure @@ -54,11 +70,15 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) int data; u16 regValue = (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))); - regValue |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2); + regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2); + + if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) + return -EBUSY; - do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); writel(regValue, priv->ioaddr + mii_address); - do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); + + if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) + return -EBUSY; /* Read the data from the MII data register */ data = (int)readl(priv->ioaddr + mii_data); @@ -86,20 +106,18 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))) | MII_WRITE; - value |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2); - + value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2); /* Wait until any existing MII operation is complete */ - do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); + if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) + return -EBUSY; /* Set the MII address register to write */ writel(phydata, priv->ioaddr + mii_data); writel(value, priv->ioaddr + mii_address); /* Wait until any existing MII operation is complete */ - do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); - - return 0; + return stmmac_mdio_busy_wait(priv->ioaddr, mii_address); } /** diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index da66ed7c3c5d..65e0f98520d6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -35,7 +35,8 @@ static void stmmac_default_data(void) plat_dat.bus_id = 1; plat_dat.phy_addr = 0; plat_dat.interface = PHY_INTERFACE_MODE_GMII; - plat_dat.pbl = 32; + plat_dat.dma_cfg->pbl = 32; + plat_dat.dma_cfg->burst_len = DMA_AXI_BLEN_256; plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ plat_dat.has_gmac = 1; plat_dat.force_sf_dma_mode = 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 116529a366b2..12bd221561e5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -50,7 +50,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, * once needed on other platforms. */ if (of_device_is_compatible(np, "st,spear600-gmac")) { - plat->pbl = 8; + plat->dma_cfg->pbl = 8; plat->has_gmac = 1; plat->pmt = 1; } |