mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-14 19:06:39 +07:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
900d96e418
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user