* [RFC PATCH 0/4] cpsw: support for control module register
@ 2013-09-08 11:23 Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 1/4] net: ethernet: cpsw: switch to devres allocations Mugunthan V N
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Mugunthan V N @ 2013-09-08 11:23 UTC (permalink / raw)
To: netdev
Cc: zonque, davem, bcousson, tony, devicetree-discuss, linux-omap,
Mugunthan V N
This patch series adds the support for configuring GMII_SEL register
of control module to select the phy mode type and also to configure
the clock source for RMII phy mode whether to use internal clock or
the external clock from the phy itself.
Till now CPSW works as this configuration is done in U-Boot and carried
over to the kernel. But during suspend/resume Control module tends to
lose its configured value for GMII_SEL register in AM33xx PG1.0, so
if CPSW is used in RMII or RGMII mode, on resume cpsw is not working
as GMII_SEL register lost its configuration values.
The initial version of the patch is done by Daniel Mack but as per
Tony's comment he wants it as a seperate driver as it is done in USB
control module. I have created a seperate driver for the same and as
the merge window is open now and no feature request is accepted I am
submitting it as RFC for reviews.
Daniel Mack (1):
net: ethernet: cpsw: switch to devres allocations
Mugunthan V N (3):
drivers: net: cpsw-phy-sel: Add new driver for phy mode selection for
cpsw
drivers: net: cpsw: use cpsw-phy-sel driver to configure phy mode
ARM: dts: am33xx: adopt to cpsw-phy-sel driver to configure phy mode
.../devicetree/bindings/net/cpsw-phy-sel.txt | 28 ++++
arch/arm/boot/dts/am33xx.dtsi | 6 +
drivers/net/ethernet/ti/Kconfig | 8 +
drivers/net/ethernet/ti/Makefile | 1 +
drivers/net/ethernet/ti/cpsw-phy-sel.c | 161 +++++++++++++++++++++
drivers/net/ethernet/ti/cpsw.c | 157 ++++++--------------
drivers/net/ethernet/ti/cpsw.h | 2 +
7 files changed, 253 insertions(+), 110 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/cpsw-phy-sel.txt
create mode 100644 drivers/net/ethernet/ti/cpsw-phy-sel.c
--
1.8.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC PATCH 1/4] net: ethernet: cpsw: switch to devres allocations
2013-09-08 11:23 [RFC PATCH 0/4] cpsw: support for control module register Mugunthan V N
@ 2013-09-08 11:23 ` Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 2/4] drivers: net: cpsw-phy-sel: Add new driver for phy mode selection for cpsw Mugunthan V N
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Mugunthan V N @ 2013-09-08 11:23 UTC (permalink / raw)
To: netdev
Cc: zonque, davem, bcousson, tony, devicetree-discuss, linux-omap,
Mugunthan V N
From: Daniel Mack <zonque@gmail.com>
This patch cleans up the allocation and error unwind paths, which
allows us to carry less information in struct cpsw_priv and reduce the
amount of jump labels in the probe functions.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 153 ++++++++++++-----------------------------
1 file changed, 43 insertions(+), 110 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 79974e3..01c42e1 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -367,8 +367,6 @@ struct cpsw_priv {
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
- struct resource *cpsw_res;
- struct resource *cpsw_wr_res;
struct napi_struct napi;
struct device *dev;
struct cpsw_platform_data data;
@@ -1712,62 +1710,55 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (of_property_read_u32(node, "active_slave", &prop)) {
pr_err("Missing active_slave property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->active_slave = prop;
if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
pr_err("Missing cpts_clock_mult property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->cpts_clock_mult = prop;
if (of_property_read_u32(node, "cpts_clock_shift", &prop)) {
pr_err("Missing cpts_clock_shift property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->cpts_clock_shift = prop;
- data->slave_data = kcalloc(data->slaves, sizeof(struct cpsw_slave_data),
- GFP_KERNEL);
+ data->slave_data = devm_kzalloc(&pdev->dev, data->slaves
+ * sizeof(struct cpsw_slave_data),
+ GFP_KERNEL);
if (!data->slave_data)
- return -EINVAL;
+ return -ENOMEM;
if (of_property_read_u32(node, "cpdma_channels", &prop)) {
pr_err("Missing cpdma_channels property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->channels = prop;
if (of_property_read_u32(node, "ale_entries", &prop)) {
pr_err("Missing ale_entries property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->ale_entries = prop;
if (of_property_read_u32(node, "bd_ram_size", &prop)) {
pr_err("Missing bd_ram_size property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->bd_ram_size = prop;
if (of_property_read_u32(node, "rx_descs", &prop)) {
pr_err("Missing rx_descs property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->rx_descs = prop;
if (of_property_read_u32(node, "mac_control", &prop)) {
pr_err("Missing mac_control property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->mac_control = prop;
@@ -1794,8 +1785,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
parp = of_get_property(slave_node, "phy_id", &lenp);
if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
pr_err("Missing slave[%d] phy_id property\n", i);
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
phyid = be32_to_cpup(parp+1);
@@ -1825,10 +1815,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
return 0;
-
-error_ret:
- kfree(data->slave_data);
- return ret;
}
static int cpsw_probe_dual_emac(struct platform_device *pdev,
@@ -1870,7 +1856,6 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
priv_sl2->coal_intvl = 0;
priv_sl2->bus_freq_mhz = priv->bus_freq_mhz;
- priv_sl2->cpsw_res = priv->cpsw_res;
priv_sl2->regs = priv->regs;
priv_sl2->host_port = priv->host_port;
priv_sl2->host_port_regs = priv->host_port_regs;
@@ -1914,8 +1899,8 @@ static int cpsw_probe(struct platform_device *pdev)
struct cpsw_priv *priv;
struct cpdma_params dma_params;
struct cpsw_ale_params ale_params;
- void __iomem *ss_regs, *wr_regs;
- struct resource *res;
+ void __iomem *ss_regs;
+ struct resource *res, *ss_res;
u32 slave_offset, sliver_offset, slave_size;
int ret = 0, i, k = 0;
@@ -1951,7 +1936,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (cpsw_probe_dt(&priv->data, pdev)) {
pr_err("cpsw: platform data missing\n");
ret = -ENODEV;
- goto clean_ndev_ret;
+ goto clean_runtime_disable_ret;
}
data = &priv->data;
@@ -1965,11 +1950,12 @@ static int cpsw_probe(struct platform_device *pdev)
memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
- priv->slaves = kzalloc(sizeof(struct cpsw_slave) * data->slaves,
- GFP_KERNEL);
+ priv->slaves = devm_kzalloc(&pdev->dev,
+ sizeof(struct cpsw_slave) * data->slaves,
+ GFP_KERNEL);
if (!priv->slaves) {
- ret = -EBUSY;
- goto clean_ndev_ret;
+ ret = -ENOMEM;
+ goto clean_runtime_disable_ret;
}
for (i = 0; i < data->slaves; i++)
priv->slaves[i].slave_num = i;
@@ -1977,55 +1963,31 @@ static int cpsw_probe(struct platform_device *pdev)
priv->slaves[0].ndev = ndev;
priv->emac_port = 0;
- priv->clk = clk_get(&pdev->dev, "fck");
+ priv->clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(priv->clk)) {
- dev_err(&pdev->dev, "fck is not found\n");
+ dev_err(priv->dev, "fck is not found\n");
ret = -ENODEV;
- goto clean_slave_ret;
+ goto clean_runtime_disable_ret;
}
priv->coal_intvl = 0;
priv->bus_freq_mhz = clk_get_rate(priv->clk) / 1000000;
- priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!priv->cpsw_res) {
- dev_err(priv->dev, "error getting i/o resource\n");
- ret = -ENOENT;
- goto clean_clk_ret;
- }
- if (!request_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res), ndev->name)) {
- dev_err(priv->dev, "failed request i/o region\n");
- ret = -ENXIO;
- goto clean_clk_ret;
- }
- ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
- if (!ss_regs) {
- dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_iores_ret;
+ ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ss_regs = devm_ioremap_resource(&pdev->dev, ss_res);
+ if (IS_ERR(ss_regs)) {
+ ret = PTR_ERR(ss_regs);
+ goto clean_runtime_disable_ret;
}
priv->regs = ss_regs;
priv->version = __raw_readl(&priv->regs->id_ver);
priv->host_port = HOST_PORT_NUM;
- priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!priv->cpsw_wr_res) {
- dev_err(priv->dev, "error getting i/o resource\n");
- ret = -ENOENT;
- goto clean_iomap_ret;
- }
- if (!request_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res), ndev->name)) {
- dev_err(priv->dev, "failed request i/o region\n");
- ret = -ENXIO;
- goto clean_iomap_ret;
- }
- wr_regs = ioremap(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
- if (!wr_regs) {
- dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_wr_iores_ret;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->wr_regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->wr_regs)) {
+ ret = PTR_ERR(priv->wr_regs);
+ goto clean_runtime_disable_ret;
}
- priv->wr_regs = wr_regs;
memset(&dma_params, 0, sizeof(dma_params));
memset(&ale_params, 0, sizeof(ale_params));
@@ -2056,12 +2018,12 @@ static int cpsw_probe(struct platform_device *pdev)
slave_size = CPSW2_SLAVE_SIZE;
sliver_offset = CPSW2_SLIVER_OFFSET;
dma_params.desc_mem_phys =
- (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET;
+ (u32 __force) ss_res->start + CPSW2_BD_OFFSET;
break;
default:
dev_err(priv->dev, "unknown version 0x%08x\n", priv->version);
ret = -ENODEV;
- goto clean_cpsw_wr_iores_ret;
+ goto clean_runtime_disable_ret;
}
for (i = 0; i < priv->data.slaves; i++) {
struct cpsw_slave *slave = &priv->slaves[i];
@@ -2089,7 +2051,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (!priv->dma) {
dev_err(priv->dev, "error initializing dma\n");
ret = -ENOMEM;
- goto clean_wr_iomap_ret;
+ goto clean_runtime_disable_ret;
}
priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
@@ -2124,8 +2086,8 @@ static int cpsw_probe(struct platform_device *pdev)
while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
for (i = res->start; i <= res->end; i++) {
- if (request_irq(i, cpsw_interrupt, 0,
- dev_name(&pdev->dev), priv)) {
+ if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
+ dev_name(priv->dev), priv)) {
dev_err(priv->dev, "error attaching irq\n");
goto clean_ale_ret;
}
@@ -2147,7 +2109,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (ret) {
dev_err(priv->dev, "error registering net device\n");
ret = -ENODEV;
- goto clean_irq_ret;
+ goto clean_ale_ret;
}
if (cpts_register(&pdev->dev, priv->cpts,
@@ -2155,44 +2117,27 @@ static int cpsw_probe(struct platform_device *pdev)
dev_err(priv->dev, "error registering cpts device\n");
cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
- priv->cpsw_res->start, ndev->irq);
+ ss_res->start, ndev->irq);
if (priv->data.dual_emac) {
ret = cpsw_probe_dual_emac(pdev, priv);
if (ret) {
cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
- goto clean_irq_ret;
+ goto clean_ale_ret;
}
}
return 0;
-clean_irq_ret:
- for (i = 0; i < priv->num_irqs; i++)
- free_irq(priv->irqs_table[i], priv);
clean_ale_ret:
cpsw_ale_destroy(priv->ale);
clean_dma_ret:
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
-clean_wr_iomap_ret:
- iounmap(priv->wr_regs);
-clean_cpsw_wr_iores_ret:
- release_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
-clean_iomap_ret:
- iounmap(priv->regs);
-clean_cpsw_iores_ret:
- release_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res));
-clean_clk_ret:
- clk_put(priv->clk);
-clean_slave_ret:
+clean_runtime_disable_ret:
pm_runtime_disable(&pdev->dev);
- kfree(priv->slaves);
clean_ndev_ret:
- kfree(priv->data.slave_data);
free_netdev(priv->ndev);
return ret;
}
@@ -2201,30 +2146,18 @@ static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_priv *priv = netdev_priv(ndev);
- int i;
if (priv->data.dual_emac)
unregister_netdev(cpsw_get_slave_ndev(priv, 1));
unregister_netdev(ndev);
cpts_unregister(priv->cpts);
- for (i = 0; i < priv->num_irqs; i++)
- free_irq(priv->irqs_table[i], priv);
cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
- iounmap(priv->regs);
- release_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res));
- iounmap(priv->wr_regs);
- release_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
pm_runtime_disable(&pdev->dev);
- clk_put(priv->clk);
- kfree(priv->slaves);
- kfree(priv->data.slave_data);
if (priv->data.dual_emac)
free_netdev(cpsw_get_slave_ndev(priv, 1));
free_netdev(ndev);
--
1.8.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH 2/4] drivers: net: cpsw-phy-sel: Add new driver for phy mode selection for cpsw
2013-09-08 11:23 [RFC PATCH 0/4] cpsw: support for control module register Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 1/4] net: ethernet: cpsw: switch to devres allocations Mugunthan V N
@ 2013-09-08 11:23 ` Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 3/4] drivers: net: cpsw: use cpsw-phy-sel driver to configure phy mode Mugunthan V N
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Mugunthan V N @ 2013-09-08 11:23 UTC (permalink / raw)
To: netdev
Cc: zonque, davem, bcousson, tony, devicetree-discuss, linux-omap,
Mugunthan V N
The cpsw currently lacks code to properly set up the hardware interface
mode on AM33xx. Other platforms might be equally affected.
Usually, the bootloader will configure the control module register, so
probably that's why such support wasn't needed in the past. In suspend
mode though, this register is modified, and so it needs reprogramming
after resume.
This patch adds a new driver in which hardware interface can configure
correct register bits when the slave is opened.
The AM33xx also has a bit for each slave to configure the RMII reference
clock direction. Setting it is now supported by a per-slave DT property.
This code path introducted by this patch is currently exclusive for
am33xx and same can be extened to various platforms via the DT compatibility
property.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
.../devicetree/bindings/net/cpsw-phy-sel.txt | 28 ++++
drivers/net/ethernet/ti/Kconfig | 8 +
drivers/net/ethernet/ti/Makefile | 1 +
drivers/net/ethernet/ti/cpsw-phy-sel.c | 161 +++++++++++++++++++++
drivers/net/ethernet/ti/cpsw.h | 2 +
5 files changed, 200 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/cpsw-phy-sel.txt
create mode 100644 drivers/net/ethernet/ti/cpsw-phy-sel.c
diff --git a/Documentation/devicetree/bindings/net/cpsw-phy-sel.txt b/Documentation/devicetree/bindings/net/cpsw-phy-sel.txt
new file mode 100644
index 0000000..d45fc83
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cpsw-phy-sel.txt
@@ -0,0 +1,28 @@
+TI CPSW Phy mode Selection Device Tree Bindings
+-----------------------------------------------
+
+Required properties:
+- compatible : Should be "ti,am3352-cpsw-phy-sel"
+- reg : physical base address and size of the cpsw
+ registers map
+- reg-names : names of the register map given in "reg" node
+
+Optional properties:
+-rmii-clock-ext : If present, the driver will configure the RMII
+ interface to external clock usage
+
+Examples:
+
+ phy_sel: cpsw_phy_sel@44e10650 {
+ compatible = "ti,am3352-cpsw-phy-sel";
+ reg= <0x44e10650 0x4>;
+ reg-names = "gmii-sel";
+ };
+
+(or)
+ phy_sel: cpsw_phy_sel@44e10650 {
+ compatible = "ti,am3352-cpsw-phy-sel";
+ reg= <0x44e10650 0x4>;
+ reg-names = "gmii-sel";
+ rmii-clock-ext;
+ };
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index de71b1e..53150c2 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -49,11 +49,19 @@ config TI_DAVINCI_CPDMA
To compile this driver as a module, choose M here: the module
will be called davinci_cpdma. This is recommended.
+config TI_CPSW_PHY_SEL
+ boolean "TI CPSW Switch Phy sel Support"
+ depends on TI_CPSW
+ ---help---
+ This driver supports configuring of the phy mode connected to
+ the CPSW.
+
config TI_CPSW
tristate "TI CPSW Switch Support"
depends on ARM && (ARCH_DAVINCI || SOC_AM33XX)
select TI_DAVINCI_CPDMA
select TI_DAVINCI_MDIO
+ select TI_CPSW_PHY_SEL
---help---
This driver supports TI's CPSW Ethernet Switch.
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index c65148e..9cfaab8 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_CPMAC) += cpmac.o
obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
+obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o
obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o
diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c
new file mode 100644
index 0000000..593f459
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c
@@ -0,0 +1,161 @@
+/* Texas Instruments Ethernet Switch Driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include "cpsw.h"
+
+/* AM33xx SoC specific definitions for the CONTROL port */
+#define AM33XX_GMII_SEL_MODE_MII 0
+#define AM33XX_GMII_SEL_MODE_RMII 1
+#define AM33XX_GMII_SEL_MODE_RGMII 2
+
+#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7)
+#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6)
+
+struct cpsw_phy_sel_priv {
+ struct device *dev;
+ u32 __iomem *gmii_sel;
+ bool rmii_clock_external;
+ void (*cpsw_phy_sel)(struct cpsw_phy_sel_priv *priv,
+ phy_interface_t phy_mode, int slave);
+};
+
+
+static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv,
+ phy_interface_t phy_mode, int slave)
+{
+ u32 reg;
+ u32 mask;
+ u32 mode = 0;
+
+ reg = readl(priv->gmii_sel);
+
+ switch (phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ mode = AM33XX_GMII_SEL_MODE_RMII;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ mode = AM33XX_GMII_SEL_MODE_RGMII;
+ break;
+
+ case PHY_INTERFACE_MODE_MII:
+ default:
+ mode = AM33XX_GMII_SEL_MODE_MII;
+ break;
+ };
+
+ mask = 0x3 << (slave * 2) | BIT(slave + 6);
+ mode <<= slave * 2;
+
+ if (priv->rmii_clock_external) {
+ if (slave == 0)
+ mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
+ else
+ mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
+ }
+
+ reg &= ~mask;
+ reg |= mode;
+
+ writel(reg, priv->gmii_sel);
+}
+
+static struct platform_driver cpsw_phy_sel_driver;
+static int match(struct device *dev, void *data)
+{
+ struct device_node *node = (struct device_node *)data;
+ return dev->of_node == node &&
+ dev->driver == &cpsw_phy_sel_driver.driver;
+}
+
+void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave)
+{
+ struct device_node *node;
+ struct cpsw_phy_sel_priv *priv;
+
+ node = of_get_child_by_name(dev->of_node, "cpsw_phy_sel");
+ if (!node) {
+ dev_err(dev, "Phy mode driver DT not found\n");
+ return;
+ }
+
+ dev = bus_find_device(&platform_bus_type, NULL, node, match);
+ priv = dev_get_drvdata(dev);
+
+ priv->cpsw_phy_sel(priv, phy_mode, slave);
+}
+EXPORT_SYMBOL_GPL(cpsw_phy_sel);
+
+static const struct of_device_id cpsw_phy_sel_id_table[] = {
+ {
+ .compatible = "ti,am3352-cpsw-phy-sel",
+ .data = &cpsw_gmii_sel_am3352,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, cpsw_phy_sel_id_table);
+
+static int cpsw_phy_sel_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ const struct of_device_id *of_id;
+ struct cpsw_phy_sel_priv *priv;
+
+ of_id = of_match_node(cpsw_phy_sel_id_table, pdev->dev.of_node);
+ if (!of_id)
+ return -EINVAL;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "unable to alloc memory for cpsw phy sel\n");
+ return -ENOMEM;
+ }
+
+ priv->cpsw_phy_sel = of_id->data;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gmii-sel");
+ priv->gmii_sel = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->gmii_sel))
+ return PTR_ERR(priv->gmii_sel);
+
+ if (of_find_property(pdev->dev.of_node, "rmii-clock-ext", NULL))
+ priv->rmii_clock_external = true;
+
+ dev_set_drvdata(&pdev->dev, priv);
+
+ return 0;
+}
+
+static struct platform_driver cpsw_phy_sel_driver = {
+ .probe = cpsw_phy_sel_probe,
+ .driver = {
+ .name = "cpsw-phy-sel",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(cpsw_phy_sel_id_table),
+ },
+};
+
+module_platform_driver(cpsw_phy_sel_driver);
+MODULE_AUTHOR("Mugunthan V N <mugunthanvnm@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index eb3e101..574f49d 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -39,4 +39,6 @@ struct cpsw_platform_data {
bool dual_emac; /* Enable Dual EMAC mode */
};
+void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave);
+
#endif /* __CPSW_H__ */
--
1.8.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH 3/4] drivers: net: cpsw: use cpsw-phy-sel driver to configure phy mode
2013-09-08 11:23 [RFC PATCH 0/4] cpsw: support for control module register Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 1/4] net: ethernet: cpsw: switch to devres allocations Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 2/4] drivers: net: cpsw-phy-sel: Add new driver for phy mode selection for cpsw Mugunthan V N
@ 2013-09-08 11:23 ` Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 4/4] ARM: dts: am33xx: adopt to " Mugunthan V N
2013-09-09 8:58 ` [RFC PATCH 0/4] cpsw: support for control module register Daniel Mack
4 siblings, 0 replies; 10+ messages in thread
From: Mugunthan V N @ 2013-09-08 11:23 UTC (permalink / raw)
To: netdev
Cc: zonque, davem, bcousson, tony, devicetree-discuss, linux-omap,
Mugunthan V N
Phy mode can be configured via the cpsw-phy-sel driver, this patch enabled the
cpsw driver to utilise the api provided by the cpsw-phy-sel driver to configure
the phy mode.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 01c42e1..5efb37b 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1021,6 +1021,10 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
dev_info(priv->dev, "phy found : id is : 0x%x\n",
slave->phy->phy_id);
phy_start(slave->phy);
+
+ /* Configure GMII_SEL register */
+ cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface,
+ slave->slave_num);
}
}
--
1.8.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH 4/4] ARM: dts: am33xx: adopt to cpsw-phy-sel driver to configure phy mode
2013-09-08 11:23 [RFC PATCH 0/4] cpsw: support for control module register Mugunthan V N
` (2 preceding siblings ...)
2013-09-08 11:23 ` [RFC PATCH 3/4] drivers: net: cpsw: use cpsw-phy-sel driver to configure phy mode Mugunthan V N
@ 2013-09-08 11:23 ` Mugunthan V N
2013-09-08 18:04 ` Sergei Shtylyov
2013-09-09 8:58 ` [RFC PATCH 0/4] cpsw: support for control module register Daniel Mack
4 siblings, 1 reply; 10+ messages in thread
From: Mugunthan V N @ 2013-09-08 11:23 UTC (permalink / raw)
To: netdev
Cc: zonque, davem, bcousson, tony, devicetree-discuss, linux-omap,
Mugunthan V N
Add DT entries for the phy mode selection in AM33xx SoC using cpsw-phy-sel
driver.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
arch/arm/boot/dts/am33xx.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index f9c5da9..4359672 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -594,6 +594,12 @@
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
+
+ phy_sel: cpsw_phy_sel@44e10650 {
+ compatible = "ti,am3352-cpsw-phy-sel";
+ reg= <0x44e10650 0x4>;
+ reg-names = "gmii-sel";
+ };
};
ocmcram: ocmcram@40300000 {
--
1.8.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 4/4] ARM: dts: am33xx: adopt to cpsw-phy-sel driver to configure phy mode
2013-09-08 11:23 ` [RFC PATCH 4/4] ARM: dts: am33xx: adopt to " Mugunthan V N
@ 2013-09-08 18:04 ` Sergei Shtylyov
2013-09-09 6:42 ` Mugunthan V N
0 siblings, 1 reply; 10+ messages in thread
From: Sergei Shtylyov @ 2013-09-08 18:04 UTC (permalink / raw)
To: Mugunthan V N
Cc: netdev, zonque, davem, bcousson, tony, devicetree-discuss,
linux-omap
Hello.
On 09/08/2013 03:23 PM, Mugunthan V N wrote:
> Add DT entries for the phy mode selection in AM33xx SoC using cpsw-phy-sel
> driver.
> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
> ---
> arch/arm/boot/dts/am33xx.dtsi | 6 ++++++
> 1 file changed, 6 insertions(+)
> diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
> index f9c5da9..4359672 100644
> --- a/arch/arm/boot/dts/am33xx.dtsi
> +++ b/arch/arm/boot/dts/am33xx.dtsi
> @@ -594,6 +594,12 @@
> /* Filled in by U-Boot */
> mac-address = [ 00 00 00 00 00 00 ];
> };
> +
> + phy_sel: cpsw_phy_sel@44e10650 {
Dashes are preferred to uderscores in the device tree names.
> + compatible = "ti,am3352-cpsw-phy-sel";
> + reg= <0x44e10650 0x4>;
> + reg-names = "gmii-sel";
> + };
WBR, Sergei
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 4/4] ARM: dts: am33xx: adopt to cpsw-phy-sel driver to configure phy mode
2013-09-08 18:04 ` Sergei Shtylyov
@ 2013-09-09 6:42 ` Mugunthan V N
2013-09-10 12:55 ` Sergei Shtylyov
0 siblings, 1 reply; 10+ messages in thread
From: Mugunthan V N @ 2013-09-09 6:42 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: netdev, zonque, davem, bcousson, tony, devicetree, linux-omap
On Sunday 08 September 2013 11:34 PM, Sergei Shtylyov wrote:
> Hello.
>
> On 09/08/2013 03:23 PM, Mugunthan V N wrote:
>
>> Add DT entries for the phy mode selection in AM33xx SoC using
>> cpsw-phy-sel
>> driver.
>
>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> ---
>> arch/arm/boot/dts/am33xx.dtsi | 6 ++++++
>> 1 file changed, 6 insertions(+)
>
>> diff --git a/arch/arm/boot/dts/am33xx.dtsi
>> b/arch/arm/boot/dts/am33xx.dtsi
>> index f9c5da9..4359672 100644
>> --- a/arch/arm/boot/dts/am33xx.dtsi
>> +++ b/arch/arm/boot/dts/am33xx.dtsi
>> @@ -594,6 +594,12 @@
>> /* Filled in by U-Boot */
>> mac-address = [ 00 00 00 00 00 00 ];
>> };
>> +
>> + phy_sel: cpsw_phy_sel@44e10650 {
>
> Dashes are preferred to uderscores in the device tree names.
I tried with dashes but i get the below error.
$ make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm dtbs
DTC arch/arm/boot/dts/am335x-evm.dtb
Error: arch/arm/boot/dts/am33xx.dtsi:598.11-12 syntax error
FATAL ERROR: Unable to parse input tree
make[1]: *** [arch/arm/boot/dts/am335x-evm.dtb] Error 1
make: *** [dtbs] Error 2
Regards
Mugunthan V N
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 0/4] cpsw: support for control module register
2013-09-08 11:23 [RFC PATCH 0/4] cpsw: support for control module register Mugunthan V N
` (3 preceding siblings ...)
2013-09-08 11:23 ` [RFC PATCH 4/4] ARM: dts: am33xx: adopt to " Mugunthan V N
@ 2013-09-09 8:58 ` Daniel Mack
2013-09-18 18:49 ` Tony Lindgren
4 siblings, 1 reply; 10+ messages in thread
From: Daniel Mack @ 2013-09-09 8:58 UTC (permalink / raw)
To: Mugunthan V N
Cc: netdev, davem, bcousson, tony, devicetree-discuss, linux-omap
On 08.09.2013 13:23, Mugunthan V N wrote:
> This patch series adds the support for configuring GMII_SEL register
> of control module to select the phy mode type and also to configure
> the clock source for RMII phy mode whether to use internal clock or
> the external clock from the phy itself.
>
> Till now CPSW works as this configuration is done in U-Boot and carried
> over to the kernel. But during suspend/resume Control module tends to
> lose its configured value for GMII_SEL register in AM33xx PG1.0, so
> if CPSW is used in RMII or RGMII mode, on resume cpsw is not working
> as GMII_SEL register lost its configuration values.
>
> The initial version of the patch is done by Daniel Mack but as per
> Tony's comment he wants it as a seperate driver as it is done in USB
> control module. I have created a seperate driver for the same and as
> the merge window is open now and no feature request is accepted I am
> submitting it as RFC for reviews.
Thanks for doing this. It's a somehow expensive approach of writing a
single 32bit register, but I agree it's cleaner to not have this code in
the cpsw driver directly.
For the whole series:
Tested-by: Daniel Mack <zonque@gmail.com>
Daniel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 4/4] ARM: dts: am33xx: adopt to cpsw-phy-sel driver to configure phy mode
2013-09-09 6:42 ` Mugunthan V N
@ 2013-09-10 12:55 ` Sergei Shtylyov
0 siblings, 0 replies; 10+ messages in thread
From: Sergei Shtylyov @ 2013-09-10 12:55 UTC (permalink / raw)
To: Mugunthan V N
Cc: netdev, zonque, davem, bcousson, tony, devicetree, linux-omap
Hello.
On 09-09-2013 10:42, Mugunthan V N wrote:
>>> Add DT entries for the phy mode selection in AM33xx SoC using
>>> cpsw-phy-sel
>>> driver.
>>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>>> ---
>>> arch/arm/boot/dts/am33xx.dtsi | 6 ++++++
>>> 1 file changed, 6 insertions(+)
>>> diff --git a/arch/arm/boot/dts/am33xx.dtsi
>>> b/arch/arm/boot/dts/am33xx.dtsi
>>> index f9c5da9..4359672 100644
>>> --- a/arch/arm/boot/dts/am33xx.dtsi
>>> +++ b/arch/arm/boot/dts/am33xx.dtsi
>>> @@ -594,6 +594,12 @@
>>> /* Filled in by U-Boot */
>>> mac-address = [ 00 00 00 00 00 00 ];
>>> };
>>> +
>>> + phy_sel: cpsw_phy_sel@44e10650 {
>> Dashes are preferred to uderscores in the device tree names.
> I tried with dashes but i get the below error.
> $ make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm dtbs
> DTC arch/arm/boot/dts/am335x-evm.dtb
> Error: arch/arm/boot/dts/am33xx.dtsi:598.11-12 syntax error
> FATAL ERROR: Unable to parse input tree
> make[1]: *** [arch/arm/boot/dts/am335x-evm.dtb] Error 1
> make: *** [dtbs] Error 2
Hm, perhaps the dashes can't be used in the labels but I was talking of
the names. Dashes in the node names should be definitely valid.
> Regards
> Mugunthan V N
WBR, Sergei
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 0/4] cpsw: support for control module register
2013-09-09 8:58 ` [RFC PATCH 0/4] cpsw: support for control module register Daniel Mack
@ 2013-09-18 18:49 ` Tony Lindgren
0 siblings, 0 replies; 10+ messages in thread
From: Tony Lindgren @ 2013-09-18 18:49 UTC (permalink / raw)
To: Daniel Mack
Cc: Mugunthan V N, netdev, davem, bcousson, devicetree-discuss,
linux-omap
* Daniel Mack <zonque@gmail.com> [130909 02:06]:
> On 08.09.2013 13:23, Mugunthan V N wrote:
> > This patch series adds the support for configuring GMII_SEL register
> > of control module to select the phy mode type and also to configure
> > the clock source for RMII phy mode whether to use internal clock or
> > the external clock from the phy itself.
> >
> > Till now CPSW works as this configuration is done in U-Boot and carried
> > over to the kernel. But during suspend/resume Control module tends to
> > lose its configured value for GMII_SEL register in AM33xx PG1.0, so
> > if CPSW is used in RMII or RGMII mode, on resume cpsw is not working
> > as GMII_SEL register lost its configuration values.
> >
> > The initial version of the patch is done by Daniel Mack but as per
> > Tony's comment he wants it as a seperate driver as it is done in USB
> > control module. I have created a seperate driver for the same and as
> > the merge window is open now and no feature request is accepted I am
> > submitting it as RFC for reviews.
>
> Thanks for doing this. It's a somehow expensive approach of writing a
> single 32bit register, but I agree it's cleaner to not have this code in
> the cpsw driver directly.
The main reason for doing that is because this register is in a
separate omap SCM (System Control Module) and may need to be
eventually a child of a SCM core driver. This is to avoid invalid
PM dependencies between separate hardware modules as they can
be clocked separately.
Most of the SCM registers can be already handled by using
pinctrl-single driver, but it's not intended for using for
transceivers etc that are not strictly pinctrl related.
Regards,
Tony
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-09-18 18:49 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-08 11:23 [RFC PATCH 0/4] cpsw: support for control module register Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 1/4] net: ethernet: cpsw: switch to devres allocations Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 2/4] drivers: net: cpsw-phy-sel: Add new driver for phy mode selection for cpsw Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 3/4] drivers: net: cpsw: use cpsw-phy-sel driver to configure phy mode Mugunthan V N
2013-09-08 11:23 ` [RFC PATCH 4/4] ARM: dts: am33xx: adopt to " Mugunthan V N
2013-09-08 18:04 ` Sergei Shtylyov
2013-09-09 6:42 ` Mugunthan V N
2013-09-10 12:55 ` Sergei Shtylyov
2013-09-09 8:58 ` [RFC PATCH 0/4] cpsw: support for control module register Daniel Mack
2013-09-18 18:49 ` Tony Lindgren
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).