From 12775af50549121ade8efbdcf3612b867188ea0b Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 6 Jun 2019 19:30:38 +0300 Subject: [PATCH 1/4] dt-bindings: doc: net: keystone-netcp: document cpts The Keystone 2 66AK2HK/E/L 1G Ethernet Switch Subsystems contains The Common Platform Time Sync (CPTS) module which is in general compatible with CPTS module found on "legacy" TI AM3/4/5 SoCs. So, the basic support for Keystone 2 CPTS is available by default, but not documented. The Keystone 2 CPTS module supports also some additional features like time sync reference (RFTCLK) clock selection through CPTS_RFTCLK_SEL register (offset: x08) in CPTS module, which is modelled as multiplexer clock. This patch adds missed binding documentation for Keystone 2 66AK2HK/E/L CPTS module. Signed-off-by: Grygorii Strashko Acked-by: Richard Cochran Signed-off-by: David S. Miller --- .../bindings/net/keystone-netcp.txt | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Documentation/devicetree/bindings/net/keystone-netcp.txt b/Documentation/devicetree/bindings/net/keystone-netcp.txt index 6262c2f293b0..24f11e042f8d 100644 --- a/Documentation/devicetree/bindings/net/keystone-netcp.txt +++ b/Documentation/devicetree/bindings/net/keystone-netcp.txt @@ -104,6 +104,23 @@ Required properties: - 10Gb mac<->mac forced mode : 11 ----phy-handle: phandle to PHY device +- cpts: sub-node time synchronization (CPTS) submodule configuration +-- clocks: CPTS reference clock. Should point on cpts-refclk-mux clock. +-- clock-names: should be "cpts" +-- cpts-refclk-mux: multiplexer clock definition sub-node for CPTS reference (RFTCLK) clock +--- #clock-cells: should be 0 +--- clocks: list of CPTS reference (RFTCLK) clock's parents as defined in Data manual +--- ti,mux-tbl: array of multiplexer indexes as defined in Data manual +--- assigned-clocks: should point on cpts-refclk-mux clock +--- assigned-clock-parents: should point on required RFTCLK clock parent to be selected +-- cpts_clock_mult: (optional) Numerator to convert input clock ticks + into nanoseconds +-- cpts_clock_shift: (optional) Denominator to convert input clock ticks into + nanoseconds. + Mult and shift will be calculated basing on CPTS + rftclk frequency if both cpts_clock_shift and + cpts_clock_mult properties are not provided. + Optional properties: - enable-ale: NetCP driver keeps the address learning feature in the ethernet switch module disabled. This attribute is to enable the address @@ -168,6 +185,23 @@ netcp: netcp@2000000 { tx-queue = <648>; tx-channel = <8>; + cpts { + clocks = <&cpts_refclk_mux>; + clock-names = "cpts"; + + cpts_refclk_mux: cpts-refclk-mux { + #clock-cells = <0>; + clocks = <&chipclk12>, <&chipclk13>, + <&timi0>, <&timi1>, + <&tsipclka>, <&tsrefclk>, + <&tsipclkb>; + ti,mux-tbl = <0x0>, <0x1>, <0x2>, + <0x3>, <0x4>, <0x8>, <0xC>; + assigned-clocks = <&cpts_refclk_mux>; + assigned-clock-parents = <&chipclk12>; + }; + }; + interfaces { gbe0: interface-0 { slave-port = <0>; @@ -219,3 +253,13 @@ netcp: netcp@2000000 { }; }; }; + +CPTS board configuration - select external CPTS RFTCLK: + +&tsrefclk{ + clock-frequency = <500000000>; +}; + +&cpts_refclk_mux { + assigned-clock-parents = <&tsrefclk>; +}; From 8a6389a515f406a89a1a69c267fbc712cdd9e8e9 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 6 Jun 2019 19:30:39 +0300 Subject: [PATCH 2/4] net: ethernet: ti: cpts: use devm_get_clk_from_child Use devm_get_clk_from_child() instead of devm_clk_get() and this way allow to group CPTS DT properties in sub-node for better code readability and maintenance. Roll-back to devm_clk_get() if devm_get_clk_from_child() fails for backward compatibility. Signed-off-by: Grygorii Strashko Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpts.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index e257018ada71..0e79f9743c19 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -572,9 +572,14 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs, if (ret) return ERR_PTR(ret); - cpts->refclk = devm_clk_get(dev, "cpts"); + cpts->refclk = devm_get_clk_from_child(dev, node, "cpts"); + if (IS_ERR(cpts->refclk)) + /* try get clk from dev node for compatibility */ + cpts->refclk = devm_clk_get(dev, "cpts"); + if (IS_ERR(cpts->refclk)) { - dev_err(dev, "Failed to get cpts refclk\n"); + dev_err(dev, "Failed to get cpts refclk %ld\n", + PTR_ERR(cpts->refclk)); return ERR_CAST(cpts->refclk); } From c8ad14514302e68992899b42fea21dedce0d135e Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 6 Jun 2019 19:30:40 +0300 Subject: [PATCH 3/4] net: ethernet: ti: netcp_ethss: add support for child cpts node Allow to place CPTS properties in the child "cpts" DT node. For backward compatibility - roll-back and read CPTS DT properties from parent node if "cpts" node is not present. Signed-off-by: Grygorii Strashko Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/netcp_ethss.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index ec179700c184..2c1fac33136c 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -3554,7 +3554,7 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, struct device_node *node, void **inst_priv) { - struct device_node *interfaces, *interface; + struct device_node *interfaces, *interface, *cpts_node; struct device_node *secondary_ports; struct cpsw_ale_params ale_params; struct gbe_priv *gbe_dev; @@ -3713,7 +3713,12 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n"); } - gbe_dev->cpts = cpts_create(gbe_dev->dev, gbe_dev->cpts_reg, node); + cpts_node = of_get_child_by_name(node, "cpts"); + if (!cpts_node) + cpts_node = of_node_get(node); + + gbe_dev->cpts = cpts_create(gbe_dev->dev, gbe_dev->cpts_reg, cpts_node); + of_node_put(cpts_node); if (IS_ENABLED(CONFIG_TI_CPTS) && IS_ERR(gbe_dev->cpts)) { ret = PTR_ERR(gbe_dev->cpts); goto free_sec_ports; From a3047a81ba1359dc6b02b9dcebc4161800de2c47 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 6 Jun 2019 19:30:41 +0300 Subject: [PATCH 4/4] net: ethernet: ti: cpts: add support for ext rftclk selection Some CPTS instances, which can be found on KeyStone 2 1G Ethernet Switch Subsystems, can control an external multiplexer that selects one of up to 32 clocks as time sync reference (RFTCLK) clock. This feature can be configured through CPTS_RFTCLK_SEL register (offset: x08) in CPTS module and can be represented as multiplexer clock. Hence, introduce support for optional cpts-refclk-mux clock, which, once defined will allow to select required CPTS RFTCLK by using assigned-clock-parents DT property in board files. Signed-off-by: Grygorii Strashko Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpts.c | 79 +++++++++++++++++++++++++++++++++- drivers/net/ethernet/ti/cpts.h | 2 +- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index 0e79f9743c19..61136428e2c0 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -5,6 +5,7 @@ * Copyright (C) 2012 Richard Cochran * */ +#include #include #include #include @@ -532,6 +533,82 @@ static void cpts_calc_mult_shift(struct cpts *cpts) freq, cpts->cc.mult, cpts->cc.shift, (ns - NSEC_PER_SEC)); } +static int cpts_of_mux_clk_setup(struct cpts *cpts, struct device_node *node) +{ + struct device_node *refclk_np; + const char **parent_names; + unsigned int num_parents; + struct clk_hw *clk_hw; + int ret = -EINVAL; + u32 *mux_table; + + refclk_np = of_get_child_by_name(node, "cpts-refclk-mux"); + if (!refclk_np) + /* refclk selection supported not for all SoCs */ + return 0; + + num_parents = of_clk_get_parent_count(refclk_np); + if (num_parents < 1) { + dev_err(cpts->dev, "mux-clock %s must have parents\n", + refclk_np->name); + goto mux_fail; + } + + parent_names = devm_kzalloc(cpts->dev, (sizeof(char *) * num_parents), + GFP_KERNEL); + + mux_table = devm_kzalloc(cpts->dev, sizeof(*mux_table) * num_parents, + GFP_KERNEL); + if (!mux_table || !parent_names) { + ret = -ENOMEM; + goto mux_fail; + } + + of_clk_parent_fill(refclk_np, parent_names, num_parents); + + ret = of_property_read_variable_u32_array(refclk_np, "ti,mux-tbl", + mux_table, + num_parents, num_parents); + if (ret < 0) + goto mux_fail; + + clk_hw = clk_hw_register_mux_table(cpts->dev, refclk_np->name, + parent_names, num_parents, + 0, + &cpts->reg->rftclk_sel, 0, 0x1F, + 0, mux_table, NULL); + if (IS_ERR(clk_hw)) { + ret = PTR_ERR(clk_hw); + goto mux_fail; + } + + ret = devm_add_action_or_reset(cpts->dev, + (void(*)(void *))clk_hw_unregister_mux, + clk_hw); + if (ret) { + dev_err(cpts->dev, "add clkmux unreg action %d", ret); + goto mux_fail; + } + + ret = of_clk_add_hw_provider(refclk_np, of_clk_hw_simple_get, clk_hw); + if (ret) + goto mux_fail; + + ret = devm_add_action_or_reset(cpts->dev, + (void(*)(void *))of_clk_del_provider, + refclk_np); + if (ret) { + dev_err(cpts->dev, "add clkmux provider unreg action %d", ret); + goto mux_fail; + } + + return ret; + +mux_fail: + of_node_put(refclk_np); + return ret; +} + static int cpts_of_parse(struct cpts *cpts, struct device_node *node) { int ret = -EINVAL; @@ -547,7 +624,7 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node) (!cpts->cc.mult && cpts->cc.shift)) goto of_error; - return 0; + return cpts_of_mux_clk_setup(cpts, node); of_error: dev_err(cpts->dev, "CPTS: Missing property in the DT.\n"); diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h index 024aab6af12f..bb997c11ee15 100644 --- a/drivers/net/ethernet/ti/cpts.h +++ b/drivers/net/ethernet/ti/cpts.h @@ -24,7 +24,7 @@ struct cpsw_cpts { u32 idver; /* Identification and version */ u32 control; /* Time sync control */ - u32 res1; + u32 rftclk_sel; /* Reference Clock Select Register */ u32 ts_push; /* Time stamp event push */ u32 ts_load_val; /* Time stamp load value */ u32 ts_load_en; /* Time stamp load enable */