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:
- 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>;
};
......@@ -5,6 +5,7 @@
* Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
*
*/
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/if.h>
#include <linux/hrtimer.h>
......@@ -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");
......@@ -572,9 +649,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);
}
......
......@@ -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 */
......
......@@ -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;
......
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