TI am335x/am437x/dra7(am5)/dm814x CPSW3G Ethernet Subsystem supports
two 10/100/1000 Ethernet ports with selectable G/MII, RMII, and RGMII interfaces.
The interface mode is selected by configuring the MII mode selection register(s)
(GMII_SEL) in the System Control Module chapter (SCM).
+--------------+
+-------------------------------+ |SCM |
| CPSW | | +---------+ |
| +--------------------------------+gmii_sel | |
| | | | +---------+ |
| +----v---+ +--------+ | +--------------+
| |Port 1..<--+-->GMII/MII<------->
| | | | | | |
| +--------+ | +--------+ |
| | |
| | +--------+ |
| | | RMII <------->
| +--> | |
| | +--------+ |
| | |
| | +--------+ |
| | | RGMII <------->
| +--> | |
| +--------+ |
+-------------------------------+
GMII_SEL register(s) and bit fields placement in SCM are different between SoCs
while fields meaning is the same. GMII_SEL(s) allows to select -
Port GMII/MII/RMII/RGMII Mode; RGMII Internal Delay Mode (SoC dependant) and
RMII Reference Clock Output mode (SoC dependant).
Historically CPSW external Port's interface mode selection configuartion was
introduced using custom driver and API cpsw-phy-sel.c.
This leads to unnecessary driver, DT binding and custom API support effort.
Moreover, even definition of cpsw-phy-sel node in DTs is logically incorrect [1]
mac: ethernet@4a100000 {
compatible = "ti,am4372-cpsw","ti,cpsw";
...
phy_sel: cpsw-phy-sel@44e10650 {
compatible = "ti,am43xx-cpsw-phy-sel";
reg= <0x44e10650 0x4>;
reg-names = "gmii-sel";
};
};
This series introduces attempt to drop custom CPSW Port interface selection
implementation (cpsw-phy-sel.c) and use well defined Linux PHY framework instead.
it introduces CPSW Port's PHY Interface Mode selection Driver (phy-gmii-sel)
which implements standard Linux PHY interface. The phy-gmii-sel PHY device
should defined as child device of SCM node (scm_conf) and can be attached to
each CPSW port node using standard PHY bindings (cell 1 - port number,
cell 2 - RMII refclk mode).
scm_conf: scm_conf@0 {
compatible = "syscon", "simple-bus";
gmii_sel_phy: cpsw-sel-netif {
compatible = "ti,am43xx-gmii-sel-phy";
syscon-scm = <&scm_conf>;
#phy-cells = <2>;
};
};
mac: ethernet@4a100000 {
compatible = "ti,am4372-cpsw","ti,cpsw";
cpsw_emac0: slave@4a100200 {
phy-mode = "rgmii";
phys = <&gmii_sel_phy 1 0>;
};
};
The CPSW driver requests phy-gmii-sel PHY for each external port and uses newly
introduced API phy_set_netif_mode() (Patch 1) for port interface mode selection
when netdev is opened.
slave->data->gmii_sel_phy = devm_of_phy_get(&pdev->dev, port_node, NULL);
slave->data->phy_if = of_get_phy_mode(port_node);
cpsw_ndo_open()
phy_set_netif_mode(slave->data->gmii_sel_phy, slave->data->phy_if);
Note. CPSW Port interface has to be reconfigured every time netdev is opened for
proper System Suspend support where CPSW can lose context.
I've considered two options while working on this series:
1) extend enum phy_mode {} and introduce more enum elements to cover missing,
required Network PHY's Interface Mode definitions, like MII/GMII/RGMII(-XID),
but it'd mean copy-past and data duplication from phy_interface_t -> phy_mode.
More over, phy_interface_t can still continue growing.
2) introduce new PHY API for network interface mode selection which will use
already defined set of modes from phy_interface_t.
Option 2 was selected for this series.
[1] https://www.mail-archive.com/netdev@vger.kernel.org/msg247135.html
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Grygorii Strashko (11):
phy: core add phy_set_netif_mode() api
dt-bindings: phy: add cpsw port interface mode selection phy bindings
phy: ti: introduce phy-gmii-sel driver
dt-bindings: net: ti: cpsw: switch to use phy-gmii-sel phy
net: ethernet: ti: cpsw: add support for port interface mode selection
phy
ARM: dts: dra7: switch to use phy-gmii-sel
ARM: dts: dm814x: switch to use phy-gmii-sel
ARM: dts: am4372: switch to use phy-gmii-sel
ARM: dts: am335x: switch to use phy-gmii-sel
dt-bindings: net: ti: deprecate cpsw-phy-sel bindings
net: ethernet: ti: cpsw: deprecate cpsw-phy-sel driver
.../devicetree/bindings/net/cpsw-phy-sel.txt | 2 +-
Documentation/devicetree/bindings/net/cpsw.txt | 8 +-
.../devicetree/bindings/phy/ti-phy-gmii-sel.txt | 68 ++++
arch/arm/boot/dts/am335x-baltos-ir2110.dts | 4 -
arch/arm/boot/dts/am335x-baltos-ir3220.dts | 3 -
arch/arm/boot/dts/am335x-baltos-ir5221.dts | 3 -
arch/arm/boot/dts/am335x-chiliboard.dts | 3 -
arch/arm/boot/dts/am335x-icev2.dts | 4 -
arch/arm/boot/dts/am335x-igep0033.dtsi | 3 -
arch/arm/boot/dts/am335x-lxm.dts | 3 -
arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts | 5 -
arch/arm/boot/dts/am335x-phycore-som.dtsi | 3 -
arch/arm/boot/dts/am33xx.dtsi | 14 +-
arch/arm/boot/dts/am4372.dtsi | 16 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 5 +-
arch/arm/boot/dts/dm814x.dtsi | 15 +-
arch/arm/boot/dts/dra7.dtsi | 14 +-
drivers/net/ethernet/ti/Kconfig | 6 +-
drivers/net/ethernet/ti/cpsw.c | 18 +-
drivers/net/ethernet/ti/cpsw.h | 6 +
drivers/phy/phy-core.c | 15 +
drivers/phy/ti/Kconfig | 10 +
drivers/phy/ti/Makefile | 1 +
drivers/phy/ti/phy-gmii-sel.c | 345 +++++++++++++++++++++
include/linux/phy/phy.h | 12 +
25 files changed, 520 insertions(+), 66 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/ti-phy-gmii-sel.txt
create mode 100644 drivers/phy/ti/phy-gmii-sel.c
--
2.10.5
The cpsw-phy-sel driver was replaced with new PHY driver phy-gmii-sel, so
deprecate cpsw-phy-sel bindings and update CPSW binding to use phy-gmii-sel
PHY bindings.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
@@ -22,7 +22,8 @@ Required properties: - cpsw-phy-sel : Specifies the phandle to the CPSW phy mode selection device. See also cpsw-phy-sel.txt for it's binding. Note that in legacy cases cpsw-phy-sel may be- a child device instead of a phandle.+ a child device instead of a phandle+ (DEPRECATED, use phy-gmii-sel PHY phandle). Optional properties: - ti,hwmods : Must be "cpgmac0"
@@ -44,6 +45,7 @@ Optional properties: Slave Properties: Required properties: - phy-mode : See ethernet.txt file in the same directory+- phys : phandle on phy-gmii-sel PHY (see phy/ti-phy-gmii-sel.txt) Optional properties: - dual_emac_res_vlan : Specifies VID to be used to segregate the ports
@@ -890,17 +896,13 @@cpsw_emac0:slave@4a100200{/* Filled in by U-Boot */mac-address=[000000000000];+phys=<&phy_gmii_sel11>;};cpsw_emac1:slave@4a100300{/* Filled in by U-Boot */mac-address=[000000000000];-};--phy_sel:cpsw-phy-sel@44e10650{-compatible="ti,am3352-cpsw-phy-sel";-reg=<0x44e106500x4>;-reg-names="gmii-sel";+phys=<&phy_gmii_sel21>;};};
Add support for port interface mode selection phy (phy-gmii-sel):
- try to request interface mode selection phy from Port DT node and fail
silently if not defined and old CONFIG_TI_CPSW_PHY_SEL driver enabled.
- use new phy if requested successfully.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
The cpsw-phy-sel driver was replaced with new PHY driver phy-gmii-sel, so
deprecate cpsw-phy-sel bindings.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
Documentation/devicetree/bindings/net/cpsw-phy-sel.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
TI am335x/am437x/dra7(am5)/dm814x CPSW3G Ethernet Subsystem supports two
10/100/1000 Ethernet ports with selectable G/MII, RMII, and RGMII
interfaces. The interface mode is selected by configuring the MII mode
selection register(s) (GMII_SEL) in the System Control Module chapter
(SCM). GMII_SEL register(s) and bit fields placement in SCM are different
between SoCs while fields meaning is the same.
Historically CPSW external Port's interface mode selection configuartion
was introduced using custom API and driver cpsw-phy-sel.c. This leads to
unnecessary driver, DT binding and custom API support effort.
This patch introduces CPSW Port's PHY Interface Mode selection Driver
(phy-gmii-sel) which implements standard Linux PHY interface and proposed
as a replacement for TI's specific driver cpsw-phy-sel.c and coresponding
custom API.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/phy/ti/Kconfig | 10 ++
drivers/phy/ti/Makefile | 1 +
drivers/phy/ti/phy-gmii-sel.c | 345 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 356 insertions(+)
create mode 100644 drivers/phy/ti/phy-gmii-sel.c
@@ -0,0 +1,345 @@+// SPDX-License-Identifier: GPL-2.0+/*+*TexasInstrumentsCPSWPort'sPHYInterfaceModeselectionDriver+*+*Copyright(C)2018TexasInstrumentsIncorporated-http://www.ti.com/+*+*Basedoncpsw-phy-sel.cdrivercreatedbyMugunthanVN<mugunthanvnm@ti.com>+*/++#include<linux/platform_device.h>+#include<linux/module.h>+#include<linux/mfd/syscon.h>+#include<linux/of.h>+#include<linux/of_net.h>+#include<linux/phy.h>+#include<linux/phy/phy.h>+#include<linux/regmap.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++enum{+PHY_GMII_SEL_PORT_MODE,+PHY_GMII_SEL_RGMII_ID_MODE,+PHY_GMII_SEL_RMII_IO_CLK_EN,+PHY_GMII_SEL_LAST,+};++structphy_gmii_sel_phy_priv{+structphy_gmii_sel_priv*priv;+u32id;+structphy*if_phy;+intrmii_clock_external;+intphy_if_mode;+structregmap_field*fields[PHY_GMII_SEL_LAST];+};++structphy_gmii_sel_soc_data{+u32num_ports;+u32features;+conststructreg_field(*regfields)[PHY_GMII_SEL_LAST];+};++structphy_gmii_sel_priv{+structdevice*dev;+conststructphy_gmii_sel_soc_data*soc_data;+structregmap*regmap;+structphy_provider*phy_provider;++structphy_gmii_sel_phy_priv*if_phys;+};++staticintphy_gmii_sel_mode(structphy*phy,phy_interface_tintf_mode)+{+structphy_gmii_sel_phy_priv*if_phy=phy_get_drvdata(phy);+conststructphy_gmii_sel_soc_data*soc_data=if_phy->priv->soc_data;+structdevice*dev=if_phy->priv->dev;+structregmap_field*regfield;+intret,rgmii_id=0;+u32mode=0;++if_phy->phy_if_mode=intf_mode;++switch(if_phy->phy_if_mode){+casePHY_INTERFACE_MODE_RMII:+mode=AM33XX_GMII_SEL_MODE_RMII;+break;++casePHY_INTERFACE_MODE_RGMII:+mode=AM33XX_GMII_SEL_MODE_RGMII;+break;++casePHY_INTERFACE_MODE_RGMII_ID:+casePHY_INTERFACE_MODE_RGMII_RXID:+casePHY_INTERFACE_MODE_RGMII_TXID:+mode=AM33XX_GMII_SEL_MODE_RGMII;+rgmii_id=1;+break;++default:+dev_warn(dev,+"port%u: unsupported mode: \"%s\". Defaulting to MII.\n",+if_phy->id,phy_modes(rgmii_id));+/* fall through */+casePHY_INTERFACE_MODE_MII:+mode=AM33XX_GMII_SEL_MODE_MII;+break;+};++dev_dbg(dev,"%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n",+__func__,if_phy->id,mode,rgmii_id,+if_phy->rmii_clock_external);++regfield=if_phy->fields[PHY_GMII_SEL_PORT_MODE];+ret=regmap_field_write(regfield,mode);++if(soc_data->features&BIT(PHY_GMII_SEL_RGMII_ID_MODE)&&+if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]){+regfield=if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE];+ret|=regmap_field_write(regfield,rgmii_id);+}++if(soc_data->features&BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)&&+if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]){+regfield=if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN];+ret|=regmap_field_write(regfield,+if_phy->rmii_clock_external);+}++if(ret){+dev_err(dev,"port%u: set mode fail %d",if_phy->id,ret);+return-EIO;+}++return0;+}++staticconst+structreg_fieldphy_gmii_sel_fields_am33xx[][PHY_GMII_SEL_LAST]={+{+[PHY_GMII_SEL_PORT_MODE]=REG_FIELD(0x650,0,1),+[PHY_GMII_SEL_RGMII_ID_MODE]=REG_FIELD(0x650,4,4),+[PHY_GMII_SEL_RMII_IO_CLK_EN]=REG_FIELD(0x650,6,6),+},+{+[PHY_GMII_SEL_PORT_MODE]=REG_FIELD(0x650,2,3),+[PHY_GMII_SEL_RGMII_ID_MODE]=REG_FIELD(0x650,5,5),+[PHY_GMII_SEL_RMII_IO_CLK_EN]=REG_FIELD(0x650,7,7),+},+};++staticconst+structphy_gmii_sel_soc_dataphy_gmii_sel_soc_am33xx={+.num_ports=2,+.features=BIT(PHY_GMII_SEL_RGMII_ID_MODE)|+BIT(PHY_GMII_SEL_RMII_IO_CLK_EN),+.regfields=phy_gmii_sel_fields_am33xx,+};++staticconst+structreg_fieldphy_gmii_sel_fields_dra7[][PHY_GMII_SEL_LAST]={+{+[PHY_GMII_SEL_PORT_MODE]=REG_FIELD(0x554,0,1),+[PHY_GMII_SEL_RGMII_ID_MODE]=REG_FIELD((~0),0,0),+[PHY_GMII_SEL_RMII_IO_CLK_EN]=REG_FIELD((~0),0,0),+},+{+[PHY_GMII_SEL_PORT_MODE]=REG_FIELD(0x554,4,5),+[PHY_GMII_SEL_RGMII_ID_MODE]=REG_FIELD((~0),0,0),+[PHY_GMII_SEL_RMII_IO_CLK_EN]=REG_FIELD((~0),0,0),+},+};++staticconst+structphy_gmii_sel_soc_dataphy_gmii_sel_soc_dra7={+.num_ports=2,+.regfields=phy_gmii_sel_fields_dra7,+};++staticconst+structphy_gmii_sel_soc_dataphy_gmii_sel_soc_dm814={+.num_ports=2,+.features=BIT(PHY_GMII_SEL_RGMII_ID_MODE),+.regfields=phy_gmii_sel_fields_am33xx,+};++staticconststructof_device_idphy_gmii_sel_id_table[]={+{+.compatible="ti,am3352-phy-gmii-sel",+.data=&phy_gmii_sel_soc_am33xx,+},+{+.compatible="ti,dra7xx-phy-gmii-sel",+.data=&phy_gmii_sel_soc_dra7,+},+{+.compatible="ti,am43xx-phy-gmii-sel",+.data=&phy_gmii_sel_soc_am33xx,+},+{+.compatible="ti,dm814-phy-gmii-sel",+.data=&phy_gmii_sel_soc_dm814,+},+{}+};+MODULE_DEVICE_TABLE(of,phy_gmii_sel_id_table);++staticconststructphy_opsphy_gmii_sel_ops={+.set_netif_mode=phy_gmii_sel_mode,+.owner=THIS_MODULE,+};++staticstructphy*phy_gmii_sel_of_xlate(structdevice*dev,+structof_phandle_args*args)+{+structphy_gmii_sel_priv*priv=dev_get_drvdata(dev);+intphy_id=args->args[0];++if(args->args_count<1)+returnERR_PTR(-EINVAL);+if(priv->soc_data->features&BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)&&+args->args_count<2)+returnERR_PTR(-EINVAL);+if(!priv||!priv->if_phys)+returnERR_PTR(-ENODEV);+if(phy_id>priv->soc_data->num_ports)+returnERR_PTR(-EINVAL);+if(phy_id!=priv->if_phys[phy_id-1].id)+returnERR_PTR(-EINVAL);++phy_id--;+if(priv->soc_data->features&BIT(PHY_GMII_SEL_RMII_IO_CLK_EN))+priv->if_phys[phy_id].rmii_clock_external=args->args[1];+dev_dbg(dev,"%s id:%u ext:%d\n",__func__,+priv->if_phys[phy_id].id,args->args[1]);++returnpriv->if_phys[phy_id].if_phy;+}++staticintphy_gmii_sel_init_ports(structphy_gmii_sel_priv*priv)+{+conststructphy_gmii_sel_soc_data*soc_data=priv->soc_data;+structdevice*dev=priv->dev;+structphy_gmii_sel_phy_priv*if_phys;+inti,num_ports,ret;++num_ports=priv->soc_data->num_ports;++if_phys=devm_kcalloc(priv->dev,num_ports,+sizeof(*if_phys),GFP_KERNEL);+if(!if_phys)+return-ENOMEM;+dev_dbg(dev,"%s %d\n",__func__,num_ports);++for(i=0;i<num_ports;i++){+conststructreg_field*field;+structregmap_field*regfield;++if_phys[i].id=i+1;+if_phys[i].priv=priv;++field=&soc_data->regfields[i][PHY_GMII_SEL_PORT_MODE];+dev_dbg(dev,"%s field %x %d %d\n",__func__,+field->reg,field->msb,field->lsb);++regfield=devm_regmap_field_alloc(dev,priv->regmap,*field);+if(IS_ERR(regfield))+returnPTR_ERR(regfield);+if_phys[i].fields[PHY_GMII_SEL_PORT_MODE]=regfield;++field=&soc_data->regfields[i][PHY_GMII_SEL_RGMII_ID_MODE];+if(field->reg!=(~0)){+regfield=devm_regmap_field_alloc(dev,+priv->regmap,+*field);+if(IS_ERR(regfield))+returnPTR_ERR(regfield);+if_phys[i].fields[PHY_GMII_SEL_RGMII_ID_MODE]=+regfield;+}++field=&soc_data->regfields[i][PHY_GMII_SEL_RMII_IO_CLK_EN];+if(field->reg!=(~0)){+regfield=devm_regmap_field_alloc(dev,+priv->regmap,+*field);+if(IS_ERR(regfield))+returnPTR_ERR(regfield);+if_phys[i].fields[PHY_GMII_SEL_RMII_IO_CLK_EN]=+regfield;+}++if_phys[i].if_phy=devm_phy_create(dev,+priv->dev->of_node,+&phy_gmii_sel_ops);+if(IS_ERR(if_phys[i].if_phy)){+ret=PTR_ERR(if_phys[i].if_phy);+dev_err(dev,"Failed to create phy%d %d\n",i,ret);+returnret;+}+phy_set_drvdata(if_phys[i].if_phy,&if_phys[i]);+}++priv->if_phys=if_phys;+return0;+}++staticintphy_gmii_sel_probe(structplatform_device*pdev)+{+structdevice*dev=&pdev->dev;+structdevice_node*node=dev->of_node;+conststructof_device_id*of_id;+structphy_gmii_sel_priv*priv;+intret;++of_id=of_match_node(phy_gmii_sel_id_table,pdev->dev.of_node);+if(!of_id)+return-EINVAL;++priv=devm_kzalloc(&pdev->dev,sizeof(*priv),GFP_KERNEL);+if(!priv)+return-ENOMEM;++priv->dev=&pdev->dev;+priv->soc_data=of_id->data;++priv->regmap=syscon_regmap_lookup_by_phandle(node,"syscon-scm");+if(IS_ERR(priv->regmap)){+ret=PTR_ERR(priv->regmap);+dev_err(dev,"Failed to get syscon %d\n",ret);+returnret;+}++ret=phy_gmii_sel_init_ports(priv);+if(ret)+returnret;++dev_set_drvdata(&pdev->dev,priv);++priv->phy_provider=+devm_of_phy_provider_register(dev,+phy_gmii_sel_of_xlate);+if(IS_ERR(priv->phy_provider)){+ret=PTR_ERR(priv->phy_provider);+dev_err(dev,"Failed to create phy provider %d\n",ret);+returnret;+}++return0;+}++staticstructplatform_driverphy_gmii_sel_driver={+.probe=phy_gmii_sel_probe,+.driver={+.name="phy-gmii-sel",+.of_match_table=phy_gmii_sel_id_table,+},+};+module_platform_driver(phy_gmii_sel_driver);++MODULE_LICENSE("GPL v2");+MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>");+MODULE_DESCRIPTION("TI CPSW Port's PHY Interface Mode selection Driver");
@@ -549,17 +555,14 @@cpsw_emac0:slave@4a100200{/* Filled in by U-Boot */mac-address=[000000000000];+phys=<&phy_gmii_sel1>;+};cpsw_emac1:slave@4a100300{/* Filled in by U-Boot */mac-address=[000000000000];-};--phy_sel:cpsw-phy-sel@48140650{-compatible="ti,am3352-cpsw-phy-sel";-reg=<0x481406500x4>;-reg-names="gmii-sel";+phys=<&phy_gmii_sel2>;};};
Add new API phy_set_netif_mode(struct phy *phy, phy_interface_t mode) and
new PHY operation callback .set_netif_mode() which intended to be implemnte
by PHY drivers which supports Network interrfaces mode selection. Both
accepts phy_interface_t vlaue as input parameter.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/phy/phy-core.c | 15 +++++++++++++++
include/linux/phy/phy.h | 12 ++++++++++++
2 files changed, 27 insertions(+)
@@ -1879,17 +1885,13 @@cpsw_emac0:slave@48480200{/* Filled in by U-Boot */mac-address=[000000000000];+phys=<&phy_gmii_sel1>;};cpsw_emac1:slave@48480300{/* Filled in by U-Boot */mac-address=[000000000000];-};--phy_sel:cpsw-phy-sel@4a002554{-compatible="ti,dra7xx-cpsw-phy-sel";-reg=<0x4a0025540x4>;-reg-names="gmii-sel";+phys=<&phy_gmii_sel2>;};};
@@ -714,17 +720,13 @@cpsw_emac0:slave@4a100200{/* Filled in by U-Boot */mac-address=[000000000000];+phys=<&phy_gmii_sel10>;};cpsw_emac1:slave@4a100300{/* Filled in by U-Boot */mac-address=[000000000000];-};--phy_sel:cpsw-phy-sel@44e10650{-compatible="ti,am43xx-cpsw-phy-sel";-reg=<0x44e106500x4>;-reg-names="gmii-sel";+phys=<&phy_gmii_sel20>;};};
Hi Grygorii
It looks like the MAC can do AM33XX_GMII_SEL_MODE_RGMII and
AM33XX_GMII_SEL_MODE_RGMII_ID. I don't think it can do
AM33XX_GMII_SEL_MODE_RGMII_RXID or AM33XX_GMII_SEL_MODE_RGMII_TXID? I
would prefer it return -EINVAL when asked to do something it cannot
do.
+
+ default:
+ dev_warn(dev,
+ "port%u: unsupported mode: \"%s\". Defaulting to MII.\n",
+ if_phy->id, phy_modes(rgmii_id));
+ /* fall through */
Returning -EINVAL would be better. Otherwise the DT might never get
fixed.
I would prefer each write had its own error check. The fact you don't
return ret means you know ret could be -EINVAL|-EOIO, making
-EMORECOFFEE.
Andrew
Is slave->data->phy_if also passed to phy_connect()? So you are going
to end up with both the MAC and the PHY inserting RGMII delays, and it
not working.
You need to somehow decide if the MAC is going to do the delay, or the
PHY. But not both.
Andrew
From: Kishon Vijay Abraham I <hidden> Date: 2018-10-09 05:23:27
Hi Grygorii,
On Tuesday 09 October 2018 05:19 AM, Grygorii Strashko wrote:
quoted hunk
Add new API phy_set_netif_mode(struct phy *phy, phy_interface_t mode) and
new PHY operation callback .set_netif_mode() which intended to be implemnte
by PHY drivers which supports Network interrfaces mode selection. Both
accepts phy_interface_t vlaue as input parameter.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/phy/phy-core.c | 15 +++++++++++++++
include/linux/phy/phy.h | 12 ++++++++++++
2 files changed, 27 insertions(+)
2) introduce new PHY API for network interface mode selection which will use
already defined set of modes from phy_interface_t.
Option 2 was selected for this series.
Looks good to me :) The dts files will cause merge conflicts with
what I have pending for the ti-sysc changes so please send the dts
changes in a separate series when posting without RFC.
Thanks,
Tony
Now that this driver can live in it's proper place in the
dts, you may want to consider just using standard reg
property for it instead of the syscon-scm. And also get
rid of the syscon reads and writes.
Regards,
Tony
Now that this driver can live in it's proper place in the
right
dts, you may want to consider just using standard reg
property for it instead of the syscon-scm. And also get
rid of the syscon reads and writes.
Could you help clarify how to get syscon in this case?
syscon_node_to_regmap(dev->parent->of_node)?
Also, there are could be more then one gmii_sel registers in SCM in the future,
so I hidden offsets in of_match data.
As result, "reg" not needed at all now.
--
regards,
-grygorii
Hi Grygorii
It looks like the MAC can do AM33XX_GMII_SEL_MODE_RGMII and
AM33XX_GMII_SEL_MODE_RGMII_ID. I don't think it can do
AM33XX_GMII_SEL_MODE_RGMII_RXID or AM33XX_GMII_SEL_MODE_RGMII_TXID?
Sry, but would prefer not to thought this logic as part of this series as i moved it here
unchanged rom cpsw-phy-sel.c (except adding possibility to update only supported field)
and any changes here would require separate review (including all existing TI DT boards)
and testing.
I
would prefer it return -EINVAL when asked to do something it cannot
do.
Just to clarify rgmii_id = 1 means *disable* CPSW Internal Delay Mode.
quoted
+
+ default:
+ dev_warn(dev,
+ "port%u: unsupported mode: \"%s\". Defaulting to MII.\n",
+ if_phy->id, phy_modes(rgmii_id));
+ /* fall through */
Returning -EINVAL would be better. Otherwise the DT might never get
fixed.
Is slave->data->phy_if also passed to phy_connect()? So you are going
to end up with both the MAC and the PHY inserting RGMII delays, and it
not working.
No. This logic not changed comparing to how it was.
* "rgmii" (RX and TX delays are added by the MAC when required)
rgmii_id = 0 --> CPSW: 0 : Internal Delay, PHY - no delay
* "rgmii-id" (RGMII with internal RX and TX delays provided by the PHY, the
MAC should not add the RX or TX delays in this case)
* "rgmii-rxid" (RGMII with internal RX delay provided by the PHY, the MAC
should not add an RX delay in this case)
* "rgmii-txid" (RGMII with internal TX delay provided by the PHY, the MAC
should not add an TX delay in this case)
rgmii_id = 1 --> CPSW: 1 : No Internal Delay, PHY/board - delay
You need to somehow decide if the MAC is going to do the delay, or the
PHY. But not both.
Again, this series does not change logic - only interfaces and DT.
Thank you for review.
--
regards,
-grygorii
Now that this driver can live in it's proper place in the
right
quoted
dts, you may want to consider just using standard reg
property for it instead of the syscon-scm. And also get
rid of the syscon reads and writes.
Could you help clarify how to get syscon in this case?
syscon_node_to_regmap(dev->parent->of_node)?
Hmm I don't think you need syscon at all now. You can just
ioremap the register(s) and use readl/writel and that's it.
Or use regmap without syscon if you prefer that.
The ioremap in this case should be hitting cached ranges
anyways, so no extra overhead there.
Also, there are could be more then one gmii_sel registers in SCM in the future,
so I hidden offsets in of_match data.
As result, "reg" not needed at all now.
But then you have to patch driver for various SoCs
instead of just configuring the standard reg property
in the dts file :)
Regards,
Tony
2) introduce new PHY API for network interface mode selection which will use
already defined set of modes from phy_interface_t.
Option 2 was selected for this series.
Looks good to me :) The dts files will cause merge conflicts with
what I have pending for the ti-sysc changes so please send the dts
changes in a separate series when posting without RFC.
expected. I did on top of mauster, but will rebase and resend if approved.
--
regards,
-grygorii
Now that this driver can live in it's proper place in the
right
quoted
dts, you may want to consider just using standard reg
property for it instead of the syscon-scm. And also get
rid of the syscon reads and writes.
Could you help clarify how to get syscon in this case?
syscon_node_to_regmap(dev->parent->of_node)?
Hmm I don't think you need syscon at all now. You can just
ioremap the register(s) and use readl/writel and that's it.
Or use regmap without syscon if you prefer that.
It will overlap with already remapped SCM syscon and i'd like to avoid this.
+ it seems common practice to use syscon for devices/drivers which are
child to SCM node - makes overall system more consistent.
The ioremap in this case should be hitting cached ranges
anyways, so no extra overhead there.
quoted
Also, there are could be more then one gmii_sel registers in SCM in the future,
so I hidden offsets in of_match data.
As result, "reg" not needed at all now.
But then you have to patch driver for various SoCs
instead of just configuring the standard reg property
in the dts file :)
Problem is that they are not guarantee to be standard between SoC's families
(number of regs and fields placement), as result it might require to change
driver any way for various SoCs to handle properly new fields placement.
I prefer to fix driver then fight with DT ;) as it's static for SoC family
and need to be changed only once when new SoC family introduced.
--
regards,
-grygorii
Now that this driver can live in it's proper place in the
right
quoted
dts, you may want to consider just using standard reg
property for it instead of the syscon-scm. And also get
rid of the syscon reads and writes.
Could you help clarify how to get syscon in this case?
syscon_node_to_regmap(dev->parent->of_node)?
Hmm I don't think you need syscon at all now. You can just
ioremap the register(s) and use readl/writel and that's it.
Or use regmap without syscon if you prefer that.
It will overlap with already remapped SCM syscon and i'd like to avoid this.
+ it seems common practice to use syscon for devices/drivers which are
child to SCM node - makes overall system more consistent.
Well it was just set up with syscon in deperation earlier with
drivers just blindly mapping registers outside of their
range..
quoted
The ioremap in this case should be hitting cached ranges
anyways, so no extra overhead there.
quoted
Also, there are could be more then one gmii_sel registers in SCM in the future,
so I hidden offsets in of_match data.
As result, "reg" not needed at all now.
But then you have to patch driver for various SoCs
instead of just configuring the standard reg property
in the dts file :)
Problem is that they are not guarantee to be standard between SoC's families
(number of regs and fields placement), as result it might require to change
driver any way for various SoCs to handle properly new fields placement.
I prefer to fix driver then fight with DT ;) as it's static for SoC family
and need to be changed only once when new SoC family introduced.
Fine with me, that can be changed later too no problem.
Regards,
Tony
On 10/09/2018 12:22 AM, Kishon Vijay Abraham I wrote:
Hi Grygorii,
On Tuesday 09 October 2018 05:19 AM, Grygorii Strashko wrote:
quoted
Add new API phy_set_netif_mode(struct phy *phy, phy_interface_t mode) and
new PHY operation callback .set_netif_mode() which intended to be implemnte
by PHY drivers which supports Network interrfaces mode selection. Both
accepts phy_interface_t vlaue as input parameter.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/phy/phy-core.c | 15 +++++++++++++++
include/linux/phy/phy.h | 12 ++++++++++++
2 files changed, 27 insertions(+)
above introduces ugly constants duplication and required every network phy driver
to maintain conversation table phy_interface_t -> enum phy_mode.
More over, if above change happens third time (first time PHY_MODE_SGMII/PHY_MODE_10GKR were added,
second - PHY_MODE_2500SGMII) it will never ends (there are ~15 more items only in phy_interface_t).
As result, enum phy_mode might became a un-maintainable monster.
So, as per above, and considering that Network subsystem is based on standards (phy_interface_t lists standard intf)
I've tried to add separate PHY API.
As an idea:
- seems it could be reasonable to introduce PHY_MODE_NETWORK (or PHY_MODE_ETHERNET) and
add generic phy_set_submode(struct phy *phy, long submode).
So, single functional PHY device can just use phy_set_submode() and
multi-functional devices (like serdes which can be muxed between PCIe, USB, NET), can use:
phy_set_mode(PHY_MODE_ETHERNET)
phy_set_submode(X);
Any way, if you still agree to just add new above phy_modes - i'll redo patches.
--
regards,
-grygorii
Now that this driver can live in it's proper place in the
right
quoted
dts, you may want to consider just using standard reg
property for it instead of the syscon-scm. And also get
rid of the syscon reads and writes.
Could you help clarify how to get syscon in this case?
syscon_node_to_regmap(dev->parent->of_node)?
Also, there are could be more then one gmii_sel registers in SCM in the future,
so I hidden offsets in of_match data.
As result, "reg" not needed at all now.
If there's a defined register range which doesn't overlap with other
things (other than the parent), then use reg whether you currently need
it or not.
Rob
From: Rob Herring <robh@kernel.org> Date: 2018-10-17 15:41:17
On Mon, Oct 08, 2018 at 06:49:42PM -0500, Grygorii Strashko wrote:
quoted hunk
The cpsw-phy-sel driver was replaced with new PHY driver phy-gmii-sel, so
deprecate cpsw-phy-sel bindings and update CPSW binding to use phy-gmii-sel
PHY bindings.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
@@ -22,7 +22,8 @@ Required properties: - cpsw-phy-sel : Specifies the phandle to the CPSW phy mode selection device. See also cpsw-phy-sel.txt for it's binding. Note that in legacy cases cpsw-phy-sel may be- a child device instead of a phandle.+ a child device instead of a phandle+ (DEPRECATED, use phy-gmii-sel PHY phandle).
phy-gmii-sel is outside the scope of this binding. Just say use 'phys'
property instead.
quoted hunk
Optional properties:
- ti,hwmods : Must be "cpgmac0"
@@ -44,6 +45,7 @@ Optional properties: Slave Properties: Required properties: - phy-mode : See ethernet.txt file in the same directory+- phys : phandle on phy-gmii-sel PHY (see phy/ti-phy-gmii-sel.txt) Optional properties: - dual_emac_res_vlan : Specifies VID to be used to segregate the ports
From: Rob Herring <robh@kernel.org> Date: 2018-10-17 15:41:58
On Mon, 8 Oct 2018 18:49:48 -0500, Grygorii Strashko wrote:
The cpsw-phy-sel driver was replaced with new PHY driver phy-gmii-sel, so
deprecate cpsw-phy-sel bindings.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
Documentation/devicetree/bindings/net/cpsw-phy-sel.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Kishon Vijay Abraham I <hidden> Date: 2018-10-25 10:06:31
Hi,
On Wednesday 10 October 2018 04:13 AM, Grygorii Strashko wrote:
quoted hunk
On 10/09/2018 12:22 AM, Kishon Vijay Abraham I wrote:
quoted
Hi Grygorii,
On Tuesday 09 October 2018 05:19 AM, Grygorii Strashko wrote:
quoted
Add new API phy_set_netif_mode(struct phy *phy, phy_interface_t mode) and
new PHY operation callback .set_netif_mode() which intended to be implemnte
by PHY drivers which supports Network interrfaces mode selection. Both
accepts phy_interface_t vlaue as input parameter.
Cc: Kishon Vijay Abraham I <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/phy/phy-core.c | 15 +++++++++++++++
include/linux/phy/phy.h | 12 ++++++++++++
2 files changed, 27 insertions(+)
above introduces ugly constants duplication and required every network phy driver
to maintain conversation table phy_interface_t -> enum phy_mode.
More over, if above change happens third time (first time PHY_MODE_SGMII/PHY_MODE_10GKR were added,
second - PHY_MODE_2500SGMII) it will never ends (there are ~15 more items only in phy_interface_t).
As result, enum phy_mode might became a un-maintainable monster.
So, as per above, and considering that Network subsystem is based on standards (phy_interface_t lists standard intf)
I've tried to add separate PHY API.
As an idea:
- seems it could be reasonable to introduce PHY_MODE_NETWORK (or PHY_MODE_ETHERNET) and
add generic phy_set_submode(struct phy *phy, long submode).
So, single functional PHY device can just use phy_set_submode() and
multi-functional devices (like serdes which can be muxed between PCIe, USB, NET), can use:
phy_set_mode(PHY_MODE_ETHERNET)
phy_set_submode(X);
Agreed on the constant duplication comment above. We can modify set_mode to
take submode as an additional parameter and fix all the users of phy_set_mode.
int phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
Thanks
Kishon