Commit 429a372e authored by David S. Miller's avatar David S. Miller

Merge branch 'stmmac-tegra186'

Thierry Reding says:

====================
net: stmmac: Fixes and Tegra186 support

This series of patches start with a few cleanups that I ran across while
adding Tegra186 support to the stmmac driver. It then adds code for FIFO
size parsing from feature registers and finally enables support for the
incarnation of the Synopsys DWC QOS IP found on NVIDIA Tegra186 SoCs.

This is based on next-20170310.

Changes in v2:
- address review comments by Mikko and Joao
- add two additional cleanup patches
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8f48ba71 e6ea2d16
...@@ -28,9 +28,9 @@ Optional properties: ...@@ -28,9 +28,9 @@ Optional properties:
clocks may be specified in derived bindings. clocks may be specified in derived bindings.
- clock-names: One name for each entry in the clocks property, the - clock-names: One name for each entry in the clocks property, the
first one should be "stmmaceth" and the second one should be "pclk". first one should be "stmmaceth" and the second one should be "pclk".
- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is - ptp_ref: this is the PTP reference clock; in case of the PTP is available
available this clock is used for programming the Timestamp Addend Register. this clock is used for programming the Timestamp Addend Register. If not
If not passed then the system clock will be used and this is fine on some passed then the system clock will be used and this is fine on some
platforms. platforms.
- tx-fifo-depth: See ethernet.txt file in the same directory - tx-fifo-depth: See ethernet.txt file in the same directory
- rx-fifo-depth: See ethernet.txt file in the same directory - rx-fifo-depth: See ethernet.txt file in the same directory
......
...@@ -324,6 +324,9 @@ struct dma_features { ...@@ -324,6 +324,9 @@ struct dma_features {
unsigned int number_tx_queues; unsigned int number_tx_queues;
/* Alternate (enhanced) DESC mode */ /* Alternate (enhanced) DESC mode */
unsigned int enh_desc; unsigned int enh_desc;
/* TX and RX FIFO sizes */
unsigned int tx_fifo_size;
unsigned int rx_fifo_size;
}; };
/* GMAC TX FIFO is 8K, Rx FIFO is 16K */ /* GMAC TX FIFO is 8K, Rx FIFO is 16K */
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define GMAC_RXQ_CTRL0 0x000000a0 #define GMAC_RXQ_CTRL0 0x000000a0
#define GMAC_INT_STATUS 0x000000b0 #define GMAC_INT_STATUS 0x000000b0
#define GMAC_INT_EN 0x000000b4 #define GMAC_INT_EN 0x000000b4
#define GMAC_1US_TIC_COUNTER 0x000000dc
#define GMAC_PCS_BASE 0x000000e0 #define GMAC_PCS_BASE 0x000000e0
#define GMAC_PHYIF_CONTROL_STATUS 0x000000f8 #define GMAC_PHYIF_CONTROL_STATUS 0x000000f8
#define GMAC_PMT 0x000000c0 #define GMAC_PMT 0x000000c0
...@@ -148,6 +149,8 @@ enum power_event { ...@@ -148,6 +149,8 @@ enum power_event {
/* MAC HW features1 bitmap */ /* MAC HW features1 bitmap */
#define GMAC_HW_FEAT_AVSEL BIT(20) #define GMAC_HW_FEAT_AVSEL BIT(20)
#define GMAC_HW_TSOEN BIT(18) #define GMAC_HW_TSOEN BIT(18)
#define GMAC_HW_TXFIFOSIZE GENMASK(10, 6)
#define GMAC_HW_RXFIFOSIZE GENMASK(4, 0)
/* MAC HW features2 bitmap */ /* MAC HW features2 bitmap */
#define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18) #define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18)
...@@ -180,6 +183,7 @@ enum power_event { ...@@ -180,6 +183,7 @@ enum power_event {
#define MTL_OP_MODE_TSF BIT(1) #define MTL_OP_MODE_TSF BIT(1)
#define MTL_OP_MODE_TQS_MASK GENMASK(24, 16) #define MTL_OP_MODE_TQS_MASK GENMASK(24, 16)
#define MTL_OP_MODE_TQS_SHIFT 16
#define MTL_OP_MODE_TTC_MASK 0x70 #define MTL_OP_MODE_TTC_MASK 0x70
#define MTL_OP_MODE_TTC_SHIFT 4 #define MTL_OP_MODE_TTC_SHIFT 4
...@@ -193,6 +197,17 @@ enum power_event { ...@@ -193,6 +197,17 @@ enum power_event {
#define MTL_OP_MODE_TTC_384 (6 << MTL_OP_MODE_TTC_SHIFT) #define MTL_OP_MODE_TTC_384 (6 << MTL_OP_MODE_TTC_SHIFT)
#define MTL_OP_MODE_TTC_512 (7 << MTL_OP_MODE_TTC_SHIFT) #define MTL_OP_MODE_TTC_512 (7 << MTL_OP_MODE_TTC_SHIFT)
#define MTL_OP_MODE_RQS_MASK GENMASK(29, 20)
#define MTL_OP_MODE_RQS_SHIFT 20
#define MTL_OP_MODE_RFD_MASK GENMASK(19, 14)
#define MTL_OP_MODE_RFD_SHIFT 14
#define MTL_OP_MODE_RFA_MASK GENMASK(13, 8)
#define MTL_OP_MODE_RFA_SHIFT 8
#define MTL_OP_MODE_EHFC BIT(7)
#define MTL_OP_MODE_RTC_MASK 0x18 #define MTL_OP_MODE_RTC_MASK 0x18
#define MTL_OP_MODE_RTC_SHIFT 3 #define MTL_OP_MODE_RTC_SHIFT 3
......
...@@ -183,8 +183,9 @@ static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt) ...@@ -183,8 +183,9 @@ static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt)
} }
static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode,
int rxmode, u32 channel) int rxmode, u32 channel, int rxfifosz)
{ {
unsigned int rqs = rxfifosz / 256 - 1;
u32 mtl_tx_op, mtl_rx_op, mtl_rx_int; u32 mtl_tx_op, mtl_rx_op, mtl_rx_int;
/* Following code only done for channel 0, other channels not yet /* Following code only done for channel 0, other channels not yet
...@@ -250,6 +251,53 @@ static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, ...@@ -250,6 +251,53 @@ static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode,
mtl_rx_op |= MTL_OP_MODE_RTC_128; mtl_rx_op |= MTL_OP_MODE_RTC_128;
} }
mtl_rx_op &= ~MTL_OP_MODE_RQS_MASK;
mtl_rx_op |= rqs << MTL_OP_MODE_RQS_SHIFT;
/* enable flow control only if each channel gets 4 KiB or more FIFO */
if (rxfifosz >= 4096) {
unsigned int rfd, rfa;
mtl_rx_op |= MTL_OP_MODE_EHFC;
/* Set Threshold for Activating Flow Control to min 2 frames,
* i.e. 1500 * 2 = 3000 bytes.
*
* Set Threshold for Deactivating Flow Control to min 1 frame,
* i.e. 1500 bytes.
*/
switch (rxfifosz) {
case 4096:
/* This violates the above formula because of FIFO size
* limit therefore overflow may occur in spite of this.
*/
rfd = 0x03; /* Full-2.5K */
rfa = 0x01; /* Full-1.5K */
break;
case 8192:
rfd = 0x06; /* Full-4K */
rfa = 0x0a; /* Full-6K */
break;
case 16384:
rfd = 0x06; /* Full-4K */
rfa = 0x12; /* Full-10K */
break;
default:
rfd = 0x06; /* Full-4K */
rfa = 0x1e; /* Full-16K */
break;
}
mtl_rx_op &= ~MTL_OP_MODE_RFD_MASK;
mtl_rx_op |= rfd << MTL_OP_MODE_RFD_SHIFT;
mtl_rx_op &= ~MTL_OP_MODE_RFA_MASK;
mtl_rx_op |= rfa << MTL_OP_MODE_RFA_SHIFT;
}
writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel)); writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel));
/* Enable MTL RX overflow */ /* Enable MTL RX overflow */
...@@ -262,7 +310,7 @@ static void dwmac4_dma_operation_mode(void __iomem *ioaddr, int txmode, ...@@ -262,7 +310,7 @@ static void dwmac4_dma_operation_mode(void __iomem *ioaddr, int txmode,
int rxmode, int rxfifosz) int rxmode, int rxfifosz)
{ {
/* Only Channel 0 is actually configured and used */ /* Only Channel 0 is actually configured and used */
dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0); dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0, rxfifosz);
} }
static void dwmac4_get_hw_feature(void __iomem *ioaddr, static void dwmac4_get_hw_feature(void __iomem *ioaddr,
...@@ -294,6 +342,11 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr, ...@@ -294,6 +342,11 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
hw_cap = readl(ioaddr + GMAC_HW_FEATURE1); hw_cap = readl(ioaddr + GMAC_HW_FEATURE1);
dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20; dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18; dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
/* RX and TX FIFO sizes are encoded as log2(n / 128). Undo that by
* shifting and store the sizes in bytes.
*/
dma_cap->tx_fifo_size = 128 << ((hw_cap & GMAC_HW_TXFIFOSIZE) >> 6);
dma_cap->rx_fifo_size = 128 << ((hw_cap & GMAC_HW_RXFIFOSIZE) >> 0);
/* MAC HW feature2 */ /* MAC HW feature2 */
hw_cap = readl(ioaddr + GMAC_HW_FEATURE2); hw_cap = readl(ioaddr + GMAC_HW_FEATURE2);
/* TX and RX number of channels */ /* TX and RX number of channels */
......
...@@ -1281,6 +1281,9 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) ...@@ -1281,6 +1281,9 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
{ {
int rxfifosz = priv->plat->rx_fifo_size; int rxfifosz = priv->plat->rx_fifo_size;
if (rxfifosz == 0)
rxfifosz = priv->dma_cap.rx_fifo_size;
if (priv->plat->force_thresh_dma_mode) if (priv->plat->force_thresh_dma_mode)
priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz); priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz);
else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
...@@ -1711,6 +1714,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) ...@@ -1711,6 +1714,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
stmmac_mmc_setup(priv); stmmac_mmc_setup(priv);
if (init_ptp) { if (init_ptp) {
ret = clk_prepare_enable(priv->plat->clk_ptp_ref);
if (ret < 0)
netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret);
ret = stmmac_init_ptp(priv); ret = stmmac_init_ptp(priv);
if (ret == -EOPNOTSUPP) if (ret == -EOPNOTSUPP)
netdev_warn(priv->dev, "PTP not supported by HW\n"); netdev_warn(priv->dev, "PTP not supported by HW\n");
...@@ -1754,6 +1761,13 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) ...@@ -1754,6 +1761,13 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
return 0; return 0;
} }
static void stmmac_hw_teardown(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
clk_disable_unprepare(priv->plat->clk_ptp_ref);
}
/** /**
* stmmac_open - open entry point of the driver * stmmac_open - open entry point of the driver
* @dev : pointer to the device structure. * @dev : pointer to the device structure.
...@@ -1821,7 +1835,7 @@ static int stmmac_open(struct net_device *dev) ...@@ -1821,7 +1835,7 @@ static int stmmac_open(struct net_device *dev)
netdev_err(priv->dev, netdev_err(priv->dev,
"%s: ERROR: allocating the IRQ %d (error: %d)\n", "%s: ERROR: allocating the IRQ %d (error: %d)\n",
__func__, dev->irq, ret); __func__, dev->irq, ret);
goto init_error; goto irq_error;
} }
/* Request the Wake IRQ in case of another line is used for WoL */ /* Request the Wake IRQ in case of another line is used for WoL */
...@@ -1858,7 +1872,12 @@ static int stmmac_open(struct net_device *dev) ...@@ -1858,7 +1872,12 @@ static int stmmac_open(struct net_device *dev)
free_irq(priv->wol_irq, dev); free_irq(priv->wol_irq, dev);
wolirq_error: wolirq_error:
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
irq_error:
if (dev->phydev)
phy_stop(dev->phydev);
del_timer_sync(&priv->txtimer);
stmmac_hw_teardown(dev);
init_error: init_error:
free_dma_desc_resources(priv); free_dma_desc_resources(priv);
dma_desc_error: dma_desc_error:
...@@ -2063,6 +2082,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2063,6 +2082,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
des = skb_frag_dma_map(priv->device, frag, 0, des = skb_frag_dma_map(priv->device, frag, 0,
skb_frag_size(frag), skb_frag_size(frag),
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (dma_mapping_error(priv->device, des))
goto dma_map_err;
stmmac_tso_allocator(priv, des, skb_frag_size(frag), stmmac_tso_allocator(priv, des, skb_frag_size(frag),
(i == nfrags - 1)); (i == nfrags - 1));
......
...@@ -359,13 +359,12 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) ...@@ -359,13 +359,12 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
clk_prepare_enable(plat->pclk); clk_prepare_enable(plat->pclk);
/* Fall-back to main clock in case of no PTP ref is passed */ /* Fall-back to main clock in case of no PTP ref is passed */
plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "clk_ptp_ref"); plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "ptp_ref");
if (IS_ERR(plat->clk_ptp_ref)) { if (IS_ERR(plat->clk_ptp_ref)) {
plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk); plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk);
plat->clk_ptp_ref = NULL; plat->clk_ptp_ref = NULL;
dev_warn(&pdev->dev, "PTP uses main clock\n"); dev_warn(&pdev->dev, "PTP uses main clock\n");
} else { } else {
clk_prepare_enable(plat->clk_ptp_ref);
plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref); plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref);
dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate); dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment