Commit 900d96e4 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-ethernet-ti-netcp-update-and-enable-cpts-support'

Grygorii Strashko says:

====================
net: ethernet: ti: netcp: update and enable cpts support

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 TI AM3/4/5 SoCs. So, the basic support for
Keystone 2 CPTS is available by default, but not documented and has never been
enabled inconfig files.

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 can modelled as multiplexer clock
(this was discussed some time ago [1]).

This series adds missed binding documentation for Keystone 2 66AK2HK/E/L
CPTS module and enables CPTS for TI Keystone 2 66AK2HK/E/L SoCs with possiblity
to select CPTS reference clock.

Patch 1: adds the CPTS binding documentation. CPTS bindings are defined in the
way that allows CPTS properties to be grouped under "cpts" sub-node.
It also defines "cpts-refclk-mux" clock for CPTS RFTCLK selection.
Patches 2-3: implement CPTS properties grouping under "cpts" sub-node with
backward compatibility support.
Patch 4: adds support for time sync reference (RFTCLK) clock selection from DT
by adding support for "cpts-refclk-mux" multiplexer clock.
Patches 5-9: DT CPTS nodes update for TI Keystone 2 66AK2HK/E/L SoCs.
Patch 10: enables CPTS for TI Keystone 2 66AK2HK/E/L SoCs.

I grouped all patches in one series for better illustration of the changes,
but in general Pateches 1-4 are netdev matarieal (first) and other patches
are platform specific.

Series can be found at:
 git@git.ti.com:~gragst/ti-linux-kernel/gragsts-ti-linux-kernel.git
branch:
 net-next-k2e-cpts-refclk

Changes in v2:
 - do reverse christmas tree in cpts_of_mux_clk_setup()
 - add ack from Richard Cochran

v1: https://lkml.org/lkml/2019/6/1/77

[1] https://www.spinics.net/lists/netdev/msg408931.html
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8d94a873 a3047a81
...@@ -104,6 +104,23 @@ Required properties: ...@@ -104,6 +104,23 @@ Required properties:
- 10Gb mac<->mac forced mode : 11 - 10Gb mac<->mac forced mode : 11
----phy-handle: phandle to PHY device ----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: Optional properties:
- enable-ale: NetCP driver keeps the address learning feature in the ethernet - enable-ale: NetCP driver keeps the address learning feature in the ethernet
switch module disabled. This attribute is to enable the address switch module disabled. This attribute is to enable the address
...@@ -168,6 +185,23 @@ netcp: netcp@2000000 { ...@@ -168,6 +185,23 @@ netcp: netcp@2000000 {
tx-queue = <648>; tx-queue = <648>;
tx-channel = <8>; 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 { interfaces {
gbe0: interface-0 { gbe0: interface-0 {
slave-port = <0>; slave-port = <0>;
...@@ -219,3 +253,13 @@ netcp: netcp@2000000 { ...@@ -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>;
};
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com> * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
* *
*/ */
#include <linux/clk-provider.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/hrtimer.h> #include <linux/hrtimer.h>
...@@ -532,6 +533,82 @@ static void cpts_calc_mult_shift(struct cpts *cpts) ...@@ -532,6 +533,82 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
freq, cpts->cc.mult, cpts->cc.shift, (ns - NSEC_PER_SEC)); 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) static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
{ {
int ret = -EINVAL; int ret = -EINVAL;
...@@ -547,7 +624,7 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node) ...@@ -547,7 +624,7 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
(!cpts->cc.mult && cpts->cc.shift)) (!cpts->cc.mult && cpts->cc.shift))
goto of_error; goto of_error;
return 0; return cpts_of_mux_clk_setup(cpts, node);
of_error: of_error:
dev_err(cpts->dev, "CPTS: Missing property in the DT.\n"); dev_err(cpts->dev, "CPTS: Missing property in the DT.\n");
...@@ -572,9 +649,14 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs, ...@@ -572,9 +649,14 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
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"); cpts->refclk = devm_clk_get(dev, "cpts");
if (IS_ERR(cpts->refclk)) { 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); return ERR_CAST(cpts->refclk);
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
struct cpsw_cpts { struct cpsw_cpts {
u32 idver; /* Identification and version */ u32 idver; /* Identification and version */
u32 control; /* Time sync control */ u32 control; /* Time sync control */
u32 res1; u32 rftclk_sel; /* Reference Clock Select Register */
u32 ts_push; /* Time stamp event push */ u32 ts_push; /* Time stamp event push */
u32 ts_load_val; /* Time stamp load value */ u32 ts_load_val; /* Time stamp load value */
u32 ts_load_en; /* Time stamp load enable */ u32 ts_load_en; /* Time stamp load enable */
......
...@@ -3554,7 +3554,7 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, ...@@ -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, static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
struct device_node *node, void **inst_priv) 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 device_node *secondary_ports;
struct cpsw_ale_params ale_params; struct cpsw_ale_params ale_params;
struct gbe_priv *gbe_dev; struct gbe_priv *gbe_dev;
...@@ -3713,7 +3713,12 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *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"); 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)) { if (IS_ENABLED(CONFIG_TI_CPTS) && IS_ERR(gbe_dev->cpts)) {
ret = PTR_ERR(gbe_dev->cpts); ret = PTR_ERR(gbe_dev->cpts);
goto free_sec_ports; goto free_sec_ports;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment