Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1587038 > unrolled thread
| Started by | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| First post | 2017-02-23 18:30 +0100 |
| Last post | 2017-02-27 08:40 +0100 |
| Articles | 7 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH 0/7] net: stmmac: Fixes and Tegra186 support Thierry Reding <thierry.reding@gmail.com> - 2017-02-23 18:30 +0100
[PATCH 7/7] net: stmmac: dwc-qos: Add Tegra186 support Thierry Reding <thierry.reding@gmail.com> - 2017-02-23 18:30 +0100
Re: [PATCH 7/7] net: stmmac: dwc-qos: Add Tegra186 support Mikko Perttunen <cyndis@kapsi.fi> - 2017-02-27 16:10 +0100
[PATCH 4/7] net: stmmac: Parse FIFO sizes from feature registers Thierry Reding <thierry.reding@gmail.com> - 2017-02-23 18:30 +0100
Re: [PATCH 4/7] net: stmmac: Parse FIFO sizes from feature registers Mikko Perttunen <cyndis@kapsi.fi> - 2017-02-27 11:00 +0100
Re: [PATCH 0/7] net: stmmac: Fixes and Tegra186 support David Miller <davem@davemloft.net> - 2017-02-23 19:30 +0100
Re: [PATCH 0/7] net: stmmac: Fixes and Tegra186 support Thierry Reding <thierry.reding@gmail.com> - 2017-02-27 08:40 +0100
| From | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| Date | 2017-02-23 18:30 +0100 |
| Subject | [PATCH 0/7] net: stmmac: Fixes and Tegra186 support |
| Message-ID | <te5nj-4nQ-5@gated-at.bofh.it> |
From: Thierry Reding <treding@nvidia.com> Hi everyone, 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-20170223. Thanks, Thierry Thierry Reding (7): net: stmmac: Rename clk_ptp_ref clock to ptp_ref net: stmmac: Balance PTP reference clock enable/disable net: stmmac: Check for DMA mapping errors net: stmmac: Parse FIFO sizes from feature registers net: stmmac: Program RX queue size and flow control net: stmmac: dwc-qos: Split out ->probe() and ->remove() net: stmmac: dwc-qos: Add Tegra186 support Documentation/devicetree/bindings/net/stmmac.txt | 6 +- drivers/net/ethernet/stmicro/stmmac/common.h | 3 + .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 366 +++++++++++++++++++-- drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 12 + drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 45 ++- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 + .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +- 7 files changed, 411 insertions(+), 33 deletions(-) -- 2.11.1
[toc] | [next] | [standalone]
| From | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| Date | 2017-02-23 18:30 +0100 |
| Subject | [PATCH 7/7] net: stmmac: dwc-qos: Add Tegra186 support |
| Message-ID | <te5nk-4nQ-35@gated-at.bofh.it> |
| In reply to | #1587038 |
From: Thierry Reding <treding@nvidia.com>
The NVIDIA Tegra186 SoC contains an instance of the Synopsys DWC
ethernet QOS IP core. The binding that it uses is slightly different
from existing ones because of the integration (clocks, resets, ...).
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
.../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 252 +++++++++++++++++++++
1 file changed, 252 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index 5071d3c15adc..54dfbdc48f6d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -14,6 +14,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
+#include <linux/gpio/consumer.h>
#include <linux/ethtool.h>
#include <linux/io.h>
#include <linux/ioport.h>
@@ -22,10 +23,24 @@
#include <linux/of_net.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
+#include <linux/reset.h>
#include <linux/stmmac.h>
#include "stmmac_platform.h"
+struct tegra_eqos {
+ struct device *dev;
+ void __iomem *regs;
+
+ struct reset_control *rst;
+ struct clk *clk_master;
+ struct clk *clk_slave;
+ struct clk *clk_tx;
+ struct clk *clk_rx;
+
+ struct gpio_desc *reset;
+};
+
static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat_dat)
{
@@ -148,6 +163,237 @@ static int dwc_qos_remove(struct platform_device *pdev)
return 0;
}
+#define SDMEMCOMPPADCTRL 0x8800
+#define SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
+
+#define AUTO_CAL_CONFIG 0x8804
+#define AUTO_CAL_CONFIG_START BIT(31)
+#define AUTO_CAL_CONFIG_ENABLE BIT(29)
+
+#define AUTO_CAL_STATUS 0x880c
+#define AUTO_CAL_STATUS_ACTIVE BIT(31)
+
+static void tegra_eqos_fix_speed(void *priv, unsigned int speed)
+{
+ struct tegra_eqos *eqos = priv;
+ unsigned long rate = 125000000;
+ bool needs_calibration = false;
+ unsigned int i;
+ u32 value;
+
+ switch (speed) {
+ case SPEED_1000:
+ needs_calibration = true;
+ rate = 125000000;
+ break;
+
+ case SPEED_100:
+ needs_calibration = true;
+ rate = 25000000;
+ break;
+
+ case SPEED_10:
+ rate = 2500000;
+ break;
+
+ default:
+ dev_err(eqos->dev, "invalid speed %u\n", speed);
+ break;
+ }
+
+ if (needs_calibration) {
+ /* calibrate */
+ value = readl(eqos->regs + SDMEMCOMPPADCTRL);
+ value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
+ writel(value, eqos->regs + SDMEMCOMPPADCTRL);
+
+ udelay(1);
+
+ value = readl(eqos->regs + AUTO_CAL_CONFIG);
+ value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE;
+ writel(value, eqos->regs + AUTO_CAL_CONFIG);
+
+ for (i = 0; i <= 10; i++) {
+ value = readl(eqos->regs + AUTO_CAL_STATUS);
+ if (value & AUTO_CAL_STATUS_ACTIVE)
+ break;
+
+ udelay(1);
+ }
+
+ if ((value & AUTO_CAL_STATUS_ACTIVE) == 0) {
+ dev_err(eqos->dev, "calibration did not start\n");
+ goto failed;
+ }
+
+ for (i = 0; i <= 10; i++) {
+ value = readl(eqos->regs + AUTO_CAL_STATUS);
+ if ((value & AUTO_CAL_STATUS_ACTIVE) == 0)
+ break;
+
+ udelay(20);
+ }
+
+ if (value & AUTO_CAL_STATUS_ACTIVE) {
+ dev_err(eqos->dev, "calibration didn't finish\n");
+ goto failed;
+ }
+
+ failed:
+ value = readl(eqos->regs + SDMEMCOMPPADCTRL);
+ value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
+ writel(value, eqos->regs + SDMEMCOMPPADCTRL);
+ } else {
+ value = readl(eqos->regs + AUTO_CAL_CONFIG);
+ value &= ~AUTO_CAL_CONFIG_ENABLE;
+ writel(value, eqos->regs + AUTO_CAL_CONFIG);
+ }
+
+ clk_set_rate(eqos->clk_tx, rate);
+}
+
+static int tegra_eqos_init(struct platform_device *pdev, void *priv)
+{
+ struct tegra_eqos *eqos = priv;
+ unsigned long rate;
+ u32 value;
+
+ rate = clk_get_rate(eqos->clk_slave);
+
+ value = readl(eqos->regs + 0xdc);
+ value = (rate / 1000000) - 1;
+ writel(value, eqos->regs + 0xdc);
+
+ return 0;
+}
+
+static void *tegra_eqos_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *data,
+ struct stmmac_resources *res)
+{
+ struct tegra_eqos *eqos;
+ int err;
+
+ eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL);
+ if (!eqos) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ eqos->dev = &pdev->dev;
+ eqos->regs = res->addr;
+
+ eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus");
+ if (IS_ERR(eqos->clk_master)) {
+ err = PTR_ERR(eqos->clk_master);
+ goto error;
+ }
+
+ err = clk_prepare_enable(eqos->clk_master);
+ if (err < 0)
+ goto error;
+
+ eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus");
+ if (IS_ERR(eqos->clk_slave)) {
+ err = PTR_ERR(eqos->clk_slave);
+ goto disable_master;
+ }
+
+ data->stmmac_clk = eqos->clk_slave;
+
+ err = clk_prepare_enable(eqos->clk_slave);
+ if (err < 0)
+ goto disable_master;
+
+ eqos->clk_rx = devm_clk_get(&pdev->dev, "rx");
+ if (IS_ERR(eqos->clk_rx)) {
+ err = PTR_ERR(eqos->clk_rx);
+ goto disable_slave;
+ }
+
+ err = clk_prepare_enable(eqos->clk_rx);
+ if (err < 0)
+ goto disable_slave;
+
+ eqos->clk_tx = devm_clk_get(&pdev->dev, "tx");
+ if (IS_ERR(eqos->clk_tx)) {
+ err = PTR_ERR(eqos->clk_tx);
+ goto disable_rx;
+ }
+
+ err = clk_prepare_enable(eqos->clk_tx);
+ if (err < 0)
+ goto disable_rx;
+
+ eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(eqos->reset)) {
+ err = PTR_ERR(eqos->reset);
+ goto disable_tx;
+ }
+
+ usleep_range(2000, 4000);
+ gpiod_set_value(eqos->reset, 0);
+
+ eqos->rst = devm_reset_control_get(&pdev->dev, "eqos");
+ if (IS_ERR(eqos->rst)) {
+ err = PTR_ERR(eqos->rst);
+ goto reset_phy;
+ }
+
+ err = reset_control_assert(eqos->rst);
+ if (err < 0)
+ goto reset_phy;
+
+ usleep_range(2000, 4000);
+
+ err = reset_control_deassert(eqos->rst);
+ if (err < 0)
+ goto reset_phy;
+
+ usleep_range(2000, 4000);
+
+ data->fix_mac_speed = tegra_eqos_fix_speed;
+ data->init = tegra_eqos_init;
+ data->bsp_priv = eqos;
+
+ err = tegra_eqos_init(pdev, eqos);
+ if (err < 0)
+ goto reset;
+
+out:
+ return eqos;
+
+reset:
+ reset_control_assert(eqos->rst);
+reset_phy:
+ gpiod_set_value(eqos->reset, 1);
+disable_tx:
+ clk_disable_unprepare(eqos->clk_tx);
+disable_rx:
+ clk_disable_unprepare(eqos->clk_rx);
+disable_slave:
+ clk_disable_unprepare(eqos->clk_slave);
+disable_master:
+ clk_disable_unprepare(eqos->clk_master);
+error:
+ eqos = ERR_PTR(err);
+ goto out;
+}
+
+static int tegra_eqos_remove(struct platform_device *pdev)
+{
+ struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev);
+
+ reset_control_assert(eqos->rst);
+ gpiod_set_value(eqos->reset, 1);
+ clk_disable_unprepare(eqos->clk_tx);
+ clk_disable_unprepare(eqos->clk_rx);
+ clk_disable_unprepare(eqos->clk_slave);
+ clk_disable_unprepare(eqos->clk_master);
+
+ return 0;
+}
+
struct dwc_eth_dwmac_data {
void *(*probe)(struct platform_device *pdev,
struct plat_stmmacenet_data *data,
@@ -160,6 +406,11 @@ static const struct dwc_eth_dwmac_data dwc_qos_data = {
.remove = dwc_qos_remove,
};
+static const struct dwc_eth_dwmac_data tegra_eqos_data = {
+ .probe = tegra_eqos_probe,
+ .remove = tegra_eqos_remove,
+};
+
static int dwc_eth_dwmac_probe(struct platform_device *pdev)
{
const struct dwc_eth_dwmac_data *data;
@@ -245,6 +496,7 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev)
static const struct of_device_id dwc_eth_dwmac_match[] = {
{ .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
+ { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data},
{ }
};
MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
--
2.11.1
[toc] | [prev] | [next] | [standalone]
| From | Mikko Perttunen <cyndis@kapsi.fi> |
|---|---|
| Date | 2017-02-27 16:10 +0100 |
| Subject | Re: [PATCH 7/7] net: stmmac: dwc-qos: Add Tegra186 support |
| Message-ID | <tfv61-7iD-1@gated-at.bofh.it> |
| In reply to | #1587039 |
On 23.02.2017 19:24, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> The NVIDIA Tegra186 SoC contains an instance of the Synopsys DWC
> ethernet QOS IP core. The binding that it uses is slightly different
> from existing ones because of the integration (clocks, resets, ...).
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 252 +++++++++++++++++++++
> 1 file changed, 252 insertions(+)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
> index 5071d3c15adc..54dfbdc48f6d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
> @@ -14,6 +14,7 @@
> #include <linux/clk.h>
> #include <linux/clk-provider.h>
> #include <linux/device.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/ethtool.h>
> #include <linux/io.h>
> #include <linux/ioport.h>
> @@ -22,10 +23,24 @@
> #include <linux/of_net.h>
> #include <linux/mfd/syscon.h>
> #include <linux/platform_device.h>
> +#include <linux/reset.h>
> #include <linux/stmmac.h>
>
> #include "stmmac_platform.h"
>
> +struct tegra_eqos {
> + struct device *dev;
> + void __iomem *regs;
> +
> + struct reset_control *rst;
> + struct clk *clk_master;
> + struct clk *clk_slave;
> + struct clk *clk_tx;
> + struct clk *clk_rx;
> +
> + struct gpio_desc *reset;
> +};
> +
> static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
> struct plat_stmmacenet_data *plat_dat)
> {
> @@ -148,6 +163,237 @@ static int dwc_qos_remove(struct platform_device *pdev)
> return 0;
> }
>
> +#define SDMEMCOMPPADCTRL 0x8800
> +#define SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
> +
> +#define AUTO_CAL_CONFIG 0x8804
> +#define AUTO_CAL_CONFIG_START BIT(31)
> +#define AUTO_CAL_CONFIG_ENABLE BIT(29)
> +
> +#define AUTO_CAL_STATUS 0x880c
> +#define AUTO_CAL_STATUS_ACTIVE BIT(31)
> +
> +static void tegra_eqos_fix_speed(void *priv, unsigned int speed)
> +{
> + struct tegra_eqos *eqos = priv;
> + unsigned long rate = 125000000;
> + bool needs_calibration = false;
> + unsigned int i;
> + u32 value;
> +
> + switch (speed) {
> + case SPEED_1000:
> + needs_calibration = true;
> + rate = 125000000;
> + break;
> +
> + case SPEED_100:
> + needs_calibration = true;
> + rate = 25000000;
> + break;
> +
> + case SPEED_10:
> + rate = 2500000;
> + break;
> +
> + default:
> + dev_err(eqos->dev, "invalid speed %u\n", speed);
> + break;
> + }
> +
> + if (needs_calibration) {
> + /* calibrate */
> + value = readl(eqos->regs + SDMEMCOMPPADCTRL);
> + value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
> + writel(value, eqos->regs + SDMEMCOMPPADCTRL);
> +
> + udelay(1);
> +
> + value = readl(eqos->regs + AUTO_CAL_CONFIG);
> + value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE;
> + writel(value, eqos->regs + AUTO_CAL_CONFIG);
> +
> + for (i = 0; i <= 10; i++) {
> + value = readl(eqos->regs + AUTO_CAL_STATUS);
> + if (value & AUTO_CAL_STATUS_ACTIVE)
> + break;
> +
> + udelay(1);
> + }
> +
> + if ((value & AUTO_CAL_STATUS_ACTIVE) == 0) {
> + dev_err(eqos->dev, "calibration did not start\n");
> + goto failed;
> + }
> +
> + for (i = 0; i <= 10; i++) {
> + value = readl(eqos->regs + AUTO_CAL_STATUS);
> + if ((value & AUTO_CAL_STATUS_ACTIVE) == 0)
> + break;
> +
> + udelay(20);
> + }
> +
> + if (value & AUTO_CAL_STATUS_ACTIVE) {
> + dev_err(eqos->dev, "calibration didn't finish\n");
> + goto failed;
> + }
Could use readl_poll_timeout/readl_poll_timeout_atomic for these loops
instead.
> +
> + failed:
> + value = readl(eqos->regs + SDMEMCOMPPADCTRL);
> + value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
> + writel(value, eqos->regs + SDMEMCOMPPADCTRL);
> + } else {
> + value = readl(eqos->regs + AUTO_CAL_CONFIG);
> + value &= ~AUTO_CAL_CONFIG_ENABLE;
> + writel(value, eqos->regs + AUTO_CAL_CONFIG);
> + }
> +
> + clk_set_rate(eqos->clk_tx, rate);
Could check error code here, and for other clock ops too.
> +}
> +
> +static int tegra_eqos_init(struct platform_device *pdev, void *priv)
> +{
> + struct tegra_eqos *eqos = priv;
> + unsigned long rate;
> + u32 value;
> +
> + rate = clk_get_rate(eqos->clk_slave);
> +
> + value = readl(eqos->regs + 0xdc);
No point in reading the value when it is fully overwritten.
> + value = (rate / 1000000) - 1;
> + writel(value, eqos->regs + 0xdc);
Please add a define for 0xdc.
> +
> + return 0;
> +}
> +
> +static void *tegra_eqos_probe(struct platform_device *pdev,
> + struct plat_stmmacenet_data *data,
> + struct stmmac_resources *res)
> +{
> + struct tegra_eqos *eqos;
> + int err;
> +
> + eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL);
> + if (!eqos) {
> + err = -ENOMEM;
> + goto error;
> + }
> +
> + eqos->dev = &pdev->dev;
> + eqos->regs = res->addr;
> +
> + eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus");
> + if (IS_ERR(eqos->clk_master)) {
> + err = PTR_ERR(eqos->clk_master);
> + goto error;
> + }
> +
> + err = clk_prepare_enable(eqos->clk_master);
> + if (err < 0)
> + goto error;
> +
> + eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus");
> + if (IS_ERR(eqos->clk_slave)) {
> + err = PTR_ERR(eqos->clk_slave);
> + goto disable_master;
> + }
> +
> + data->stmmac_clk = eqos->clk_slave;
> +
> + err = clk_prepare_enable(eqos->clk_slave);
> + if (err < 0)
> + goto disable_master;
> +
> + eqos->clk_rx = devm_clk_get(&pdev->dev, "rx");
> + if (IS_ERR(eqos->clk_rx)) {
> + err = PTR_ERR(eqos->clk_rx);
> + goto disable_slave;
> + }
> +
> + err = clk_prepare_enable(eqos->clk_rx);
> + if (err < 0)
> + goto disable_slave;
> +
> + eqos->clk_tx = devm_clk_get(&pdev->dev, "tx");
> + if (IS_ERR(eqos->clk_tx)) {
> + err = PTR_ERR(eqos->clk_tx);
> + goto disable_rx;
> + }
> +
> + err = clk_prepare_enable(eqos->clk_tx);
> + if (err < 0)
> + goto disable_rx;
> +
> + eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
> + if (IS_ERR(eqos->reset)) {
> + err = PTR_ERR(eqos->reset);
> + goto disable_tx;
> + }
> +
> + usleep_range(2000, 4000);
> + gpiod_set_value(eqos->reset, 0);
> +
> + eqos->rst = devm_reset_control_get(&pdev->dev, "eqos");
> + if (IS_ERR(eqos->rst)) {
> + err = PTR_ERR(eqos->rst);
> + goto reset_phy;
> + }
> +
> + err = reset_control_assert(eqos->rst);
> + if (err < 0)
> + goto reset_phy;
> +
> + usleep_range(2000, 4000);
> +
> + err = reset_control_deassert(eqos->rst);
> + if (err < 0)
> + goto reset_phy;
> +
> + usleep_range(2000, 4000);
> +
> + data->fix_mac_speed = tegra_eqos_fix_speed;
> + data->init = tegra_eqos_init;
> + data->bsp_priv = eqos;
> +
> + err = tegra_eqos_init(pdev, eqos);
> + if (err < 0)
> + goto reset;
> +
> +out:
> + return eqos;
> +
> +reset:
> + reset_control_assert(eqos->rst);
> +reset_phy:
> + gpiod_set_value(eqos->reset, 1);
> +disable_tx:
> + clk_disable_unprepare(eqos->clk_tx);
> +disable_rx:
> + clk_disable_unprepare(eqos->clk_rx);
> +disable_slave:
> + clk_disable_unprepare(eqos->clk_slave);
> +disable_master:
> + clk_disable_unprepare(eqos->clk_master);
> +error:
> + eqos = ERR_PTR(err);
> + goto out;
> +}
> +
> +static int tegra_eqos_remove(struct platform_device *pdev)
> +{
> + struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev);
> +
> + reset_control_assert(eqos->rst);
> + gpiod_set_value(eqos->reset, 1);
> + clk_disable_unprepare(eqos->clk_tx);
> + clk_disable_unprepare(eqos->clk_rx);
> + clk_disable_unprepare(eqos->clk_slave);
> + clk_disable_unprepare(eqos->clk_master);
> +
> + return 0;
> +}
> +
> struct dwc_eth_dwmac_data {
> void *(*probe)(struct platform_device *pdev,
> struct plat_stmmacenet_data *data,
> @@ -160,6 +406,11 @@ static const struct dwc_eth_dwmac_data dwc_qos_data = {
> .remove = dwc_qos_remove,
> };
>
> +static const struct dwc_eth_dwmac_data tegra_eqos_data = {
> + .probe = tegra_eqos_probe,
> + .remove = tegra_eqos_remove,
> +};
> +
> static int dwc_eth_dwmac_probe(struct platform_device *pdev)
> {
> const struct dwc_eth_dwmac_data *data;
> @@ -245,6 +496,7 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev)
>
> static const struct of_device_id dwc_eth_dwmac_match[] = {
> { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
> + { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data},
Missing space before '}'.
> { }
> };
> MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
>
[toc] | [prev] | [next] | [standalone]
| From | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| Date | 2017-02-23 18:30 +0100 |
| Subject | [PATCH 4/7] net: stmmac: Parse FIFO sizes from feature registers |
| Message-ID | <te5nk-4nQ-33@gated-at.bofh.it> |
| In reply to | #1587038 |
From: Thierry Reding <treding@nvidia.com>
New version of this core encode the FIFO sizes in one of the feature
registers. Use these sizes as default, but still allow device tree to
override them for backwards compatibility.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 3 +++
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
3 files changed, 8 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 144fe84e8a53..6ac653845d82 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -324,6 +324,9 @@ struct dma_features {
unsigned int number_tx_queues;
/* Alternate (enhanced) DESC mode */
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 */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 377d1b44d4f2..8d249f3b34c8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -296,6 +296,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
hw_cap = readl(ioaddr + GMAC_HW_FEATURE1);
dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
+ dma_cap->tx_fifo_size = 128 << ((hw_cap >> 6) & 0x1f);
+ dma_cap->rx_fifo_size = 128 << ((hw_cap >> 0) & 0x1f);
/* MAC HW feature2 */
hw_cap = readl(ioaddr + GMAC_HW_FEATURE2);
/* TX and RX number of channels */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d7387919bdb6..291e34f0ca94 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1281,6 +1281,9 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
{
int rxfifosz = priv->plat->rx_fifo_size;
+ if (rxfifosz == 0)
+ rxfifosz = priv->dma_cap.rx_fifo_size;
+
if (priv->plat->force_thresh_dma_mode)
priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz);
else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
--
2.11.1
[toc] | [prev] | [next] | [standalone]
| From | Mikko Perttunen <cyndis@kapsi.fi> |
|---|---|
| Date | 2017-02-27 11:00 +0100 |
| Subject | Re: [PATCH 4/7] net: stmmac: Parse FIFO sizes from feature registers |
| Message-ID | <tfqg1-3L5-9@gated-at.bofh.it> |
| In reply to | #1587042 |
On 23.02.2017 19:24, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> New version of this core encode the FIFO sizes in one of the feature
> registers. Use these sizes as default, but still allow device tree to
> override them for backwards compatibility.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/common.h | 3 +++
> drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 2 ++
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
> 3 files changed, 8 insertions(+)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 144fe84e8a53..6ac653845d82 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -324,6 +324,9 @@ struct dma_features {
> unsigned int number_tx_queues;
> /* Alternate (enhanced) DESC mode */
> 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 */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 377d1b44d4f2..8d249f3b34c8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -296,6 +296,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
> hw_cap = readl(ioaddr + GMAC_HW_FEATURE1);
> dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
> dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
> + dma_cap->tx_fifo_size = 128 << ((hw_cap >> 6) & 0x1f);
> + dma_cap->rx_fifo_size = 128 << ((hw_cap >> 0) & 0x1f);
> /* MAC HW feature2 */
> hw_cap = readl(ioaddr + GMAC_HW_FEATURE2);
> /* TX and RX number of channels */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index d7387919bdb6..291e34f0ca94 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1281,6 +1281,9 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
> {
> int rxfifosz = priv->plat->rx_fifo_size;
>
> + if (rxfifosz == 0)
> + rxfifosz = priv->dma_cap.rx_fifo_size;
> +
> if (priv->plat->force_thresh_dma_mode)
> priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz);
> else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2017-02-23 19:30 +0100 |
| Message-ID | <te6jn-4Yu-1@gated-at.bofh.it> |
| In reply to | #1587038 |
The net-next tree is closed, therefore it is not appropriate to submit feature patches or cleanups at this time. Please wait for the merge window to be finished and the net-next tree to open back up before resubmitting this patch series. Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| Date | 2017-02-27 08:40 +0100 |
| Message-ID | <tfo4x-2jd-7@gated-at.bofh.it> |
| In reply to | #1587067 |
[Multipart message — attachments visible in raw view] — view raw
On Thu, Feb 23, 2017 at 12:57:05PM -0500, David Miller wrote: > > The net-next tree is closed, therefore it is not appropriate to submit > feature patches or cleanups at this time. > > Please wait for the merge window to be finished and the net-next tree > to open back up before resubmitting this patch series. Okay, I'll resend this after the merge window. In the meantime, surely it's okay for others to review patches? Thierry
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web