[U-Boot] [PATCH 00/14] net: ti: icssg: Add prueth support

The series adds support for icssg_prueth functionality on u-boot. This series is based on top of master branch. rproc init needs to be done from uboot command prompt. The pru/rtu firmware loading is done by prueth driver soon after config paramters are setup.
Currently only slice0/1 of icssg2 instance on am6-evm is supported. i.e Both slices of icssg2 instance are supported.
On u-boot prompt following commands to test icssg2_port 0 on am654-evm:
setenv ethact pruss2_eth; setenv serverip 172.24.191.45; fatload mmc 1 ${pru0loadaddr} am65x-pru0-prueth-fw.elf; fatload mmc 1 ${rtu0loadaddr} am65x-rtu0-prueth-fw.elf; rproc init; setenv autoload no; dhcp; tftp 0x82000000 Image; tftp 0x83000000 k3-am654-base-board.dtb; booti 0x82000000 - 0x83000000
This tests tftp on prueth.
Note: Uboot ethernet driver architecture supports once instance per probe. So only one of the ports are supported per instance. So DT of prueth node should have either ethernet-mii0 or ethernet-mii1.
Keerthy (14): net: eth-uclass: eth_get_dev based on SEQ_ALIAS instead of probe order net: eth-uclass: call stop only for active devices misc: uclass: Introduce misc_init_by_ofnode soc: ti: pruss: add a misc driver for PRUSS in TI SoCs remoteproc: pruss: add PRU remoteproc driver net: ti: icssg-prueth: Add ICSSG ethernet driver net: ti: icssg-prueth: Workaround to shutdown the prueth firmware arm: dts: k3-am65-main: Add msmc_ram node arm: dts: k3-am654-base-board-u-boot: Add icssg specific msmc_ram carveout nodes arm: dts: k3-am65-main: Add scm_conf node arm: dts: k3-am65-main: Add pruss nodes for ICSSG2 arm64: dts: ti: am654-base-board: add ICSSG2 Ethernet support configs: am65x_evm_a53_defconfig: Enable CONFIG_REMOTEPROC_TI_PRU configs: am65x_evm_a53_defconfig: Enable CONFIG_CMD_REMOTEPROC
arch/arm/dts/k3-am65-main.dtsi | 212 ++++++++ arch/arm/dts/k3-am65.dtsi | 4 +- arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 130 +++++ configs/am65x_evm_a53_defconfig | 5 + drivers/misc/misc-uclass.c | 25 + drivers/net/ti/Kconfig | 8 + drivers/net/ti/Makefile | 1 + drivers/net/ti/icssg-prueth.c | 525 +++++++++++++++++++ drivers/net/ti/icssg.h | 31 ++ drivers/net/ti/icssg_classifier.c | 397 ++++++++++++++ drivers/remoteproc/Kconfig | 11 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/pru_rproc.c | 384 ++++++++++++++ drivers/soc/ti/Kconfig | 13 + drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 143 +++++ include/misc.h | 9 + include/ti-pruss.h | 13 + net/eth-uclass.c | 7 +- 19 files changed, 1916 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ti/icssg-prueth.c create mode 100644 drivers/net/ti/icssg.h create mode 100644 drivers/net/ti/icssg_classifier.c create mode 100644 drivers/remoteproc/pru_rproc.c create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/ti-pruss.h

In case of multiple eth interfaces currently eth_get_dev fetches the device based on the probe order which can be random hence try with the alias.
Signed-off-by: Keerthy j-keerthy@ti.com --- net/eth-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 031d558625..f11c307b8c 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -68,8 +68,8 @@ struct udevice *eth_get_dev(void)
uc_priv = eth_get_uclass_priv(); if (!uc_priv->current) - eth_errno = uclass_first_device(UCLASS_ETH, - &uc_priv->current); + eth_errno = uclass_get_device_by_seq(UCLASS_ETH, + 0, &uc_priv->current); return uc_priv->current; }

On Tue, Aug 06, 2019 at 04:08:31PM +0530, Keerthy wrote:
In case of multiple eth interfaces currently eth_get_dev fetches the device based on the probe order which can be random hence try with the alias.
Signed-off-by: Keerthy j-keerthy@ti.com
net/eth-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 031d558625..f11c307b8c 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -68,8 +68,8 @@ struct udevice *eth_get_dev(void)
uc_priv = eth_get_uclass_priv(); if (!uc_priv->current)
eth_errno = uclass_first_device(UCLASS_ETH,
&uc_priv->current);
eth_errno = uclass_get_device_by_seq(UCLASS_ETH,
return uc_priv->current;0, &uc_priv->current);
}
This breaks networking on qemu_arm / qemu_arm64 and no networking device is found.

On 10/25/2019 5:35 PM, Tom Rini wrote:
On Tue, Aug 06, 2019 at 04:08:31PM +0530, Keerthy wrote:
In case of multiple eth interfaces currently eth_get_dev fetches the device based on the probe order which can be random hence try with the alias.
Signed-off-by: Keerthy j-keerthy@ti.com
net/eth-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 031d558625..f11c307b8c 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -68,8 +68,8 @@ struct udevice *eth_get_dev(void)
uc_priv = eth_get_uclass_priv(); if (!uc_priv->current)
eth_errno = uclass_first_device(UCLASS_ETH,
&uc_priv->current);
eth_errno = uclass_get_device_by_seq(UCLASS_ETH,
return uc_priv->current; }0, &uc_priv->current);
This breaks networking on qemu_arm / qemu_arm64 and no networking device is found.
Okay. That is pretty strange. So seems like uclass_get_device_by_seq is failing for some reason.

On 25/10/19 10:23 PM, keerthy wrote:
On 10/25/2019 5:35 PM, Tom Rini wrote:
On Tue, Aug 06, 2019 at 04:08:31PM +0530, Keerthy wrote:
In case of multiple eth interfaces currently eth_get_dev fetches the device based on the probe order which can be random hence try with the alias.
Signed-off-by: Keerthy j-keerthy@ti.com
net/eth-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 031d558625..f11c307b8c 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -68,8 +68,8 @@ struct udevice *eth_get_dev(void) uc_priv = eth_get_uclass_priv(); if (!uc_priv->current) - eth_errno = uclass_first_device(UCLASS_ETH, - &uc_priv->current); + eth_errno = uclass_get_device_by_seq(UCLASS_ETH, + 0, &uc_priv->current); return uc_priv->current; }
This breaks networking on qemu_arm / qemu_arm64 and no networking device is found.
Okay. That is pretty strange. So seems like uclass_get_device_by_seq is failing for some reason.
because not everyone populates aliases. You can do something like below:
eth_errno = uclass_get_device_by_seq(UCLASS_ETH, 0, &uc_priv->current); if (eth_errno || !uc_priv->current) eth_errno = uclass_first_device(UCLASS_ETH, &uc_priv->current);
Thanks and regards, Lokesh

On 10/29/2019 2:33 PM, Lokesh Vutla wrote:
On 25/10/19 10:23 PM, keerthy wrote:
On 10/25/2019 5:35 PM, Tom Rini wrote:
On Tue, Aug 06, 2019 at 04:08:31PM +0530, Keerthy wrote:
In case of multiple eth interfaces currently eth_get_dev fetches the device based on the probe order which can be random hence try with the alias.
Signed-off-by: Keerthy j-keerthy@ti.com
net/eth-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 031d558625..f11c307b8c 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -68,8 +68,8 @@ struct udevice *eth_get_dev(void) uc_priv = eth_get_uclass_priv(); if (!uc_priv->current) - eth_errno = uclass_first_device(UCLASS_ETH, - &uc_priv->current); + eth_errno = uclass_get_device_by_seq(UCLASS_ETH, + 0, &uc_priv->current); return uc_priv->current; }
This breaks networking on qemu_arm / qemu_arm64 and no networking device is found.
Okay. That is pretty strange. So seems like uclass_get_device_by_seq is failing for some reason.
because not everyone populates aliases. You can do something like below:
eth_errno = uclass_get_device_by_seq(UCLASS_ETH, 0, &uc_priv->current); if (eth_errno || !uc_priv->current) eth_errno = uclass_first_device(UCLASS_ETH, &uc_priv->current);
Thanks Lokesh. I will add that check.
Thanks and regards, Lokesh

Currently stop is being called unconditionally without even checking if start is called which will result in crash where multiple instances are present and stop gets called even without calling start.
Signed-off-by: Keerthy j-keerthy@ti.com --- net/eth-uclass.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index f11c307b8c..58d6f26e04 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -557,7 +557,8 @@ static int eth_pre_remove(struct udevice *dev) { struct eth_pdata *pdata = dev->platdata;
- eth_get_ops(dev)->stop(dev); + if (eth_is_active(dev)) + eth_get_ops(dev)->stop(dev);
/* clear the MAC address */ memset(pdata->enetaddr, 0, ARP_HLEN);

Introduce misc_init_by_ofnode to probe a misc device using its ofnode.
Signed-off-by: Keerthy j-keerthy@ti.com --- drivers/misc/misc-uclass.c | 25 +++++++++++++++++++++++++ include/misc.h | 9 +++++++++ 2 files changed, 34 insertions(+)
diff --git a/drivers/misc/misc-uclass.c b/drivers/misc/misc-uclass.c index 55381edc98..835d3f7118 100644 --- a/drivers/misc/misc-uclass.c +++ b/drivers/misc/misc-uclass.c @@ -5,6 +5,8 @@
#include <common.h> #include <dm.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> #include <errno.h> #include <misc.h>
@@ -65,6 +67,29 @@ int misc_set_enabled(struct udevice *dev, bool val) return ops->set_enabled(dev, val); }
+int misc_init_by_ofnode(ofnode node) +{ + struct udevice *dev = NULL; + int ret; + long temp1, temp2; + + temp1 = ofnode_to_offset(node); + + for (ret = uclass_find_first_device(UCLASS_MISC, &dev); dev; + ret = uclass_find_next_device(&dev)) { + temp2 = ofnode_to_offset(dev_ofnode(dev)); + if (temp1 == temp2) { + ret = device_probe(dev); + if (ret) + debug("%s: Failed to initialize - %d\n", + dev->name, ret); + return ret; + } + } + + return -ENODEV; +} + UCLASS_DRIVER(misc) = { .id = UCLASS_MISC, .name = "misc", diff --git a/include/misc.h b/include/misc.h index 12d1325ee2..79263ed480 100644 --- a/include/misc.h +++ b/include/misc.h @@ -76,6 +76,15 @@ int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size, */ int misc_set_enabled(struct udevice *dev, bool val);
+/** + * misc_init_by_ofnode() - Probe a misc device by using ofnode. + * @node: ofnode of the misc device. + * + * A misc device is probed using ofnode. + * + * Return: -ve on error, 0 on success + */ +int misc_init_by_ofnode(ofnode node); /* * struct misc_ops - Driver model Misc operations *

On Tue, Aug 06, 2019 at 04:08:33PM +0530, Keerthy wrote:
Introduce misc_init_by_ofnode to probe a misc device using its ofnode.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/misc/misc-uclass.c | 25 +++++++++++++++++++++++++ include/misc.h | 9 +++++++++ 2 files changed, 34 insertions(+)
diff --git a/drivers/misc/misc-uclass.c b/drivers/misc/misc-uclass.c index 55381edc98..835d3f7118 100644 --- a/drivers/misc/misc-uclass.c +++ b/drivers/misc/misc-uclass.c @@ -5,6 +5,8 @@
#include <common.h> #include <dm.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> #include <errno.h> #include <misc.h>
@@ -65,6 +67,29 @@ int misc_set_enabled(struct udevice *dev, bool val) return ops->set_enabled(dev, val); }
+int misc_init_by_ofnode(ofnode node) +{
- struct udevice *dev = NULL;
- int ret;
- long temp1, temp2;
- temp1 = ofnode_to_offset(node);
- for (ret = uclass_find_first_device(UCLASS_MISC, &dev); dev;
ret = uclass_find_next_device(&dev)) {
temp2 = ofnode_to_offset(dev_ofnode(dev));
if (temp1 == temp2) {
ret = device_probe(dev);
if (ret)
debug("%s: Failed to initialize - %d\n",
Doesn't that put a 'minus' in front of an already negative number? Might look more confusing than it needs to be. I've often seen the formatting specifier for errors be like "...(%d)...".
dev->name, ret);
return ret;
}
- }
- return -ENODEV;
+}
UCLASS_DRIVER(misc) = { .id = UCLASS_MISC, .name = "misc", diff --git a/include/misc.h b/include/misc.h index 12d1325ee2..79263ed480 100644 --- a/include/misc.h +++ b/include/misc.h @@ -76,6 +76,15 @@ int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size, */ int misc_set_enabled(struct udevice *dev, bool val);
+/**
- misc_init_by_ofnode() - Probe a misc device by using ofnode.
- @node: ofnode of the misc device.
- A misc device is probed using ofnode.
- Return: -ve on error, 0 on success
- */
+int misc_init_by_ofnode(ofnode node);
Missing blank line here.
-- Andreas Dannenberg Texas Instruments Inc
/*
- struct misc_ops - Driver model Misc operations
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

Hi Keerthy,
On Tue, 6 Aug 2019 at 04:38, Keerthy j-keerthy@ti.com wrote:
Introduce misc_init_by_ofnode to probe a misc device using its ofnode.
What is the purpose of this? All patches should have a motivation.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/misc/misc-uclass.c | 25 +++++++++++++++++++++++++ include/misc.h | 9 +++++++++ 2 files changed, 34 insertions(+)
diff --git a/drivers/misc/misc-uclass.c b/drivers/misc/misc-uclass.c index 55381edc98..835d3f7118 100644 --- a/drivers/misc/misc-uclass.c +++ b/drivers/misc/misc-uclass.c @@ -5,6 +5,8 @@
#include <common.h> #include <dm.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> #include <errno.h> #include <misc.h>
@@ -65,6 +67,29 @@ int misc_set_enabled(struct udevice *dev, bool val) return ops->set_enabled(dev, val); }
+int misc_init_by_ofnode(ofnode node) +{
struct udevice *dev = NULL;
int ret;
long temp1, temp2;
temp1 = ofnode_to_offset(node);
Why convert to offset? Can you just compare the node?
for (ret = uclass_find_first_device(UCLASS_MISC, &dev); dev;
ret = uclass_find_next_device(&dev)) {
uclass_foreach_dev(dev, UCLASS_MISC) {
temp2 = ofnode_to_offset(dev_ofnode(dev));
Again hopefully you can avoid this conversion. It won't work with livetree.
if (temp1 == temp2) {
ret = device_probe(dev);
Hmm can you use uclass_foreach_dev_probe() above instead?
if (ret)
debug("%s: Failed to initialize - %d\n",
dev->name, ret);
return ret;
}
}
return -ENODEV;
+}
UCLASS_DRIVER(misc) = { .id = UCLASS_MISC, .name = "misc", diff --git a/include/misc.h b/include/misc.h index 12d1325ee2..79263ed480 100644 --- a/include/misc.h +++ b/include/misc.h @@ -76,6 +76,15 @@ int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size, */ int misc_set_enabled(struct udevice *dev, bool val);
+/**
- misc_init_by_ofnode() - Probe a misc device by using ofnode.
- @node: ofnode of the misc device.
- A misc device is probed using ofnode.
- Return: -ve on error, 0 on success
- */
+int misc_init_by_ofnode(ofnode node); /*
- struct misc_ops - Driver model Misc operations
-- 2.17.1

On 13/08/19 3:04 PM, Simon Glass wrote:
Hi Keerthy,
On Tue, 6 Aug 2019 at 04:38, Keerthy j-keerthy@ti.com wrote:
Introduce misc_init_by_ofnode to probe a misc device using its ofnode.
What is the purpose of this? All patches should have a motivation.
Okay. I will add more details in the commit log. In my case pruss which is the pru subsystem which is a misc device needs to be probed before pru device which is an rproc class device. I will try to figure out a cleaner way if it exists.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/misc/misc-uclass.c | 25 +++++++++++++++++++++++++ include/misc.h | 9 +++++++++ 2 files changed, 34 insertions(+)
diff --git a/drivers/misc/misc-uclass.c b/drivers/misc/misc-uclass.c index 55381edc98..835d3f7118 100644 --- a/drivers/misc/misc-uclass.c +++ b/drivers/misc/misc-uclass.c @@ -5,6 +5,8 @@
#include <common.h> #include <dm.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> #include <errno.h> #include <misc.h>
@@ -65,6 +67,29 @@ int misc_set_enabled(struct udevice *dev, bool val) return ops->set_enabled(dev, val); }
+int misc_init_by_ofnode(ofnode node) +{
struct udevice *dev = NULL;
int ret;
long temp1, temp2;
temp1 = ofnode_to_offset(node);
Why convert to offset? Can you just compare the node?
Yes okay.
for (ret = uclass_find_first_device(UCLASS_MISC, &dev); dev;
ret = uclass_find_next_device(&dev)) {
uclass_foreach_dev(dev, UCLASS_MISC) {
okay
temp2 = ofnode_to_offset(dev_ofnode(dev));
Again hopefully you can avoid this conversion. It won't work with livetree.
okay
if (temp1 == temp2) {
ret = device_probe(dev);
Hmm can you use uclass_foreach_dev_probe() above instead?
okay. I will try to figure out a cleaner way for my case.
Thanks for the review.
if (ret)
debug("%s: Failed to initialize - %d\n",
dev->name, ret);
return ret;
}
}
return -ENODEV;
+}
- UCLASS_DRIVER(misc) = { .id = UCLASS_MISC, .name = "misc",
diff --git a/include/misc.h b/include/misc.h index 12d1325ee2..79263ed480 100644 --- a/include/misc.h +++ b/include/misc.h @@ -76,6 +76,15 @@ int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size, */ int misc_set_enabled(struct udevice *dev, bool val);
+/**
- misc_init_by_ofnode() - Probe a misc device by using ofnode.
- @node: ofnode of the misc device.
- A misc device is probed using ofnode.
- Return: -ve on error, 0 on success
- */
+int misc_init_by_ofnode(ofnode node); /*
- struct misc_ops - Driver model Misc operations
-- 2.17.1

The Programmable Real-Time Unit - Industrial Communication Subsystem (PRU-ICSS) is present of various TI SoCs such as AM335x or AM437x or the AM654x family. Each SoC can have one or more PRUSS instances that may or may not be identical.
The PRUSS consists of dual 32-bit RISC cores called the Programmable Real-Time Units (PRUs), some shared, data and instruction memories, some internal peripheral modules, and an interrupt controller. The programmable nature of the PRUs provide flexibility to implement custom peripheral interfaces, fast real-time responses, or specialized data handling.
Add support for pruss driver. Currently am654x family is supported.
Signed-off-by: Keerthy j-keerthy@ti.com --- drivers/soc/ti/Kconfig | 13 ++++ drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 128 ++++++++++++++++++++++++++++++++++++++++ include/ti-pruss.h | 12 ++++ 4 files changed, 154 insertions(+) create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/ti-pruss.h
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index e4f8834448..179b73a541 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -23,4 +23,17 @@ config TI_KEYSTONE_SERDES SerDes driver for Keystone SoC used for ethernet support on TI K2 platforms.
+config TI_PRUSS + bool "Support for TI's K3 based Pruss driver" + depends on DM + depends on ARCH_K3 + depends on OF_CONTROL + depends on SYSCON + help + + Support for TI PRU-ICSSG subsystem. + + Currently supported on AM65xx SoCs Say Y here to support the + Programmable Realtime Unit (PRU). + endif # SOC_TI diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index 4ec04ee125..34f80aad29 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -2,3 +2,4 @@
obj-$(CONFIG_TI_K3_NAVSS_RINGACC) += k3-navss-ringacc.o obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o +obj-$(CONFIG_TI_PRUSS) += pruss.o diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c new file mode 100644 index 0000000000..03ddaaa539 --- /dev/null +++ b/drivers/soc/ti/pruss.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PRU-ICSS platform driver for various TI SoCs + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Keerthy j-keerthy@ti.com + */ + +#include <common.h> +#include <dm.h> +#include <dm/of_access.h> +#include <errno.h> +#include <clk.h> +#include <reset.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h> +#include <power-domain.h> +#include <ti-pruss.h> + +#define PRUSS_CFG_IEPCLK 0x30 +#define ICSSG_CFG_CORE_SYNC 0x3c + +/* PRUSS_IEPCLK register bits */ +#define PRUSS_IEPCLK_IEP_OCP_CLK_EN BIT(0) + +/* ICSSG CORE_SYNC register bits */ +#define ICSSG_CORE_VBUSP_SYNC_EN BIT(0) + +/** + * enum pruss_mem - PRUSS memory range identifiers + */ +enum pruss_mem { + PRUSS_MEM_DRAM0 = 0, + PRUSS_MEM_DRAM1, + PRUSS_MEM_SHRD_RAM2, + PRUSS_MEM_MAX, +}; + +int pruss_request_shrmem_region(struct udevice *dev, phys_addr_t *loc) +{ + struct pruss *priv; + + priv = dev_get_priv(dev); + if (!priv || !priv->pruss_shrdram2) + return -EINVAL; + + *loc = priv->pruss_shrdram2; + + return 0; +} + +static int pruss_bind(struct udevice *dev) +{ + return dm_scan_fdt_dev(dev); +} + +/** + * pruss_probe() - Basic probe + * @dev: corresponding k3 device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int pruss_probe(struct udevice *dev) +{ + struct pruss *priv; + int ret, idx; + ofnode sub_node, node, memories; + struct regmap *regmap_cfg; + struct udevice *syscon; + + priv = dev_get_priv(dev); + node = dev_ofnode(dev); + sub_node = ofnode_find_subnode(node, "cfg"); + memories = ofnode_find_subnode(node, "memories"); + + idx = ofnode_stringlist_search(memories, "reg-names", "dram0"); + priv->pruss_dram0 = ofnode_get_addr_size_index(memories, idx, + (u64 *)&priv->pruss_dram0sz); + idx = ofnode_stringlist_search(memories, "reg-names", "dram1"); + priv->pruss_dram1 = ofnode_get_addr_size_index(memories, idx, + (u64 *)&priv->pruss_dram1sz); + idx = ofnode_stringlist_search(memories, "reg-names", "shrdram2"); + priv->pruss_shrdram2 = ofnode_get_addr_size_index(memories, idx, + (u64 *)&priv->pruss_shrdram2sz); + + ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, sub_node, + &syscon); + + regmap_cfg = syscon_get_regmap(syscon); + + /* + * The CORE block uses two multiplexers to allow software to + * select one of three source clocks (ICSSGn_CORE_CLK, ICSSGn_ICLK or + * ICSSGn_IEP_CLK) for the final clock source of the CORE block. + * The user needs to configure ICSSG_CORE_SYNC_REG[0] CORE_VBUSP_SYNC_EN + * bit & ICSSG_IEPCLK_REG[0] IEP_OCP_CLK_EN bit in order to select the + * clock source to the CORE block. + */ + ret = regmap_update_bits(regmap_cfg, ICSSG_CFG_CORE_SYNC, + ICSSG_CORE_VBUSP_SYNC_EN, + ICSSG_CORE_VBUSP_SYNC_EN); + if (ret) + return ret; + ret = regmap_update_bits(regmap_cfg, PRUSS_CFG_IEPCLK, + PRUSS_IEPCLK_IEP_OCP_CLK_EN, + PRUSS_IEPCLK_IEP_OCP_CLK_EN); + if (ret) + return ret; + + dev_dbg(dev, "pruss successfully probed %s\n", dev->name); + + return 0; +} + +static const struct udevice_id pruss_ids[] = { + { .compatible = "ti,am654-icssg"}, + {} +}; + +U_BOOT_DRIVER(pruss) = { + .name = "pruss", + .of_match = pruss_ids, + .id = UCLASS_MISC, + .bind = pruss_bind, + .probe = pruss_probe, + .priv_auto_alloc_size = sizeof(struct pruss), +}; diff --git a/include/ti-pruss.h b/include/ti-pruss.h new file mode 100644 index 0000000000..547ec5ee33 --- /dev/null +++ b/include/ti-pruss.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 + +struct pruss { + phys_addr_t pruss_dram0; + phys_addr_t pruss_dram1; + phys_addr_t pruss_shrdram2; + phys_size_t pruss_dram0sz; + phys_size_t pruss_dram1sz; + phys_size_t pruss_shrdram2sz; +}; + +int pruss_request_shrmem_region(struct udevice *dev, phys_addr_t *loc);

On Tue, Aug 06, 2019 at 04:08:34PM +0530, Keerthy wrote:
The Programmable Real-Time Unit - Industrial Communication Subsystem (PRU-ICSS) is present of various TI SoCs such as AM335x or AM437x or the AM654x family. Each SoC can have one or more PRUSS instances that may or may not be identical.
The PRUSS consists of dual 32-bit RISC cores called the Programmable Real-Time Units (PRUs), some shared, data and instruction memories, some internal peripheral modules, and an interrupt controller. The programmable nature of the PRUs provide flexibility to implement custom peripheral interfaces, fast real-time responses, or specialized data handling.
Add support for pruss driver. Currently am654x family is supported.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/soc/ti/Kconfig | 13 ++++ drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 128 ++++++++++++++++++++++++++++++++++++++++ include/ti-pruss.h | 12 ++++ 4 files changed, 154 insertions(+) create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/ti-pruss.h
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index e4f8834448..179b73a541 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -23,4 +23,17 @@ config TI_KEYSTONE_SERDES SerDes driver for Keystone SoC used for ethernet support on TI K2 platforms.
+config TI_PRUSS
- bool "Support for TI's K3 based Pruss driver"
- depends on DM
- depends on ARCH_K3
- depends on OF_CONTROL
- depends on SYSCON
- help
Usually there is no blank line below 'help', the next line should follow immediately to better indicate those things belong together.
Support for TI PRU-ICSSG subsystem.
Currently supported on AM65xx SoCs Say Y here to support the
First sentence is missing the period ('.')
Programmable Realtime Unit (PRU).
endif # SOC_TI diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index 4ec04ee125..34f80aad29 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -2,3 +2,4 @@
obj-$(CONFIG_TI_K3_NAVSS_RINGACC) += k3-navss-ringacc.o obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o +obj-$(CONFIG_TI_PRUSS) += pruss.o diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c new file mode 100644 index 0000000000..03ddaaa539 --- /dev/null +++ b/drivers/soc/ti/pruss.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- PRU-ICSS platform driver for various TI SoCs
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- Keerthy j-keerthy@ti.com
- */
+#include <common.h> +#include <dm.h> +#include <dm/of_access.h> +#include <errno.h> +#include <clk.h> +#include <reset.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h> +#include <power-domain.h> +#include <ti-pruss.h>
+#define PRUSS_CFG_IEPCLK 0x30 +#define ICSSG_CFG_CORE_SYNC 0x3c
+/* PRUSS_IEPCLK register bits */ +#define PRUSS_IEPCLK_IEP_OCP_CLK_EN BIT(0)
+/* ICSSG CORE_SYNC register bits */ +#define ICSSG_CORE_VBUSP_SYNC_EN BIT(0)
+/**
- enum pruss_mem - PRUSS memory range identifiers
- */
+enum pruss_mem {
- PRUSS_MEM_DRAM0 = 0,
- PRUSS_MEM_DRAM1,
- PRUSS_MEM_SHRD_RAM2,
- PRUSS_MEM_MAX,
+};
+int pruss_request_shrmem_region(struct udevice *dev, phys_addr_t *loc) +{
- struct pruss *priv;
- priv = dev_get_priv(dev);
- if (!priv || !priv->pruss_shrdram2)
return -EINVAL;
- *loc = priv->pruss_shrdram2;
- return 0;
+}
+static int pruss_bind(struct udevice *dev) +{
- return dm_scan_fdt_dev(dev);
+}
+/**
- pruss_probe() - Basic probe
- @dev: corresponding k3 device
- Return: 0 if all goes good, else appropriate error message.
- */
+static int pruss_probe(struct udevice *dev) +{
- struct pruss *priv;
- int ret, idx;
- ofnode sub_node, node, memories;
- struct regmap *regmap_cfg;
- struct udevice *syscon;
- priv = dev_get_priv(dev);
- node = dev_ofnode(dev);
- sub_node = ofnode_find_subnode(node, "cfg");
- memories = ofnode_find_subnode(node, "memories");
- idx = ofnode_stringlist_search(memories, "reg-names", "dram0");
- priv->pruss_dram0 = ofnode_get_addr_size_index(memories, idx,
(u64 *)&priv->pruss_dram0sz);
- idx = ofnode_stringlist_search(memories, "reg-names", "dram1");
- priv->pruss_dram1 = ofnode_get_addr_size_index(memories, idx,
(u64 *)&priv->pruss_dram1sz);
- idx = ofnode_stringlist_search(memories, "reg-names", "shrdram2");
- priv->pruss_shrdram2 = ofnode_get_addr_size_index(memories, idx,
(u64 *)&priv->pruss_shrdram2sz);
- ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, sub_node,
&syscon);
- regmap_cfg = syscon_get_regmap(syscon);
- /*
* The CORE block uses two multiplexers to allow software to
* select one of three source clocks (ICSSGn_CORE_CLK, ICSSGn_ICLK or
* ICSSGn_IEP_CLK) for the final clock source of the CORE block.
* The user needs to configure ICSSG_CORE_SYNC_REG[0] CORE_VBUSP_SYNC_EN
* bit & ICSSG_IEPCLK_REG[0] IEP_OCP_CLK_EN bit in order to select the
* clock source to the CORE block.
*/
- ret = regmap_update_bits(regmap_cfg, ICSSG_CFG_CORE_SYNC,
ICSSG_CORE_VBUSP_SYNC_EN,
ICSSG_CORE_VBUSP_SYNC_EN);
- if (ret)
return ret;
- ret = regmap_update_bits(regmap_cfg, PRUSS_CFG_IEPCLK,
PRUSS_IEPCLK_IEP_OCP_CLK_EN,
PRUSS_IEPCLK_IEP_OCP_CLK_EN);
- if (ret)
return ret;
- dev_dbg(dev, "pruss successfully probed %s\n", dev->name);
- return 0;
+}
+static const struct udevice_id pruss_ids[] = {
- { .compatible = "ti,am654-icssg"},
There should be a space prior to the closing curly brace.
- {}
+};
+U_BOOT_DRIVER(pruss) = {
- .name = "pruss",
- .of_match = pruss_ids,
- .id = UCLASS_MISC,
- .bind = pruss_bind,
- .probe = pruss_probe,
- .priv_auto_alloc_size = sizeof(struct pruss),
+}; diff --git a/include/ti-pruss.h b/include/ti-pruss.h new file mode 100644 index 0000000000..547ec5ee33 --- /dev/null +++ b/include/ti-pruss.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0
How about adding some include guards (#ifndef...) to the header file?
-- Andreas Dannenberg Texas Instruments Inc
+struct pruss {
- phys_addr_t pruss_dram0;
- phys_addr_t pruss_dram1;
- phys_addr_t pruss_shrdram2;
- phys_size_t pruss_dram0sz;
- phys_size_t pruss_dram1sz;
- phys_size_t pruss_shrdram2sz;
+};
+int pruss_request_shrmem_region(struct udevice *dev, phys_addr_t *loc);
2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

The Programmable Real-Time Unit Subsystem (PRUSS) consists of dual 32-bit RISC cores (Programmable Real-Time Units, or PRUs) for program execution. This patch adds a remoteproc platform driver for managing the individual PRU RISC cores life cycle.
The driver currently supports the AM65xx SoC
Signed-off-by: Keerthy j-keerthy@ti.com --- drivers/remoteproc/Kconfig | 11 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/pru_rproc.c | 384 +++++++++++++++++++++++++++++++++ 3 files changed, 396 insertions(+) create mode 100644 drivers/remoteproc/pru_rproc.c
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f54a245424..15aeca65ab 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -61,4 +61,15 @@ config REMOTEPROC_TI_POWER help Say 'y' here to add support for TI power processors such as those found on certain TI keystone and OMAP generation SoCs. + +config REMOTEPROC_TI_PRU + bool "Support for TI's K3 based PRU remoteproc driver" + select REMOTEPROC + depends on DM + depends on TI_PRUSS + depends on ARCH_K3 + depends on OF_CONTROL + help + Say 'y' here to add support for TI' K3 remoteproc driver. + endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 271ba55b09..73d061757a 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o +obj-$(CONFIG_REMOTEPROC_TI_PRU) += pru_rproc.o diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c new file mode 100644 index 0000000000..7768cb77e1 --- /dev/null +++ b/drivers/remoteproc/pru_rproc.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PRU-RTU remoteproc driver for various SoCs + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Keerthy j-keerthy@ti.com + */ + +#include <common.h> +#include <dm.h> +#include <elf.h> +#include <dm/of_access.h> +#include <remoteproc.h> +#include <errno.h> +#include <clk.h> +#include <reset.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h> +#include <power-domain.h> +#include <ti-pruss.h> + +/* PRU_ICSS_PRU_CTRL registers */ +#define PRU_CTRL_CTRL 0x0000 +#define PRU_CTRL_STS 0x0004 +#define PRU_CTRL_WAKEUP_EN 0x0008 +#define PRU_CTRL_CYCLE 0x000C +#define PRU_CTRL_STALL 0x0010 +#define PRU_CTRL_CTBIR0 0x0020 +#define PRU_CTRL_CTBIR1 0x0024 +#define PRU_CTRL_CTPPR0 0x0028 +#define PRU_CTRL_CTPPR1 0x002C + +/* CTRL register bit-fields */ +#define CTRL_CTRL_SOFT_RST_N BIT(0) +#define CTRL_CTRL_EN BIT(1) +#define CTRL_CTRL_SLEEPING BIT(2) +#define CTRL_CTRL_CTR_EN BIT(3) +#define CTRL_CTRL_SINGLE_STEP BIT(8) +#define CTRL_CTRL_RUNSTATE BIT(15) + +#define RPROC_FLAGS_SHIFT 16 +#define RPROC_FLAGS_NONE 0 +#define RPROC_FLAGS_ELF_PHDR BIT(0 + RPROC_FLAGS_SHIFT) +#define RPROC_FLAGS_ELF_SHDR BIT(1 + RPROC_FLAGS_SHIFT) + +/** + * enum pru_mem - PRU core memory range identifiers + */ +enum pru_mem { + PRU_MEM_IRAM = 0, + PRU_MEM_CTRL, + PRU_MEM_DEBUG, + PRU_MEM_MAX, +}; + +struct pru_privdata { + phys_addr_t pru_iram; + phys_addr_t pru_ctrl; + phys_addr_t pru_debug; + fdt_size_t pru_iramsz; + fdt_size_t pru_ctrlsz; + fdt_size_t pru_debugsz; + const char *fw_name; + u32 iram_da; + u32 pdram_da; + u32 sdram_da; + u32 shrdram_da; + u32 bootaddr; + int id; + struct pruss *prusspriv; +}; + +static int pru_start(struct udevice *dev) +{ + struct pru_privdata *priv; + int val = 0; + + priv = dev_get_priv(dev); + + val = CTRL_CTRL_EN | ((priv->bootaddr >> 2) << 16); + writel(val, priv->pru_ctrl + PRU_CTRL_CTRL); + + return 0; +} + +static int pru_stop(struct udevice *dev) +{ + struct pru_privdata *priv; + int val = 0; + + priv = dev_get_priv(dev); + + val = readl(priv->pru_ctrl + PRU_CTRL_CTRL); + val &= ~CTRL_CTRL_EN; + writel(val, priv->pru_ctrl + PRU_CTRL_CTRL); + + return 0; +} + +/** + * pru_init() - Initialize the remote processor + * @dev: rproc device pointer + * + * Return: 0 if all went ok, else return appropriate error + */ +static int pru_init(struct udevice *dev) +{ + return 0; +} + +/* + * Convert PRU device address (data spaces only) to kernel virtual address + * + * Each PRU has access to all data memories within the PRUSS, accessible at + * different ranges. So, look through both its primary and secondary Data + * RAMs as well as any shared Data RAM to convert a PRU device address to + * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data + * RAM1 is primary Data RAM for PRU1. + */ +static void *pru_d_da_to_pa(struct pru_privdata *priv, u32 da, int len) +{ + u32 offset; + void *pa = NULL; + phys_addr_t dram0, dram1, shrdram2; + u32 dram0sz, dram1sz, shrdram2sz; + + if (len <= 0) + return NULL; + + dram0 = priv->prusspriv->pruss_dram0; + dram1 = priv->prusspriv->pruss_dram1; + shrdram2 = priv->prusspriv->pruss_shrdram2; + dram0sz = priv->prusspriv->pruss_dram0sz; + dram1sz = priv->prusspriv->pruss_dram1sz; + shrdram2sz = priv->prusspriv->pruss_shrdram2sz; + + /* PRU1 has its local RAM addresses reversed */ + if (priv->id == 1) { + dram1 = priv->prusspriv->pruss_dram0; + dram0 = priv->prusspriv->pruss_dram1; + dram1sz = priv->prusspriv->pruss_dram0sz; + dram0sz = priv->prusspriv->pruss_dram1sz; + } + + if (da >= priv->pdram_da && da + len <= priv->pdram_da + dram0sz) { + offset = da - priv->pdram_da; + pa = (__force void *)(dram0 + offset); + } else if (da >= priv->sdram_da && + da + len <= priv->sdram_da + dram1sz) { + offset = da - priv->sdram_da; + pa = (__force void *)(dram1 + offset); + } else if (da >= priv->shrdram_da && + da + len <= priv->shrdram_da + shrdram2sz) { + offset = da - priv->shrdram_da; + pa = (__force void *)(shrdram2 + offset); + } + + return pa; +} + +/* + * Convert PRU device address (instruction space) to kernel virtual address + * + * A PRU does not have an unified address space. Each PRU has its very own + * private Instruction RAM, and its device address is identical to that of + * its primary Data RAM device address. + */ +static void *pru_i_da_to_pa(struct pru_privdata *priv, u32 da, int len) +{ + u32 offset; + void *pa = NULL; + + if (len <= 0) + return NULL; + + if (da >= priv->iram_da && + da + len <= priv->iram_da + priv->pru_iramsz) { + offset = da - priv->iram_da; + pa = (__force void *)(priv->pru_iram + offset); + } + + return pa; +} + +/* PRU-specific address translator */ +static void *pru_da_to_pa(struct pru_privdata *priv, u64 da, int len, u32 flags) +{ + void *pa; + u32 exec_flag; + + exec_flag = ((flags & RPROC_FLAGS_ELF_SHDR) ? flags & SHF_EXECINSTR : + ((flags & RPROC_FLAGS_ELF_PHDR) ? flags & PF_X : 0)); + + if (exec_flag) + pa = pru_i_da_to_pa(priv, da, len); + else + pa = pru_d_da_to_pa(priv, da, len); + + return pa; +} + +/* + * Custom memory copy implementation for ICSSG PRU/RTU Cores + * + * The ICSSG PRU/RTU cores have a memory copying issue with IRAM memories, that + * is not seen on previous generation SoCs. The data is reflected properly in + * the IRAM memories only for integer (4-byte) copies. Any unaligned copies + * result in all the other pre-existing bytes zeroed out within that 4-byte + * boundary, thereby resulting in wrong text/code in the IRAMs. Also, the + * IRAM memory port interface does not allow any 8-byte copies (as commonly + * used by ARM64 memcpy implementation) and throws an exception. The DRAM + * memory ports do not show this behavior. Use this custom copying function + * to properly load the PRU/RTU firmware images on all memories for simplicity. + * + * TODO: Improve the function to deal with additional corner cases like + * unaligned copy sizes or sub-integer trailing bytes when the need arises. + */ +static int pru_rproc_memcpy(void *dest, void *src, size_t count) +{ + const int *s = src; + int *d = dest; + int size = count / 4; + int *tmp_src = NULL; + + /* limited to 4-byte aligned addresses and copy sizes */ + if ((long)dest % 4 || count % 4) + return -EINVAL; + + /* src offsets in ELF firmware image can be non-aligned */ + if ((long)src % 4) { + tmp_src = malloc(count); + if (!tmp_src) + return -ENOMEM; + + memcpy(tmp_src, src, count); + s = tmp_src; + } + + while (size--) + *d++ = *s++; + + kfree(tmp_src); + + return 0; +} + +static int pru_load(struct udevice *dev, ulong addr, ulong size) +{ + struct pru_privdata *priv; + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + int i, ret = 0; + + priv = dev_get_priv(dev); + + ehdr = (Elf32_Ehdr *)addr; + phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); + + /* go through the available ELF segments */ + for (i = 0; i < ehdr->e_phnum; i++, phdr++) { + u32 da = phdr->p_paddr; + u32 memsz = phdr->p_memsz; + u32 filesz = phdr->p_filesz; + u32 offset = phdr->p_offset; + void *ptr; + + if (phdr->p_type != PT_LOAD) + continue; + + dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n", + phdr->p_type, da, memsz, filesz); + + if (filesz > memsz) { + dev_dbg(dev, "bad phdr filesz 0x%x memsz 0x%x\n", + filesz, memsz); + ret = -EINVAL; + break; + } + + if (offset + filesz > size) { + dev_dbg(dev, "truncated fw: need 0x%x avail 0x%zx\n", + offset + filesz, size); + ret = -EINVAL; + break; + } + + /* grab the kernel address for this device address */ + ptr = pru_da_to_pa(priv, da, memsz, + RPROC_FLAGS_ELF_PHDR | phdr->p_flags); + if (!ptr) { + dev_dbg(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz); + ret = -EINVAL; + break; + } + + /* skip the memzero logic performed by remoteproc ELF loader */ + if (!phdr->p_filesz) + continue; + + ret = pru_rproc_memcpy(ptr, + (void *)addr + phdr->p_offset, filesz); + if (ret) { + dev_dbg(dev, "PRU custom memory copy failed for da 0x%x memsz 0x%x\n", + da, memsz); + break; + } + } + + priv->bootaddr = ehdr->e_entry; + + return ret; +} + +static const struct dm_rproc_ops pru_ops = { + .init = pru_init, + .start = pru_start, + .stop = pru_stop, + .load = pru_load, +}; + +static void pru_set_id(struct pru_privdata *priv, struct udevice *dev) +{ + u32 mask2 = 0x38000; + + if (device_is_compatible(dev, "ti,am654-rtu")) + mask2 = 0x6000; + + if ((priv->pru_iram & mask2) == mask2) + priv->id = 1; + else + priv->id = 0; +} + +/** + * pru_probe() - Basic probe + * @dev: corresponding k3 remote processor device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int pru_probe(struct udevice *dev) +{ + struct pru_privdata *priv; + int lenp; + ofnode node; + + node = dev_ofnode(dev); + + priv = dev_get_priv(dev); + priv->prusspriv = dev_get_priv(dev->parent); + + priv->pru_iram = devfdt_get_addr_size_index(dev, PRU_MEM_IRAM, + &priv->pru_iramsz); + priv->pru_ctrl = devfdt_get_addr_size_index(dev, PRU_MEM_CTRL, + &priv->pru_ctrlsz); + priv->pru_debug = devfdt_get_addr_size_index(dev, PRU_MEM_DEBUG, + &priv->pru_debugsz); + + priv->fw_name = ofnode_get_property(node, "firmware-name", &lenp); + + priv->iram_da = 0; + priv->pdram_da = 0; + priv->sdram_da = 0x2000; + priv->shrdram_da = 0x10000; + + pru_set_id(priv, dev); + + return 0; +} + +static const struct udevice_id pru_ids[] = { + { .compatible = "ti,am654-pru"}, + { .compatible = "ti,am654-rtu"}, + {} +}; + +U_BOOT_DRIVER(pru) = { + .name = "pru", + .of_match = pru_ids, + .id = UCLASS_REMOTEPROC, + .ops = &pru_ops, + .probe = pru_probe, + .priv_auto_alloc_size = sizeof(struct pru_privdata), +};

This is the Ethernet driver for TI SoCs with the ICSSG PRU Sub-system running EMAC firmware. This driver caters to either of the slices(pru/rtu pair) of the icssg subsystem.
Following are the firmwares needed to run cores:
am65x-pru0-prueth-fw.elf for pru0 of slice0 am65x-rtu0-prueth-fw.elf for rtu0 of slice0 am65x-pru1-prueth-fw.elf for pru1 of slice1 am65x-rtu1-prueth-fw.elf for rtu1 of slice1
One and exactly one of the slices is supported as the u-boot ethernet supports probing one interface at a time.
Signed-off-by: Keerthy j-keerthy@ti.com --- drivers/net/ti/Kconfig | 8 + drivers/net/ti/Makefile | 1 + drivers/net/ti/icssg-prueth.c | 517 ++++++++++++++++++++++++++++++ drivers/net/ti/icssg.h | 31 ++ drivers/net/ti/icssg_classifier.c | 397 +++++++++++++++++++++++ 5 files changed, 954 insertions(+) create mode 100644 drivers/net/ti/icssg-prueth.c create mode 100644 drivers/net/ti/icssg.h create mode 100644 drivers/net/ti/icssg_classifier.c
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig index ecf642de10..1b6285709f 100644 --- a/drivers/net/ti/Kconfig +++ b/drivers/net/ti/Kconfig @@ -26,3 +26,11 @@ config TI_AM65_CPSW_NUSS help This driver supports TI K3 MCU CPSW Nuss Ethernet controller in Texas Instruments K3 AM65x SoCs. + +config TI_AM64_ICSSG_PRUETH + bool "TI Gigabit PRU Ethernet driver" + depends on ARCH_K3 + select PHYLIB + help + Support Gigabit Ethernet ports over the ICSSG PRU Subsystem + This subsystem is available starting with the AM65 platform. diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile index 8d3808bb4b..b486498909 100644 --- a/drivers/net/ti/Makefile +++ b/drivers/net/ti/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o cpsw_mdio.o obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o cpsw_mdio.o +obj-$(CONFIG_TI_AM64_ICSSG_PRUETH) += icssg-prueth.o cpsw_mdio.o icssg_classifier.o diff --git a/drivers/net/ti/icssg-prueth.c b/drivers/net/ti/icssg-prueth.c new file mode 100644 index 0000000000..f8935ee087 --- /dev/null +++ b/drivers/net/ti/icssg-prueth.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments K3 AM65 PRU Ethernet Driver + * + * Copyright (C) 2019, Texas Instruments, Incorporated + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <clk.h> +#include <dm.h> +#include <dm/lists.h> +#include <dm/device.h> +#include <dma-uclass.h> +#include <dm/of_access.h> +#include <fs_loader.h> +#include <miiphy.h> +#include <misc.h> +#include <net.h> +#include <phy.h> +#include <power-domain.h> +#include <linux/soc/ti/ti-udma.h> +#include <regmap.h> +#include <remoteproc.h> +#include <syscon.h> +#include <ti-pruss.h> + +#include "cpsw_mdio.h" +#include "icssg.h" + +#define ICSS_SLICE0 0 +#define ICSS_SLICE1 1 + +#ifdef PKTSIZE_ALIGN +#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN +#else +#define UDMA_RX_BUF_SIZE ALIGN(1522, ARCH_DMA_MINALIGN) +#endif + +#ifdef PKTBUFSRX +#define UDMA_RX_DESC_NUM PKTBUFSRX +#else +#define UDMA_RX_DESC_NUM 4 +#endif + +enum prueth_mac { + PRUETH_MAC0 = 0, + PRUETH_MAC1, + PRUETH_NUM_MACS, +}; + +enum prueth_port { + PRUETH_PORT_HOST = 0, /* host side port */ + PRUETH_PORT_MII0, /* physical port MII 0 */ + PRUETH_PORT_MII1, /* physical port MII 1 */ +}; + +/* Config region lies in shared RAM */ +#define ICSS_CONFIG_OFFSET_SLICE0 0 +#define ICSS_CONFIG_OFFSET_SLICE1 0x8000 + +/* Firmware flags */ +#define ICSS_SET_RUN_FLAG_VLAN_ENABLE BIT(0) /* switch only */ +#define ICSS_SET_RUN_FLAG_FLOOD_UNICAST BIT(1) /* switch only */ +#define ICSS_SET_RUN_FLAG_PROMISC BIT(2) /* MAC only */ +#define ICSS_SET_RUN_FLAG_MULTICAST_PROMISC BIT(3) /* MAC only */ + +/* CTRLMMR_ICSSG_RGMII_CTRL register bits */ +#define ICSSG_CTRL_RGMII_ID_MODE BIT(24) + +/** + * enum pruss_pru_id - PRU core identifiers + */ +enum pruss_pru_id { + PRUSS_PRU0 = 0, + PRUSS_PRU1, + PRUSS_NUM_PRUS, +}; + +struct prueth { + struct udevice *dev; + struct regmap *miig_rt; + fdt_addr_t mdio_base; + phys_addr_t pruss_shrdram2; + struct mii_dev *bus; + u32 port_id; + u32 sram_pa; + struct phy_device *phydev; + bool has_phy; + ofnode phy_node; + u32 phy_addr; + ofnode eth_node[PRUETH_NUM_MACS]; + struct icssg_config config[PRUSS_NUM_PRUS]; + u32 mdio_freq; + int phy_interface; + struct clk mdiofck; + struct dma dma_tx; + struct dma dma_rx; + u32 rx_next; + u32 rx_pend; + int slice; +}; + +static int icssg_phy_init(struct udevice *dev) +{ + struct prueth *priv = dev_get_priv(dev); + struct phy_device *phydev; + u32 supported = PHY_GBIT_FEATURES; + int ret; + + phydev = phy_connect(priv->bus, + priv->phy_addr, + priv->dev, + priv->phy_interface); + + if (!phydev) { + dev_err(dev, "phy_connect() failed\n"); + return -ENODEV; + } + + phydev->supported &= supported; + phydev->advertising = phydev->supported; + +#ifdef CONFIG_DM_ETH + if (ofnode_valid(priv->phy_node)) + phydev->node = priv->phy_node; +#endif + + priv->phydev = phydev; + ret = phy_config(phydev); + if (ret < 0) + pr_err("phy_config() failed: %d", ret); + + return ret; +} + +static int icssg_mdio_init(struct udevice *dev) +{ + struct prueth *prueth = dev_get_priv(dev); + + prueth->bus = cpsw_mdio_init(dev->name, prueth->mdio_base, + prueth->mdio_freq, + clk_get_rate(&prueth->mdiofck)); + if (!prueth->bus) + return -EFAULT; + + return 0; +} + +static void icssg_config_set(struct prueth *prueth) +{ + void __iomem *va; + + va = (void __iomem *)prueth->pruss_shrdram2 + prueth->slice * + ICSSG_CONFIG_OFFSET_SLICE1; + + memcpy_toio(va, &prueth->config[0], sizeof(prueth->config[0])); +} + +static int prueth_start(struct udevice *dev) +{ + struct prueth *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev->platdata; + int ret, i; + char tx_chn_name[16]; + char rx_chn_name[16]; + + icssg_class_set_mac_addr(priv->miig_rt, priv->slice, + (u8 *)pdata->enetaddr); + icssg_class_default(priv->miig_rt, priv->slice); + + /* To differentiate channels for SLICE0 vs SLICE1 */ + snprintf(tx_chn_name, sizeof(tx_chn_name), "tx%d-0", priv->slice); + snprintf(rx_chn_name, sizeof(rx_chn_name), "rx%d", priv->slice); + + ret = dma_get_by_name(dev, tx_chn_name, &priv->dma_tx); + if (ret) + dev_err(dev, "TX dma get failed %d\n", ret); + + ret = dma_get_by_name(dev, rx_chn_name, &priv->dma_rx); + if (ret) + dev_err(dev, "RX dma get failed %d\n", ret); + + for (i = 0; i < UDMA_RX_DESC_NUM; i++) { + ret = dma_prepare_rcv_buf(&priv->dma_rx, + net_rx_packets[i], + UDMA_RX_BUF_SIZE); + if (ret) + dev_err(dev, "RX dma add buf failed %d\n", ret); + } + + ret = dma_enable(&priv->dma_tx); + if (ret) { + dev_err(dev, "TX dma_enable failed %d\n", ret); + return ret; + } + + ret = dma_enable(&priv->dma_rx); + if (ret) { + dev_err(dev, "RX dma_enable failed %d\n", ret); + goto rx_fail; + } + + ret = phy_startup(priv->phydev); + if (ret) { + dev_err(dev, "phy_startup failed\n"); + goto phy_fail; + } + + return 0; +phy_fail: + dma_disable(&priv->dma_rx); +rx_fail: + dma_disable(&priv->dma_tx); + + return ret; +} + +void prueth_print_buf(ulong addr, const void *data, uint width, + uint count, uint linelen) +{ + print_buffer(addr, data, width, count, linelen); +} + +static int prueth_send(struct udevice *dev, void *packet, int length) +{ + struct prueth *priv = dev_get_priv(dev); + int ret; + + ret = dma_send(&priv->dma_tx, packet, length, NULL); + + return ret; +} + +static int prueth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct prueth *priv = dev_get_priv(dev); + int ret; + + /* try to receive a new packet */ + ret = dma_receive(&priv->dma_rx, (void **)packetp, NULL); + + return ret; +} + +static int prueth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct prueth *priv = dev_get_priv(dev); + int ret = 0; + + if (length > 0) { + u32 pkt = priv->rx_next % UDMA_RX_DESC_NUM; + + dev_dbg(dev, "%s length:%d pkt:%u\n", __func__, length, pkt); + + ret = dma_prepare_rcv_buf(&priv->dma_rx, + net_rx_packets[pkt], + UDMA_RX_BUF_SIZE); + priv->rx_next++; + } + + return ret; +} + +static void prueth_stop(struct udevice *dev) +{ + struct prueth *priv = dev_get_priv(dev); + + icssg_class_disable(priv->miig_rt, priv->slice); + + phy_shutdown(priv->phydev); + + dma_disable(&priv->dma_tx); + dma_free(&priv->dma_tx); + + dma_disable(&priv->dma_rx); + dma_free(&priv->dma_rx); +} + +static const struct eth_ops prueth_ops = { + .start = prueth_start, + .send = prueth_send, + .recv = prueth_recv, + .free_pkt = prueth_free_pkt, + .stop = prueth_stop, +}; + +static int icssg_ofdata_parse_phy(struct udevice *dev, ofnode port_np) +{ + struct prueth *priv = dev_get_priv(dev); + struct ofnode_phandle_args out_args; + const char *phy_mode; + int ret = 0; + + phy_mode = ofnode_read_string(port_np, "phy-mode"); + if (phy_mode) { + priv->phy_interface = + phy_get_interface_by_name(phy_mode); + if (priv->phy_interface == -1) { + dev_err(dev, "Invalid PHY mode '%s'\n", + phy_mode); + ret = -EINVAL; + goto out; + } + } + + ret = ofnode_parse_phandle_with_args(port_np, "phy-handle", + NULL, 0, 0, &out_args); + if (ret) { + dev_err(dev, "can't parse phy-handle port (%d)\n", ret); + ret = 0; + } + + priv->phy_node = out_args.node; + ret = ofnode_read_u32(priv->phy_node, "reg", &priv->phy_addr); + if (ret) + dev_err(dev, "failed to get phy_addr port (%d)\n", ret); + +out: + return ret; +} + +static int prueth_config_rgmiidelay(struct prueth *prueth, + ofnode eth_np) +{ + struct regmap *ctrl_mmr; + u32 val; + int ret = 0; + ofnode node; + u32 tmp[2]; + + ret = ofnode_read_u32_array(eth_np, "syscon-rgmii-delay", tmp, 2); + if (ret) { + dev_err(dev, "no syscon-rgmii-delay\n"); + return ret; + } + + node = ofnode_get_by_phandle(tmp[0]); + if (!ofnode_valid(node)) { + dev_err(dev, "can't get syscon-rgmii-delay node\n"); + return -EINVAL; + } + + ctrl_mmr = syscon_node_to_regmap(node); + if (!ctrl_mmr) { + dev_err(dev, "can't get ctrl_mmr regmap\n"); + return -EINVAL; + } + + if (ofnode_read_bool(eth_np, "enable-rgmii-delay")) + val = 0; + else + val = ICSSG_CTRL_RGMII_ID_MODE; + + regmap_update_bits(ctrl_mmr, tmp[1], ICSSG_CTRL_RGMII_ID_MODE, val); + + return 0; +} + +static int prueth_probe(struct udevice *dev) +{ + struct prueth *prueth; + int ret = 0, i; + ofnode eth0_node, eth1_node, node, pruss_node, mdio_node, sram_node; + u32 phandle, err, sp; + struct udevice **prussdev = NULL; + struct icssg_config *config; + + prueth = dev_get_priv(dev); + prueth->dev = dev; + err = ofnode_read_u32(dev_ofnode(dev), "prus", &phandle); + if (err) + return err; + + node = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(node)) + return -EINVAL; + + pruss_node = ofnode_get_parent(node); + err = misc_init_by_ofnode(pruss_node); + if (err) + return err; + + ret = device_find_global_by_ofnode(pruss_node, prussdev); + if (ret) + dev_err(dev, "error getting the pruss dev\n"); + + ret = pruss_request_shrmem_region(*prussdev, &prueth->pruss_shrdram2); + if (ret) + return ret; + + node = dev_ofnode(dev); + eth0_node = ofnode_find_subnode(node, "ethernet-mii0"); + eth1_node = ofnode_find_subnode(node, "ethernet-mii1"); + /* one node must be present and available else we fail */ + if (!ofnode_valid(eth0_node) && !ofnode_valid(eth1_node)) { + dev_err(dev, "neither ethernet-mii0 nor ethernet-mii1 node available\n"); + return -ENODEV; + } + + /* + * Exactly one node must be present as uboot ethernet framework does + * not support two interfaces in a single probe. So Device Tree should + * have exactly one of mii0 or mii1 interface. + */ + if (ofnode_valid(eth0_node) && ofnode_valid(eth1_node)) { + dev_err(dev, "Both slices cannot be supported\n"); + return -EINVAL; + } + + if (ofnode_valid(eth0_node)) { + prueth->slice = 0; + icssg_ofdata_parse_phy(dev, eth0_node); + prueth->eth_node[PRUETH_MAC0] = eth0_node; + } + + if (ofnode_valid(eth1_node)) { + prueth->slice = 1; + icssg_ofdata_parse_phy(dev, eth1_node); + prueth->eth_node[PRUETH_MAC0] = eth1_node; + } + + prueth->miig_rt = syscon_regmap_lookup_by_phandle(dev, "mii-g-rt"); + if (!prueth->miig_rt) { + dev_err(dev, "couldn't get mii-g-rt syscon regmap\n"); + return -ENODEV; + } + + ret = clk_get_by_name(dev, "mdio_fck", &prueth->mdiofck); + if (ret) { + dev_err(dev, "failed to get clock %d\n", ret); + return ret; + } + ret = clk_enable(&prueth->mdiofck); + if (ret) { + dev_err(dev, "clk_enable failed %d\n", ret); + return ret; + } + + ret = ofnode_read_u32(dev_ofnode(dev), "sram", &sp); + if (ret) { + dev_err(dev, "sram node fetch failed %d\n", ret); + return ret; + } + + sram_node = ofnode_get_by_phandle(sp); + if (!ofnode_valid(node)) + return -EINVAL; + + prueth->sram_pa = ofnode_get_addr(sram_node); + + if (!prueth->slice) { + ret = prueth_config_rgmiidelay(prueth, eth0_node); + if (ret) { + dev_err(dev, "prueth_config_rgmiidelay failed\n"); + return ret; + } + } else { + ret = prueth_config_rgmiidelay(prueth, eth1_node); + if (ret) { + dev_err(dev, "prueth_config_rgmiidelay failed\n"); + return ret; + } + } + + mdio_node = ofnode_find_subnode(pruss_node, "mdio"); + prueth->mdio_base = ofnode_get_addr(mdio_node); + ofnode_read_u32(mdio_node, "bus_freq", &prueth->mdio_freq); + + ret = icssg_mdio_init(dev); + if (ret) + return ret; + + ret = icssg_phy_init(dev); + if (ret) { + dev_err(dev, "phy_init failed\n"); + goto out; + } + + /* Set Load time configuration */ + config = &prueth->config[0]; + memset(config, 0, sizeof(*config)); + config->addr_lo = cpu_to_le32(lower_32_bits(prueth->sram_pa)); + config->addr_hi = cpu_to_le32(upper_32_bits(prueth->sram_pa)); + config->num_tx_threads = 0; + config->rx_flow_id = 0; /* flow id for host port */ + + for (i = 8; i < 16; i++) + config->tx_buf_sz[i] = cpu_to_le32(0x1800); + + icssg_config_set(prueth); + + return 0; +out: + cpsw_mdio_free(prueth->bus); + clk_disable(&prueth->mdiofck); + + return ret; +} + +static const struct udevice_id prueth_ids[] = { + { .compatible = "ti,am654-icssg-prueth" }, + { } +}; + +U_BOOT_DRIVER(prueth) = { + .name = "prueth", + .id = UCLASS_ETH, + .of_match = prueth_ids, + .probe = prueth_probe, + .ops = &prueth_ops, + .priv_auto_alloc_size = sizeof(struct prueth), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/net/ti/icssg.h b/drivers/net/ti/icssg.h new file mode 100644 index 0000000000..2e881e6eb3 --- /dev/null +++ b/drivers/net/ti/icssg.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver + * + * Copyright (C) 2019, Texas Instruments, Incorporated + * + */ +void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac); +void icssg_class_disable(struct regmap *miig_rt, int slice); +void icssg_class_default(struct regmap *miig_rt, int slice); +void icssg_class_promiscuous(struct regmap *miig_rt, int slice); + +/* Config area lies in shared RAM */ +#define ICSSG_CONFIG_OFFSET_SLICE0 0 +#define ICSSG_CONFIG_OFFSET_SLICE1 0x8000 + +/* Load time Fiwmware Configuration */ +struct icssg_config { + __le32 status; /* Firmware status */ + __le32 addr_lo; /* MSMC Buffer pool base address low. */ + __le32 addr_hi; /* MSMC Buffer pool base address high. Must be 0 */ + __le32 tx_buf_sz[16]; /* Array of buffer pool sizes */ + __le32 num_tx_threads; /* Number of active egress threads, 1 to 4 */ + __le32 tx_rate_lim_en; /* Bitmask: Egress rate limit enable per thread */ + __le32 rx_flow_id; /* RX flow id for first rx ring */ + __le32 rx_mgr_flow_id; /* RX flow id for the first management ring */ + __le32 flags; /* TBD */ + __le32 n_burst; /* for debug */ + __le32 rtu_status; /* RTU status */ + __le32 info; /* reserved */ +} __packed; diff --git a/drivers/net/ti/icssg_classifier.c b/drivers/net/ti/icssg_classifier.c new file mode 100644 index 0000000000..2af14ed5b2 --- /dev/null +++ b/drivers/net/ti/icssg_classifier.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet Driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <clk.h> +#include <dm.h> +#include <dm/lists.h> +#include <dm/device.h> +#include <dma-uclass.h> +#include <dm/of_access.h> +#include <miiphy.h> +#include <net.h> +#include <phy.h> +#include <power-domain.h> +#include <linux/soc/ti/ti-udma.h> +#include <syscon.h> +#include <ti-pruss.h> +#include <regmap.h> + +#include "cpsw_mdio.h" +#include "icssg.h" + +#define ICSSG_NUM_CLASSIFIERS 16 +#define ICSSG_NUM_FT1_SLOTS 8 +#define ICSSG_NUM_FT3_SLOTS 16 + +/* Filter 1 - FT1 */ +#define FT1_NUM_SLOTS 8 +#define FT1_SLOT_SIZE 0x10 /* bytes */ + +/* offsets from FT1 slot base i.e. slot 1 start */ +#define FT1_DA0 0x0 +#define FT1_DA1 0x4 +#define FT1_DA0_MASK 0x8 +#define FT1_DA1_MASK 0xc + +#define FT1_N_REG(slize, n, reg) (offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg)) + +#define FT1_LEN_MASK GENMASK(19, 16) +#define FT1_LEN_SHIFT 16 +#define FT1_LEN(len) (((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK) + +#define FT1_MATCH_SLOT(n) (GENMASK(23, 16) & (BIT(n) << 16)) + +enum ft1_cfg_type { + FT1_CFG_TYPE_DISABLED = 0, + FT1_CFG_TYPE_EQ, + FT1_CFG_TYPE_GT, + FT1_CFG_TYPE_LT, +}; + +#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n))) + +/* Filter 3 - FT3 */ +#define FT3_NUM_SLOTS 16 +#define FT3_SLOT_SIZE 0x20 /* bytes */ + +/* offsets from FT3 slot n's base */ +#define FT3_START 0 +#define FT3_START_AUTO 0x4 +#define FT3_START_OFFSET 0x8 +#define FT3_JUMP_OFFSET 0xc +#define FT3_LEN 0x10 +#define FT3_CFG 0x14 +#define FT3_T 0x18 +#define FT3_T_MASK 0x1c + +#define FT3_N_REG(slize, n, reg) (offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg)) + +/* offsets from rx_class n's base */ +#define RX_CLASS_AND_EN 0 +#define RX_CLASS_OR_EN 0x4 + +#define RX_CLASS_NUM_SLOTS 16 +#define RX_CLASS_EN_SIZE 0x8 /* bytes */ + +#define RX_CLASS_N_REG(slice, n, reg) (offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg)) + +/* RX Class Gates */ +#define RX_CLASS_GATES_SIZE 0x4 /* bytes */ + +#define RX_CLASS_GATES_N_REG(slice, n) (offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n)) + +#define RX_CLASS_GATES_ALLOW_MASK BIT(6) +#define RX_CLASS_GATES_RAW_MASK BIT(5) +#define RX_CLASS_GATES_PHASE_MASK BIT(4) + +/* RX Class traffic data matching bits */ +#define RX_CLASS_FT_UC BIT(31) +#define RX_CLASS_FT_MC BIT(30) +#define RX_CLASS_FT_BC BIT(29) +#define RX_CLASS_FT_FW BIT(28) +#define RX_CLASS_FT_RCV BIT(27) +#define RX_CLASS_FT_VLAN BIT(26) +#define RX_CLASS_FT_DA_P BIT(25) +#define RX_CLASS_FT_DA_I BIT(24) +#define RX_CLASS_FT_FT1_MATCH_MASK GENMASK(23, 16) +#define RX_CLASS_FT_FT1_MATCH_SHIFT 16 +#define RX_CLASS_FT_FT3_MATCH_MASK GENMASK(15, 0) +#define RX_CLASS_FT_FT3_MATCH_SHIFT 0 + +enum rx_class_sel_type { + RX_CLASS_SEL_TYPE_OR = 0, + RX_CLASS_SEL_TYPE_AND = 1, + RX_CLASS_SEL_TYPE_OR_AND_AND = 2, + RX_CLASS_SEL_TYPE_OR_OR_AND = 3, +}; + +#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n))) + +#define RX_CLASS_SEL_SHIFT(n) (2 * (n)) +#define RX_CLASS_SEL_MASK(n) (0x3 << RX_CLASS_SEL_SHIFT((n))) + +#define ICSSG_CFG_OFFSET 0 +#define RGMII_CFG_OFFSET 4 + +#define ICSSG_CFG_RX_L2_G_EN BIT(2) + +/* these are register offsets per PRU */ +struct miig_rt_offsets { + u32 mac0; + u32 mac1; + u32 ft1_start_len; + u32 ft1_cfg; + u32 ft1_slot_base; + u32 ft3_slot_base; + u32 ft3_p_base; + u32 ft_rx_ptr; + u32 rx_class_base; + u32 rx_class_cfg1; + u32 rx_class_cfg2; + u32 rx_class_gates_base; + u32 rx_green; + u32 rx_rate_cfg_base; + u32 rx_rate_src_sel0; + u32 rx_rate_src_sel1; + u32 tx_rate_cfg_base; + u32 stat_base; + u32 tx_hsr_tag; + u32 tx_hsr_seq; + u32 tx_vlan_type; + u32 tx_vlan_ins; +}; + +static struct miig_rt_offsets offs[] = { + /* PRU0 */ + { + 0x8, + 0xc, + 0x80, + 0x84, + 0x88, + 0x108, + 0x308, + 0x408, + 0x40c, + 0x48c, + 0x490, + 0x494, + 0x4d4, + 0x4e4, + 0x504, + 0x508, + 0x50c, + 0x54c, + 0x63c, + 0x640, + 0x644, + 0x648, + }, + /* PRU1 */ + { + 0x10, + 0x14, + 0x64c, + 0x650, + 0x654, + 0x6d4, + 0x8d4, + 0x9d4, + 0x9d8, + 0xa58, + 0xa5c, + 0xa60, + 0xaa0, + 0xab0, + 0xad0, + 0xad4, + 0xad8, + 0xb18, + 0xc08, + 0xc0c, + 0xc10, + 0xc14, + }, +}; + +static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n, + enum ft1_cfg_type type) +{ + u32 offset; + + offset = offs[slice].ft1_cfg; + regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n), + type << FT1_CFG_SHIFT(n)); +} + +static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n, + enum rx_class_sel_type type) +{ + u32 offset; + + offset = offs[slice].rx_class_cfg1; + regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n), + type << RX_CLASS_SEL_SHIFT(n)); +} + +static void rx_class_set_and(struct regmap *miig_rt, int slice, int n, + u32 data) +{ + u32 offset; + + offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN); + regmap_write(miig_rt, offset, data); +} + +static void rx_class_set_or(struct regmap *miig_rt, int slice, int n, + u32 data) +{ + u32 offset; + + offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN); + regmap_write(miig_rt, offset, data); +} + +/* disable all RX traffic */ +void icssg_class_disable(struct regmap *miig_rt, int slice) +{ + u32 data, offset; + int n; + + /* Enable RX_L2_G */ + regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN, + ICSSG_CFG_RX_L2_G_EN); + + for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++) { + /* AND_EN = 0 */ + rx_class_set_and(miig_rt, slice, n, 0); + /* OR_EN = 0 */ + rx_class_set_or(miig_rt, slice, n, 0); + + /* set CFG1 to OR */ + rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR); + + /* configure gate */ + offset = RX_CLASS_GATES_N_REG(slice, n); + regmap_read(miig_rt, offset, &data); + /* clear class_raw */ + data &= ~RX_CLASS_GATES_RAW_MASK; + /* set allow and phase mask */ + data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK; + regmap_write(miig_rt, offset, data); + } + + /* FT1 uses 6 bytes of DA address */ + offset = offs[slice].ft1_start_len; + regmap_write(miig_rt, offset, FT1_LEN(6)); + + /* FT1 type EQ */ + for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) + rx_class_ft1_cfg_set_type(miig_rt, slice, n, FT1_CFG_TYPE_EQ); + + /* FT1[0] DA compare address 00-00-00-00-00-00 */ + offset = FT1_N_REG(slice, 0, FT1_DA0); + regmap_write(miig_rt, offset, 0); + offset = FT1_N_REG(slice, 0, FT1_DA1); + regmap_write(miig_rt, offset, 0); + + /* FT1[0] mask FE-FF-FF-FF-FF-FF */ + offset = FT1_N_REG(slice, 0, FT1_DA0_MASK); + regmap_write(miig_rt, offset, 0); + offset = FT1_N_REG(slice, 0, FT1_DA1_MASK); + regmap_write(miig_rt, offset, 0); + + /* clear CFG2 */ + regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0); +} + +void icssg_class_default(struct regmap *miig_rt, int slice) +{ + u32 offset, data; + int n; + + /* defaults */ + icssg_class_disable(miig_rt, slice); + + /* FT1 uses 6 bytes of DA address */ + offset = offs[slice].ft1_start_len; + regmap_write(miig_rt, offset, FT1_LEN(6)); + + /* FT1 slots to EQ */ + for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) + rx_class_ft1_cfg_set_type(miig_rt, slice, n, FT1_CFG_TYPE_EQ); + + /* FT1[0] DA compare address 00-00-00-00-00-00 */ + offset = FT1_N_REG(slice, 0, FT1_DA0); + regmap_write(miig_rt, offset, 0); + offset = FT1_N_REG(slice, 0, FT1_DA1); + regmap_write(miig_rt, offset, 0); + + /* FT1[0] mask 00-00-00-00-00-00 */ + offset = FT1_N_REG(slice, 0, FT1_DA0_MASK); + regmap_write(miig_rt, offset, 0); + offset = FT1_N_REG(slice, 0, FT1_DA1_MASK); + regmap_write(miig_rt, offset, 0); + + /* Setup Classifier 4 */ + /* match on Broadcast or MAC_PRU address */ + data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P; + rx_class_set_or(miig_rt, slice, 4, data); + + /* set CFG1 for OR_OR_AND for classifier 4 */ + rx_class_sel_set_type(miig_rt, slice, 4, RX_CLASS_SEL_TYPE_OR_OR_AND); + + /* ungate classifier 4 */ + offset = RX_CLASS_GATES_N_REG(slice, 4); + regmap_read(miig_rt, offset, &data); + data |= RX_CLASS_GATES_RAW_MASK; + regmap_write(miig_rt, offset, data); + + /* clear CFG2 */ + regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0); +} + +void icssg_class_promiscuous(struct regmap *miig_rt, int slice) +{ + u32 data; + u32 offset; + int n; + + /* defaults */ + icssg_class_disable(miig_rt, slice); + + /* FT1 uses 6 bytes of DA address */ + offset = offs[slice].ft1_start_len; + regmap_write(miig_rt, offset, FT1_LEN(6)); + + /* FT1 type EQ */ + for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) + rx_class_ft1_cfg_set_type(miig_rt, slice, n, FT1_CFG_TYPE_EQ); + + /* FT1[0] DA compare address 00-00-00-00-00-00 */ + offset = FT1_N_REG(slice, 0, FT1_DA0); + regmap_write(miig_rt, offset, 0); + offset = FT1_N_REG(slice, 0, FT1_DA1); + regmap_write(miig_rt, offset, 0); + + /* FT1[0] mask FE-FF-FF-FF-FF-FF */ + offset = FT1_N_REG(slice, 0, FT1_DA0_MASK); + regmap_write(miig_rt, offset, 0xfffffffe); + offset = FT1_N_REG(slice, 0, FT1_DA1_MASK); + regmap_write(miig_rt, offset, 0xffff); + + /* Setup Classifier 4 */ + /* match on multicast, broadcast or unicast (ft1-0 address) */ + data = RX_CLASS_FT_MC | RX_CLASS_FT_BC | FT1_MATCH_SLOT(0); + rx_class_set_or(miig_rt, slice, 4, data); + + /* set CFG1 for OR_OR_AND for classifier 4 */ + rx_class_sel_set_type(miig_rt, slice, 4, RX_CLASS_SEL_TYPE_OR_OR_AND); + + /* ungate classifier 4 */ + offset = RX_CLASS_GATES_N_REG(slice, 4); + regmap_read(miig_rt, offset, &data); + data |= RX_CLASS_GATES_RAW_MASK; + regmap_write(miig_rt, offset, data); +} + +void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac) +{ + u32 mac0, mac1; + + mac0 = mac[0] | mac[1] << 8 | + mac[2] << 16 | mac[3] << 24; + mac1 = mac[4] | mac[5] << 8; + + regmap_write(miig_rt, offs[slice].mac0, mac0); + regmap_write(miig_rt, offs[slice].mac1, mac1); +}

On Tue, Aug 06, 2019 at 04:08:36PM +0530, Keerthy wrote:
This is the Ethernet driver for TI SoCs with the ICSSG PRU Sub-system running EMAC firmware. This driver caters to either of the slices(pru/rtu pair) of the icssg subsystem.
Following are the firmwares needed to run cores:
am65x-pru0-prueth-fw.elf for pru0 of slice0 am65x-rtu0-prueth-fw.elf for rtu0 of slice0 am65x-pru1-prueth-fw.elf for pru1 of slice1 am65x-rtu1-prueth-fw.elf for rtu1 of slice1
One and exactly one of the slices is supported as the u-boot ethernet supports probing one interface at a time.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/net/ti/Kconfig | 8 + drivers/net/ti/Makefile | 1 + drivers/net/ti/icssg-prueth.c | 517 ++++++++++++++++++++++++++++++ drivers/net/ti/icssg.h | 31 ++ drivers/net/ti/icssg_classifier.c | 397 +++++++++++++++++++++++ 5 files changed, 954 insertions(+) create mode 100644 drivers/net/ti/icssg-prueth.c create mode 100644 drivers/net/ti/icssg.h create mode 100644 drivers/net/ti/icssg_classifier.c
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig index ecf642de10..1b6285709f 100644 --- a/drivers/net/ti/Kconfig +++ b/drivers/net/ti/Kconfig @@ -26,3 +26,11 @@ config TI_AM65_CPSW_NUSS help This driver supports TI K3 MCU CPSW Nuss Ethernet controller in Texas Instruments K3 AM65x SoCs.
+config TI_AM64_ICSSG_PRUETH
- bool "TI Gigabit PRU Ethernet driver"
- depends on ARCH_K3
- select PHYLIB
- help
Support Gigabit Ethernet ports over the ICSSG PRU Subsystem
This subsystem is available starting with the AM65 platform.
diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile index 8d3808bb4b..b486498909 100644 --- a/drivers/net/ti/Makefile +++ b/drivers/net/ti/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o cpsw_mdio.o obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o cpsw_mdio.o +obj-$(CONFIG_TI_AM64_ICSSG_PRUETH) += icssg-prueth.o cpsw_mdio.o icssg_classifier.o diff --git a/drivers/net/ti/icssg-prueth.c b/drivers/net/ti/icssg-prueth.c new file mode 100644 index 0000000000..f8935ee087 --- /dev/null +++ b/drivers/net/ti/icssg-prueth.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Texas Instruments K3 AM65 PRU Ethernet Driver
If the driver is AM65x specific that should be reflected in the driver name, like already done for CPSW_NUSS, for consistency and scalability sake.
- Copyright (C) 2019, Texas Instruments, Incorporated
- */
+#include <common.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <clk.h> +#include <dm.h> +#include <dm/lists.h> +#include <dm/device.h> +#include <dma-uclass.h> +#include <dm/of_access.h> +#include <fs_loader.h> +#include <miiphy.h> +#include <misc.h> +#include <net.h> +#include <phy.h> +#include <power-domain.h> +#include <linux/soc/ti/ti-udma.h> +#include <regmap.h> +#include <remoteproc.h> +#include <syscon.h> +#include <ti-pruss.h>
+#include "cpsw_mdio.h" +#include "icssg.h"
+#define ICSS_SLICE0 0 +#define ICSS_SLICE1 1
+#ifdef PKTSIZE_ALIGN +#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN +#else +#define UDMA_RX_BUF_SIZE ALIGN(1522, ARCH_DMA_MINALIGN) +#endif
+#ifdef PKTBUFSRX +#define UDMA_RX_DESC_NUM PKTBUFSRX +#else +#define UDMA_RX_DESC_NUM 4 +#endif
+enum prueth_mac {
- PRUETH_MAC0 = 0,
- PRUETH_MAC1,
- PRUETH_NUM_MACS,
+};
+enum prueth_port {
- PRUETH_PORT_HOST = 0, /* host side port */
- PRUETH_PORT_MII0, /* physical port MII 0 */
- PRUETH_PORT_MII1, /* physical port MII 1 */
+};
+/* Config region lies in shared RAM */ +#define ICSS_CONFIG_OFFSET_SLICE0 0 +#define ICSS_CONFIG_OFFSET_SLICE1 0x8000
+/* Firmware flags */ +#define ICSS_SET_RUN_FLAG_VLAN_ENABLE BIT(0) /* switch only */ +#define ICSS_SET_RUN_FLAG_FLOOD_UNICAST BIT(1) /* switch only */ +#define ICSS_SET_RUN_FLAG_PROMISC BIT(2) /* MAC only */ +#define ICSS_SET_RUN_FLAG_MULTICAST_PROMISC BIT(3) /* MAC only */
+/* CTRLMMR_ICSSG_RGMII_CTRL register bits */ +#define ICSSG_CTRL_RGMII_ID_MODE BIT(24)
+/**
- enum pruss_pru_id - PRU core identifiers
- */
+enum pruss_pru_id {
- PRUSS_PRU0 = 0,
- PRUSS_PRU1,
- PRUSS_NUM_PRUS,
+};
+struct prueth {
- struct udevice *dev;
- struct regmap *miig_rt;
- fdt_addr_t mdio_base;
- phys_addr_t pruss_shrdram2;
- struct mii_dev *bus;
- u32 port_id;
- u32 sram_pa;
- struct phy_device *phydev;
- bool has_phy;
- ofnode phy_node;
- u32 phy_addr;
- ofnode eth_node[PRUETH_NUM_MACS];
- struct icssg_config config[PRUSS_NUM_PRUS];
- u32 mdio_freq;
- int phy_interface;
- struct clk mdiofck;
- struct dma dma_tx;
- struct dma dma_rx;
- u32 rx_next;
- u32 rx_pend;
- int slice;
+};
+static int icssg_phy_init(struct udevice *dev) +{
- struct prueth *priv = dev_get_priv(dev);
- struct phy_device *phydev;
- u32 supported = PHY_GBIT_FEATURES;
- int ret;
- phydev = phy_connect(priv->bus,
priv->phy_addr,
priv->dev,
priv->phy_interface);
- if (!phydev) {
dev_err(dev, "phy_connect() failed\n");
return -ENODEV;
- }
- phydev->supported &= supported;
- phydev->advertising = phydev->supported;
+#ifdef CONFIG_DM_ETH
- if (ofnode_valid(priv->phy_node))
phydev->node = priv->phy_node;
+#endif
- priv->phydev = phydev;
- ret = phy_config(phydev);
- if (ret < 0)
pr_err("phy_config() failed: %d", ret);
- return ret;
+}
+static int icssg_mdio_init(struct udevice *dev) +{
- struct prueth *prueth = dev_get_priv(dev);
- prueth->bus = cpsw_mdio_init(dev->name, prueth->mdio_base,
prueth->mdio_freq,
clk_get_rate(&prueth->mdiofck));
- if (!prueth->bus)
return -EFAULT;
- return 0;
+}
+static void icssg_config_set(struct prueth *prueth) +{
- void __iomem *va;
- va = (void __iomem *)prueth->pruss_shrdram2 + prueth->slice *
ICSSG_CONFIG_OFFSET_SLICE1;
- memcpy_toio(va, &prueth->config[0], sizeof(prueth->config[0]));
+}
+static int prueth_start(struct udevice *dev) +{
- struct prueth *priv = dev_get_priv(dev);
- struct eth_pdata *pdata = dev->platdata;
- int ret, i;
- char tx_chn_name[16];
- char rx_chn_name[16];
- icssg_class_set_mac_addr(priv->miig_rt, priv->slice,
(u8 *)pdata->enetaddr);
- icssg_class_default(priv->miig_rt, priv->slice);
- /* To differentiate channels for SLICE0 vs SLICE1 */
- snprintf(tx_chn_name, sizeof(tx_chn_name), "tx%d-0", priv->slice);
- snprintf(rx_chn_name, sizeof(rx_chn_name), "rx%d", priv->slice);
- ret = dma_get_by_name(dev, tx_chn_name, &priv->dma_tx);
- if (ret)
dev_err(dev, "TX dma get failed %d\n", ret);
Should we return on errors? Same comment applies to the statements immediately following this...
- ret = dma_get_by_name(dev, rx_chn_name, &priv->dma_rx);
- if (ret)
dev_err(dev, "RX dma get failed %d\n", ret);
- for (i = 0; i < UDMA_RX_DESC_NUM; i++) {
ret = dma_prepare_rcv_buf(&priv->dma_rx,
net_rx_packets[i],
UDMA_RX_BUF_SIZE);
if (ret)
dev_err(dev, "RX dma add buf failed %d\n", ret);
- }
- ret = dma_enable(&priv->dma_tx);
- if (ret) {
dev_err(dev, "TX dma_enable failed %d\n", ret);
return ret;
- }
- ret = dma_enable(&priv->dma_rx);
- if (ret) {
dev_err(dev, "RX dma_enable failed %d\n", ret);
goto rx_fail;
- }
- ret = phy_startup(priv->phydev);
- if (ret) {
dev_err(dev, "phy_startup failed\n");
goto phy_fail;
- }
- return 0;
+phy_fail:
- dma_disable(&priv->dma_rx);
+rx_fail:
- dma_disable(&priv->dma_tx);
- return ret;
+}
+void prueth_print_buf(ulong addr, const void *data, uint width,
uint count, uint linelen)
+{
- print_buffer(addr, data, width, count, linelen);
+}
This function does not appear to be used? If so please remove...
+static int prueth_send(struct udevice *dev, void *packet, int length) +{
- struct prueth *priv = dev_get_priv(dev);
- int ret;
- ret = dma_send(&priv->dma_tx, packet, length, NULL);
- return ret;
+}
+static int prueth_recv(struct udevice *dev, int flags, uchar **packetp) +{
- struct prueth *priv = dev_get_priv(dev);
- int ret;
- /* try to receive a new packet */
- ret = dma_receive(&priv->dma_rx, (void **)packetp, NULL);
- return ret;
+}
+static int prueth_free_pkt(struct udevice *dev, uchar *packet, int length) +{
- struct prueth *priv = dev_get_priv(dev);
- int ret = 0;
- if (length > 0) {
u32 pkt = priv->rx_next % UDMA_RX_DESC_NUM;
dev_dbg(dev, "%s length:%d pkt:%u\n", __func__, length, pkt);
ret = dma_prepare_rcv_buf(&priv->dma_rx,
net_rx_packets[pkt],
UDMA_RX_BUF_SIZE);
priv->rx_next++;
- }
- return ret;
+}
+static void prueth_stop(struct udevice *dev) +{
- struct prueth *priv = dev_get_priv(dev);
- icssg_class_disable(priv->miig_rt, priv->slice);
- phy_shutdown(priv->phydev);
- dma_disable(&priv->dma_tx);
- dma_free(&priv->dma_tx);
- dma_disable(&priv->dma_rx);
- dma_free(&priv->dma_rx);
+}
+static const struct eth_ops prueth_ops = {
- .start = prueth_start,
- .send = prueth_send,
- .recv = prueth_recv,
- .free_pkt = prueth_free_pkt,
- .stop = prueth_stop,
+};
+static int icssg_ofdata_parse_phy(struct udevice *dev, ofnode port_np) +{
- struct prueth *priv = dev_get_priv(dev);
- struct ofnode_phandle_args out_args;
- const char *phy_mode;
- int ret = 0;
- phy_mode = ofnode_read_string(port_np, "phy-mode");
- if (phy_mode) {
priv->phy_interface =
phy_get_interface_by_name(phy_mode);
if (priv->phy_interface == -1) {
dev_err(dev, "Invalid PHY mode '%s'\n",
phy_mode);
ret = -EINVAL;
goto out;
}
- }
- ret = ofnode_parse_phandle_with_args(port_np, "phy-handle",
NULL, 0, 0, &out_args);
- if (ret) {
dev_err(dev, "can't parse phy-handle port (%d)\n", ret);
ret = 0;
- }
- priv->phy_node = out_args.node;
- ret = ofnode_read_u32(priv->phy_node, "reg", &priv->phy_addr);
- if (ret)
dev_err(dev, "failed to get phy_addr port (%d)\n", ret);
+out:
- return ret;
+}
+static int prueth_config_rgmiidelay(struct prueth *prueth,
ofnode eth_np)
+{
- struct regmap *ctrl_mmr;
- u32 val;
- int ret = 0;
- ofnode node;
- u32 tmp[2];
- ret = ofnode_read_u32_array(eth_np, "syscon-rgmii-delay", tmp, 2);
- if (ret) {
dev_err(dev, "no syscon-rgmii-delay\n");
return ret;
- }
- node = ofnode_get_by_phandle(tmp[0]);
- if (!ofnode_valid(node)) {
dev_err(dev, "can't get syscon-rgmii-delay node\n");
return -EINVAL;
- }
- ctrl_mmr = syscon_node_to_regmap(node);
- if (!ctrl_mmr) {
dev_err(dev, "can't get ctrl_mmr regmap\n");
return -EINVAL;
- }
- if (ofnode_read_bool(eth_np, "enable-rgmii-delay"))
val = 0;
- else
val = ICSSG_CTRL_RGMII_ID_MODE;
- regmap_update_bits(ctrl_mmr, tmp[1], ICSSG_CTRL_RGMII_ID_MODE, val);
- return 0;
+}
+static int prueth_probe(struct udevice *dev) +{
- struct prueth *prueth;
- int ret = 0, i;
- ofnode eth0_node, eth1_node, node, pruss_node, mdio_node, sram_node;
- u32 phandle, err, sp;
- struct udevice **prussdev = NULL;
- struct icssg_config *config;
- prueth = dev_get_priv(dev);
- prueth->dev = dev;
- err = ofnode_read_u32(dev_ofnode(dev), "prus", &phandle);
- if (err)
return err;
- node = ofnode_get_by_phandle(phandle);
- if (!ofnode_valid(node))
return -EINVAL;
- pruss_node = ofnode_get_parent(node);
- err = misc_init_by_ofnode(pruss_node);
- if (err)
return err;
- ret = device_find_global_by_ofnode(pruss_node, prussdev);
- if (ret)
dev_err(dev, "error getting the pruss dev\n");
Should we not exit here?
- ret = pruss_request_shrmem_region(*prussdev, &prueth->pruss_shrdram2);
- if (ret)
return ret;
- node = dev_ofnode(dev);
- eth0_node = ofnode_find_subnode(node, "ethernet-mii0");
- eth1_node = ofnode_find_subnode(node, "ethernet-mii1");
- /* one node must be present and available else we fail */
- if (!ofnode_valid(eth0_node) && !ofnode_valid(eth1_node)) {
dev_err(dev, "neither ethernet-mii0 nor ethernet-mii1 node available\n");
return -ENODEV;
- }
- /*
* Exactly one node must be present as uboot ethernet framework does
* not support two interfaces in a single probe. So Device Tree should
* have exactly one of mii0 or mii1 interface.
*/
- if (ofnode_valid(eth0_node) && ofnode_valid(eth1_node)) {
dev_err(dev, "Both slices cannot be supported\n");
return -EINVAL;
- }
- if (ofnode_valid(eth0_node)) {
prueth->slice = 0;
icssg_ofdata_parse_phy(dev, eth0_node);
prueth->eth_node[PRUETH_MAC0] = eth0_node;
- }
- if (ofnode_valid(eth1_node)) {
prueth->slice = 1;
icssg_ofdata_parse_phy(dev, eth1_node);
prueth->eth_node[PRUETH_MAC0] = eth1_node;
- }
- prueth->miig_rt = syscon_regmap_lookup_by_phandle(dev, "mii-g-rt");
- if (!prueth->miig_rt) {
dev_err(dev, "couldn't get mii-g-rt syscon regmap\n");
return -ENODEV;
- }
- ret = clk_get_by_name(dev, "mdio_fck", &prueth->mdiofck);
- if (ret) {
dev_err(dev, "failed to get clock %d\n", ret);
return ret;
- }
Blank line here for consistency with other statements.
- ret = clk_enable(&prueth->mdiofck);
- if (ret) {
dev_err(dev, "clk_enable failed %d\n", ret);
return ret;
- }
- ret = ofnode_read_u32(dev_ofnode(dev), "sram", &sp);
- if (ret) {
dev_err(dev, "sram node fetch failed %d\n", ret);
return ret;
- }
- sram_node = ofnode_get_by_phandle(sp);
- if (!ofnode_valid(node))
return -EINVAL;
- prueth->sram_pa = ofnode_get_addr(sram_node);
- if (!prueth->slice) {
ret = prueth_config_rgmiidelay(prueth, eth0_node);
if (ret) {
dev_err(dev, "prueth_config_rgmiidelay failed\n");
return ret;
}
- } else {
ret = prueth_config_rgmiidelay(prueth, eth1_node);
if (ret) {
dev_err(dev, "prueth_config_rgmiidelay failed\n");
return ret;
}
- }
- mdio_node = ofnode_find_subnode(pruss_node, "mdio");
- prueth->mdio_base = ofnode_get_addr(mdio_node);
- ofnode_read_u32(mdio_node, "bus_freq", &prueth->mdio_freq);
- ret = icssg_mdio_init(dev);
- if (ret)
return ret;
- ret = icssg_phy_init(dev);
- if (ret) {
dev_err(dev, "phy_init failed\n");
goto out;
- }
- /* Set Load time configuration */
- config = &prueth->config[0];
- memset(config, 0, sizeof(*config));
- config->addr_lo = cpu_to_le32(lower_32_bits(prueth->sram_pa));
- config->addr_hi = cpu_to_le32(upper_32_bits(prueth->sram_pa));
- config->num_tx_threads = 0;
- config->rx_flow_id = 0; /* flow id for host port */
- for (i = 8; i < 16; i++)
tx_buf_sz is 16 elements in size. What is different about elements 0...7 so that they don't need to get intialized?
config->tx_buf_sz[i] = cpu_to_le32(0x1800);
- icssg_config_set(prueth);
- return 0;
+out:
- cpsw_mdio_free(prueth->bus);
- clk_disable(&prueth->mdiofck);
- return ret;
+}
+static const struct udevice_id prueth_ids[] = {
- { .compatible = "ti,am654-icssg-prueth" },
- { }
+};
+U_BOOT_DRIVER(prueth) = {
- .name = "prueth",
- .id = UCLASS_ETH,
- .of_match = prueth_ids,
- .probe = prueth_probe,
- .ops = &prueth_ops,
- .priv_auto_alloc_size = sizeof(struct prueth),
- .platdata_auto_alloc_size = sizeof(struct eth_pdata),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+}; diff --git a/drivers/net/ti/icssg.h b/drivers/net/ti/icssg.h new file mode 100644 index 0000000000..2e881e6eb3 --- /dev/null +++ b/drivers/net/ti/icssg.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver
- Copyright (C) 2019, Texas Instruments, Incorporated
- */
Header file needs include guards. Needs blank line here.
+void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac); +void icssg_class_disable(struct regmap *miig_rt, int slice); +void icssg_class_default(struct regmap *miig_rt, int slice); +void icssg_class_promiscuous(struct regmap *miig_rt, int slice);
Typically the order of declarations in header files is...
1) defines 2) types 3) function prototypes
+/* Config area lies in shared RAM */ +#define ICSSG_CONFIG_OFFSET_SLICE0 0 +#define ICSSG_CONFIG_OFFSET_SLICE1 0x8000
+/* Load time Fiwmware Configuration */ +struct icssg_config {
- __le32 status; /* Firmware status */
- __le32 addr_lo; /* MSMC Buffer pool base address low. */
- __le32 addr_hi; /* MSMC Buffer pool base address high. Must be 0 */
- __le32 tx_buf_sz[16]; /* Array of buffer pool sizes */
- __le32 num_tx_threads; /* Number of active egress threads, 1 to 4 */
- __le32 tx_rate_lim_en; /* Bitmask: Egress rate limit enable per thread */
- __le32 rx_flow_id; /* RX flow id for first rx ring */
- __le32 rx_mgr_flow_id; /* RX flow id for the first management ring */
- __le32 flags; /* TBD */
- __le32 n_burst; /* for debug */
- __le32 rtu_status; /* RTU status */
- __le32 info; /* reserved */
+} __packed; diff --git a/drivers/net/ti/icssg_classifier.c b/drivers/net/ti/icssg_classifier.c new file mode 100644 index 0000000000..2af14ed5b2 --- /dev/null +++ b/drivers/net/ti/icssg_classifier.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet Driver
- Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
2019
- */
+#include <common.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <clk.h> +#include <dm.h> +#include <dm/lists.h> +#include <dm/device.h> +#include <dma-uclass.h> +#include <dm/of_access.h> +#include <miiphy.h> +#include <net.h> +#include <phy.h> +#include <power-domain.h> +#include <linux/soc/ti/ti-udma.h> +#include <syscon.h> +#include <ti-pruss.h> +#include <regmap.h>
+#include "cpsw_mdio.h" +#include "icssg.h"
+#define ICSSG_NUM_CLASSIFIERS 16 +#define ICSSG_NUM_FT1_SLOTS 8 +#define ICSSG_NUM_FT3_SLOTS 16
+/* Filter 1 - FT1 */ +#define FT1_NUM_SLOTS 8 +#define FT1_SLOT_SIZE 0x10 /* bytes */
+/* offsets from FT1 slot base i.e. slot 1 start */ +#define FT1_DA0 0x0 +#define FT1_DA1 0x4 +#define FT1_DA0_MASK 0x8 +#define FT1_DA1_MASK 0xc
+#define FT1_N_REG(slize, n, reg) (offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg))
+#define FT1_LEN_MASK GENMASK(19, 16) +#define FT1_LEN_SHIFT 16 +#define FT1_LEN(len) (((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK)
+#define FT1_MATCH_SLOT(n) (GENMASK(23, 16) & (BIT(n) << 16))
+enum ft1_cfg_type {
- FT1_CFG_TYPE_DISABLED = 0,
- FT1_CFG_TYPE_EQ,
- FT1_CFG_TYPE_GT,
- FT1_CFG_TYPE_LT,
+};
+#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n)))
+/* Filter 3 - FT3 */ +#define FT3_NUM_SLOTS 16 +#define FT3_SLOT_SIZE 0x20 /* bytes */
+/* offsets from FT3 slot n's base */ +#define FT3_START 0 +#define FT3_START_AUTO 0x4 +#define FT3_START_OFFSET 0x8 +#define FT3_JUMP_OFFSET 0xc +#define FT3_LEN 0x10 +#define FT3_CFG 0x14 +#define FT3_T 0x18 +#define FT3_T_MASK 0x1c
+#define FT3_N_REG(slize, n, reg) (offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg))
+/* offsets from rx_class n's base */ +#define RX_CLASS_AND_EN 0 +#define RX_CLASS_OR_EN 0x4
+#define RX_CLASS_NUM_SLOTS 16 +#define RX_CLASS_EN_SIZE 0x8 /* bytes */
+#define RX_CLASS_N_REG(slice, n, reg) (offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg))
+/* RX Class Gates */ +#define RX_CLASS_GATES_SIZE 0x4 /* bytes */
+#define RX_CLASS_GATES_N_REG(slice, n) (offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n))
+#define RX_CLASS_GATES_ALLOW_MASK BIT(6) +#define RX_CLASS_GATES_RAW_MASK BIT(5) +#define RX_CLASS_GATES_PHASE_MASK BIT(4)
+/* RX Class traffic data matching bits */ +#define RX_CLASS_FT_UC BIT(31) +#define RX_CLASS_FT_MC BIT(30) +#define RX_CLASS_FT_BC BIT(29) +#define RX_CLASS_FT_FW BIT(28) +#define RX_CLASS_FT_RCV BIT(27) +#define RX_CLASS_FT_VLAN BIT(26) +#define RX_CLASS_FT_DA_P BIT(25) +#define RX_CLASS_FT_DA_I BIT(24) +#define RX_CLASS_FT_FT1_MATCH_MASK GENMASK(23, 16) +#define RX_CLASS_FT_FT1_MATCH_SHIFT 16 +#define RX_CLASS_FT_FT3_MATCH_MASK GENMASK(15, 0) +#define RX_CLASS_FT_FT3_MATCH_SHIFT 0
+enum rx_class_sel_type {
- RX_CLASS_SEL_TYPE_OR = 0,
- RX_CLASS_SEL_TYPE_AND = 1,
- RX_CLASS_SEL_TYPE_OR_AND_AND = 2,
- RX_CLASS_SEL_TYPE_OR_OR_AND = 3,
+};
+#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n)))
+#define RX_CLASS_SEL_SHIFT(n) (2 * (n)) +#define RX_CLASS_SEL_MASK(n) (0x3 << RX_CLASS_SEL_SHIFT((n)))
+#define ICSSG_CFG_OFFSET 0 +#define RGMII_CFG_OFFSET 4
+#define ICSSG_CFG_RX_L2_G_EN BIT(2)
+/* these are register offsets per PRU */ +struct miig_rt_offsets {
- u32 mac0;
- u32 mac1;
- u32 ft1_start_len;
- u32 ft1_cfg;
- u32 ft1_slot_base;
- u32 ft3_slot_base;
- u32 ft3_p_base;
- u32 ft_rx_ptr;
- u32 rx_class_base;
- u32 rx_class_cfg1;
- u32 rx_class_cfg2;
- u32 rx_class_gates_base;
- u32 rx_green;
- u32 rx_rate_cfg_base;
- u32 rx_rate_src_sel0;
- u32 rx_rate_src_sel1;
- u32 tx_rate_cfg_base;
- u32 stat_base;
- u32 tx_hsr_tag;
- u32 tx_hsr_seq;
- u32 tx_vlan_type;
- u32 tx_vlan_ins;
+};
+static struct miig_rt_offsets offs[] = {
- /* PRU0 */
- {
0x8,
0xc,
0x80,
0x84,
0x88,
0x108,
0x308,
0x408,
0x40c,
0x48c,
0x490,
0x494,
0x4d4,
0x4e4,
0x504,
0x508,
0x50c,
0x54c,
0x63c,
0x640,
0x644,
0x648,
- },
- /* PRU1 */
- {
0x10,
0x14,
0x64c,
0x650,
0x654,
0x6d4,
0x8d4,
0x9d4,
0x9d8,
0xa58,
0xa5c,
0xa60,
0xaa0,
0xab0,
0xad0,
0xad4,
0xad8,
0xb18,
0xc08,
0xc0c,
0xc10,
0xc14,
- },
+};
+static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n,
enum ft1_cfg_type type)
+{
- u32 offset;
- offset = offs[slice].ft1_cfg;
- regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n),
type << FT1_CFG_SHIFT(n));
+}
+static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n,
enum rx_class_sel_type type)
+{
- u32 offset;
- offset = offs[slice].rx_class_cfg1;
- regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n),
type << RX_CLASS_SEL_SHIFT(n));
+}
+static void rx_class_set_and(struct regmap *miig_rt, int slice, int n,
u32 data)
+{
- u32 offset;
- offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN);
- regmap_write(miig_rt, offset, data);
+}
+static void rx_class_set_or(struct regmap *miig_rt, int slice, int n,
u32 data)
+{
- u32 offset;
- offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
- regmap_write(miig_rt, offset, data);
+}
+/* disable all RX traffic */ +void icssg_class_disable(struct regmap *miig_rt, int slice) +{
- u32 data, offset;
- int n;
- /* Enable RX_L2_G */
- regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN,
ICSSG_CFG_RX_L2_G_EN);
- for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++) {
/* AND_EN = 0 */
rx_class_set_and(miig_rt, slice, n, 0);
/* OR_EN = 0 */
rx_class_set_or(miig_rt, slice, n, 0);
/* set CFG1 to OR */
rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR);
/* configure gate */
offset = RX_CLASS_GATES_N_REG(slice, n);
regmap_read(miig_rt, offset, &data);
/* clear class_raw */
data &= ~RX_CLASS_GATES_RAW_MASK;
/* set allow and phase mask */
data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK;
regmap_write(miig_rt, offset, data);
- }
- /* FT1 uses 6 bytes of DA address */
- offset = offs[slice].ft1_start_len;
- regmap_write(miig_rt, offset, FT1_LEN(6));
- /* FT1 type EQ */
- for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++)
rx_class_ft1_cfg_set_type(miig_rt, slice, n, FT1_CFG_TYPE_EQ);
- /* FT1[0] DA compare address 00-00-00-00-00-00 */
- offset = FT1_N_REG(slice, 0, FT1_DA0);
- regmap_write(miig_rt, offset, 0);
- offset = FT1_N_REG(slice, 0, FT1_DA1);
- regmap_write(miig_rt, offset, 0);
- /* FT1[0] mask FE-FF-FF-FF-FF-FF */
- offset = FT1_N_REG(slice, 0, FT1_DA0_MASK);
- regmap_write(miig_rt, offset, 0);
- offset = FT1_N_REG(slice, 0, FT1_DA1_MASK);
- regmap_write(miig_rt, offset, 0);
- /* clear CFG2 */
- regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
+}
+void icssg_class_default(struct regmap *miig_rt, int slice) +{
- u32 offset, data;
- int n;
- /* defaults */
- icssg_class_disable(miig_rt, slice);
- /* FT1 uses 6 bytes of DA address */
- offset = offs[slice].ft1_start_len;
- regmap_write(miig_rt, offset, FT1_LEN(6));
- /* FT1 slots to EQ */
- for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++)
rx_class_ft1_cfg_set_type(miig_rt, slice, n, FT1_CFG_TYPE_EQ);
- /* FT1[0] DA compare address 00-00-00-00-00-00 */
- offset = FT1_N_REG(slice, 0, FT1_DA0);
- regmap_write(miig_rt, offset, 0);
- offset = FT1_N_REG(slice, 0, FT1_DA1);
- regmap_write(miig_rt, offset, 0);
- /* FT1[0] mask 00-00-00-00-00-00 */
- offset = FT1_N_REG(slice, 0, FT1_DA0_MASK);
- regmap_write(miig_rt, offset, 0);
- offset = FT1_N_REG(slice, 0, FT1_DA1_MASK);
- regmap_write(miig_rt, offset, 0);
- /* Setup Classifier 4 */
- /* match on Broadcast or MAC_PRU address */
- data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;
- rx_class_set_or(miig_rt, slice, 4, data);
- /* set CFG1 for OR_OR_AND for classifier 4 */
- rx_class_sel_set_type(miig_rt, slice, 4, RX_CLASS_SEL_TYPE_OR_OR_AND);
- /* ungate classifier 4 */
- offset = RX_CLASS_GATES_N_REG(slice, 4);
- regmap_read(miig_rt, offset, &data);
- data |= RX_CLASS_GATES_RAW_MASK;
- regmap_write(miig_rt, offset, data);
- /* clear CFG2 */
- regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
+}
+void icssg_class_promiscuous(struct regmap *miig_rt, int slice) +{
- u32 data;
- u32 offset;
- int n;
- /* defaults */
- icssg_class_disable(miig_rt, slice);
- /* FT1 uses 6 bytes of DA address */
- offset = offs[slice].ft1_start_len;
- regmap_write(miig_rt, offset, FT1_LEN(6));
- /* FT1 type EQ */
- for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++)
rx_class_ft1_cfg_set_type(miig_rt, slice, n, FT1_CFG_TYPE_EQ);
- /* FT1[0] DA compare address 00-00-00-00-00-00 */
- offset = FT1_N_REG(slice, 0, FT1_DA0);
- regmap_write(miig_rt, offset, 0);
- offset = FT1_N_REG(slice, 0, FT1_DA1);
- regmap_write(miig_rt, offset, 0);
- /* FT1[0] mask FE-FF-FF-FF-FF-FF */
- offset = FT1_N_REG(slice, 0, FT1_DA0_MASK);
- regmap_write(miig_rt, offset, 0xfffffffe);
- offset = FT1_N_REG(slice, 0, FT1_DA1_MASK);
- regmap_write(miig_rt, offset, 0xffff);
- /* Setup Classifier 4 */
- /* match on multicast, broadcast or unicast (ft1-0 address) */
- data = RX_CLASS_FT_MC | RX_CLASS_FT_BC | FT1_MATCH_SLOT(0);
- rx_class_set_or(miig_rt, slice, 4, data);
- /* set CFG1 for OR_OR_AND for classifier 4 */
- rx_class_sel_set_type(miig_rt, slice, 4, RX_CLASS_SEL_TYPE_OR_OR_AND);
- /* ungate classifier 4 */
- offset = RX_CLASS_GATES_N_REG(slice, 4);
- regmap_read(miig_rt, offset, &data);
- data |= RX_CLASS_GATES_RAW_MASK;
- regmap_write(miig_rt, offset, data);
+}
+void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac) +{
- u32 mac0, mac1;
- mac0 = mac[0] | mac[1] << 8 |
mac[2] << 16 | mac[3] << 24;
This could be in one line ^^
-- Andreas Dannenberg Texas Instruments Inc
- mac1 = mac[4] | mac[5] << 8;
- regmap_write(miig_rt, offs[slice].mac0, mac0);
- regmap_write(miig_rt, offs[slice].mac1, mac1);
+}
2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

Currently shutdown command is yet to be implemented. So work around clearing the task manager of ICSSG.
Signed-off-by: Keerthy j-keerthy@ti.com --- drivers/net/ti/icssg-prueth.c | 8 ++++++++ drivers/soc/ti/pruss.c | 15 +++++++++++++++ include/ti-pruss.h | 1 + 3 files changed, 24 insertions(+)
diff --git a/drivers/net/ti/icssg-prueth.c b/drivers/net/ti/icssg-prueth.c index f8935ee087..980a1d9ee8 100644 --- a/drivers/net/ti/icssg-prueth.c +++ b/drivers/net/ti/icssg-prueth.c @@ -84,6 +84,7 @@ struct prueth { struct regmap *miig_rt; fdt_addr_t mdio_base; phys_addr_t pruss_shrdram2; + phys_addr_t tmaddr; struct mii_dev *bus; u32 port_id; u32 sram_pa; @@ -277,6 +278,9 @@ static void prueth_stop(struct udevice *dev)
dma_disable(&priv->dma_rx); dma_free(&priv->dma_rx); + + /* Workaround for shutdown command */ + writel(0x0, priv->tmaddr + priv->slice * 0x200); }
static const struct eth_ops prueth_ops = { @@ -391,6 +395,10 @@ static int prueth_probe(struct udevice *dev) if (ret) return ret;
+ ret = pruss_request_tm_region(*prussdev, &prueth->tmaddr); + if (ret) + return ret; + node = dev_ofnode(dev); eth0_node = ofnode_find_subnode(node, "ethernet-mii0"); eth1_node = ofnode_find_subnode(node, "ethernet-mii1"); diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 03ddaaa539..0d53d0a26b 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -21,6 +21,8 @@ #define PRUSS_CFG_IEPCLK 0x30 #define ICSSG_CFG_CORE_SYNC 0x3c
+#define ICSSG_TASK_MGR_OFFSET 0x2a000 + /* PRUSS_IEPCLK register bits */ #define PRUSS_IEPCLK_IEP_OCP_CLK_EN BIT(0)
@@ -37,6 +39,19 @@ enum pruss_mem { PRUSS_MEM_MAX, };
+int pruss_request_tm_region(struct udevice *dev, phys_addr_t *loc) +{ + struct pruss *priv; + + priv = dev_get_priv(dev); + if (!priv || !priv->pruss_dram0) + return -EINVAL; + + *loc = priv->pruss_dram0 + ICSSG_TASK_MGR_OFFSET; + + return 0; +} + int pruss_request_shrmem_region(struct udevice *dev, phys_addr_t *loc) { struct pruss *priv; diff --git a/include/ti-pruss.h b/include/ti-pruss.h index 547ec5ee33..9eadeef172 100644 --- a/include/ti-pruss.h +++ b/include/ti-pruss.h @@ -10,3 +10,4 @@ struct pruss { };
int pruss_request_shrmem_region(struct udevice *dev, phys_addr_t *loc); +int pruss_request_tm_region(struct udevice *dev, phys_addr_t *loc);

Add msmc_ram node needed for prueth
Signed-off-by: Keerthy j-keerthy@ti.com --- arch/arm/dts/k3-am65-main.dtsi | 21 +++++++++++++++++++++ arch/arm/dts/k3-am65.dtsi | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index 7d03706057..8e2a506185 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -6,6 +6,27 @@ */
&cbass_main { + msmc_ram: sram@70000000 { + compatible = "mmio-sram"; + reg = <0x0 0x70000000 0x0 0x200000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x70000000 0x200000>; + u-boot,dm-spl; + + atf-sram@0 { + reg = <0x0 0x20000>; + }; + + sysfw-sram@f0000 { + reg = <0xf0000 0x10000>; + }; + + l3cache-sram@100000 { + reg = <0x100000 0x100000>; + }; + }; + gic500: interrupt-controller@1800000 { compatible = "arm,gic-v3"; #address-cells = <2>; diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi index a3abd146d1..431b27813a 100644 --- a/arch/arm/dts/k3-am65.dtsi +++ b/arch/arm/dts/k3-am65.dtsi @@ -76,7 +76,9 @@ <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, - <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>; + <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, + <0x07 0x00000000 0x07 0x00000000 0x01 0x0000000>, + <0x00 0x70000000 0x00 0x70000000 0x00 0x00200000>;
cbass_mcu: interconnect@28380000 { compatible = "simple-bus";

On Tue, Aug 06, 2019 at 04:08:38PM +0530, Keerthy wrote:
Add msmc_ram node needed for prueth
Signed-off-by: Keerthy j-keerthy@ti.com
arch/arm/dts/k3-am65-main.dtsi | 21 +++++++++++++++++++++ arch/arm/dts/k3-am65.dtsi | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index 7d03706057..8e2a506185 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -6,6 +6,27 @@ */
&cbass_main {
- msmc_ram: sram@70000000 {
compatible = "mmio-sram";
reg = <0x0 0x70000000 0x0 0x200000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x70000000 0x200000>;
u-boot,dm-spl;
atf-sram@0 {
reg = <0x0 0x20000>;
};
sysfw-sram@f0000 {
reg = <0xf0000 0x10000>;
};
l3cache-sram@100000 {
reg = <0x100000 0x100000>;
};
- };
- gic500: interrupt-controller@1800000 { compatible = "arm,gic-v3"; #address-cells = <2>;
diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi index a3abd146d1..431b27813a 100644 --- a/arch/arm/dts/k3-am65.dtsi +++ b/arch/arm/dts/k3-am65.dtsi @@ -76,7 +76,9 @@ <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>,
<0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>;
<0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>,
<0x07 0x00000000 0x07 0x00000000 0x01 0x0000000>,
Should align the width of the last block of zeroes with the other numbers...
-- Andreas Dannenberg Texas Instruments Inc
<0x00 0x70000000 0x00 0x70000000 0x00 0x00200000>;
cbass_mcu: interconnect@28380000 { compatible = "simple-bus";
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

Add icssg specific msmc_ram carveout nodes
Signed-off-by: Keerthy j-keerthy@ti.com ---
Carving out as there is no msmc-ram driver. Suggestions welcome.
arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index 8589f76d23..71a7069e74 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -361,3 +361,15 @@ &wkup_i2c0 { u-boot,dm-spl; }; + +&msmc_ram { + icssg0_sram: icssg0-sram@40000 { + reg = <0x40000 0x10000>; + }; + icssg1_sram: icssg1-sram@50000 { + reg = <0x50000 0x10000>; + }; + icssg2_sram: icssg2-sram@60000 { + reg = <0x60000 0x10000>; + }; +};

Add scm_conf node needed for prueth.
Signed-off-by: Keerthy j-keerthy@ti.com --- arch/arm/dts/k3-am65-main.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index 8e2a506185..0cd3e5e606 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -50,6 +50,14 @@ }; };
+ scm_conf: scm_conf@100000 { + compatible = "syscon", "simple-mfd"; + reg = <0 0x00100000 0 0x1c000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x00100000 0x1c000>; + }; + secure_proxy_main: mailbox@32c00000 { compatible = "ti,am654-secure-proxy"; #mbox-cells = <1>;

Add pruss nodes. Add nodes as in the 4.19 integration kernel.
Signed-off-by: Keerthy j-keerthy@ti.com --- arch/arm/dts/k3-am65-main.dtsi | 183 +++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+)
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index 0cd3e5e606..d357966dac 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -5,6 +5,8 @@ * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ */
+#include <dt-bindings/dma/k3-udma.h> + &cbass_main { msmc_ram: sram@70000000 { compatible = "mmio-sram"; @@ -172,4 +174,185 @@ clocks = <&k3_clks 113 1>; power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>; }; + + icssg_soc_bus2: pruss-soc-bus@b226004 { + compatible = "ti,am654-icssg-soc-bus", "simple-bus"; + reg = <0x00 0x0b226004 0x00 0x4>; + power-domains = <&k3_pds 64>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0b200000 0x00 0x0b200000 0x100000>; + dma-ranges; + + icssg2: icssg@b200000 { + compatible = "ti,am654-icssg"; + reg = <0xb200000 0x80000>; + interrupts = <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host2", "host3", "host4", + "host5", "host6", "host7", + "host8", "host9"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + dma-ranges; + ti,psil-base = <0x4300>; /* ICSSG2 PSIL thread start */ + + ti,psil-config0 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + ti,psil-config1 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + ti,psil-config2 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + ti,psil-config3 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + ti,psil-config4 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + ti,psil-config5 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + ti,psil-config6 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + ti,psil-config7 { + linux,udma-mode = <UDMA_PKT_MODE>; + statictr-type = <PSIL_STATIC_TR_NONE>; + ti,needs-epib; + ti,psd-size = <16>; + }; + + icssg2_mem: memories@b200000 { + reg = <0xb200000 0x2000>, + <0xb202000 0x2000>, + <0xb210000 0x10000>; + reg-names = "dram0", "dram1", + "shrdram2"; + }; + + icssg2_cfg: cfg@b226000 { + compatible = "syscon"; + reg = <0xb226000 0x200>; + }; + + icssg2_iep: iep@b22e000 { + compatible = "syscon"; + reg = <0xb22e000 0x1000>; + }; + + icssg2_mii_rt: mii-rt@b232000 { + compatible = "syscon"; + reg = <0xb232000 0x100>; + }; + + icssg2_mii_g_rt: mii-g-rt@b233000 { + compatible = "syscon"; + reg = <0xb233000 0x1000>; + }; + + icssg2_intc: interrupt-controller@b220000 { + compatible = "ti,am654-icssg-intc"; + reg = <0xb220000 0x2000>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + pru2_0: pru@b234000 { + compatible = "ti,am654-pru"; + reg = <0xb234000 0x4000>, + <0xb222000 0x100>, + <0xb222400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-pru2_0-fw"; + interrupt-parent = <&icssg2_intc>; + interrupts = <16>, <17>; + interrupt-names = "vring", "kick"; + }; + + rtu2_0: rtu@b204000 { + compatible = "ti,am654-rtu"; + reg = <0xb204000 0x2000>, + <0xb223000 0x100>, + <0xb223400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-rtu2_0-fw"; + interrupt-parent = <&icssg2_intc>; + interrupts = <20>, <21>; + interrupt-names = "vring", "kick"; + }; + + pru2_1: pru@b238000 { + compatible = "ti,am654-pru"; + reg = <0xb238000 0x4000>, + <0xb224000 0x100>, + <0xb224400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-pru2_1-fw"; + interrupt-parent = <&icssg2_intc>; + interrupts = <18>, <19>; + interrupt-names = "vring", "kick"; + }; + + rtu2_1: rtu@b206000 { + compatible = "ti,am654-rtu"; + reg = <0xb206000 0x2000>, + <0xb223800 0x100>, + <0xb223c00 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-rtu2_1-fw"; + interrupt-parent = <&icssg2_intc>; + interrupts = <22>, <23>; + interrupt-names = "vring", "kick"; + }; + + icssg2_mdio: mdio@b232400 { + compatible = "ti,davinci_mdio"; + reg = <0xb232400 0x100>; + clocks = <&k3_clks 64 3>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <0>; + bus_freq = <1000000>; + status = "disabled"; + }; + }; + }; };

Hi Keerthy,
On 8/6/19 5:38 AM, Keerthy wrote:
Add pruss nodes. Add nodes as in the 4.19 integration kernel.
Signed-off-by: Keerthy j-keerthy@ti.com
arch/arm/dts/k3-am65-main.dtsi | 183 +++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+)
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index 0cd3e5e606..d357966dac 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -5,6 +5,8 @@
- Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
*/
+#include <dt-bindings/dma/k3-udma.h>
&cbass_main { msmc_ram: sram@70000000 { compatible = "mmio-sram"; @@ -172,4 +174,185 @@ clocks = <&k3_clks 113 1>; power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>; };
- icssg_soc_bus2: pruss-soc-bus@b226004 {
compatible = "ti,am654-icssg-soc-bus", "simple-bus";
reg = <0x00 0x0b226004 0x00 0x4>;
power-domains = <&k3_pds 64>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0b200000 0x00 0x0b200000 0x100000>;
dma-ranges;
So, the SoC bus nodes are rejected on the kernel-side, and the overall PRUSS bindings are still a work in progress.
icssg2: icssg@b200000 {
compatible = "ti,am654-icssg";
reg = <0xb200000 0x80000>;
interrupts = <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "host2", "host3", "host4",
"host5", "host6", "host7",
"host8", "host9";
These are going away as well, and being moved into the INTC node.
#address-cells = <1>;
#size-cells = <1>;
ranges;
dma-ranges;
ti,psil-base = <0x4300>; /* ICSSG2 PSIL thread start */
ti,psil-config0 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config1 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config2 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config3 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config4 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config5 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config6 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config7 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
These are still up for debate. So, I think this whole series is a bit premature.
regards Suman
icssg2_mem: memories@b200000 {
reg = <0xb200000 0x2000>,
<0xb202000 0x2000>,
<0xb210000 0x10000>;
reg-names = "dram0", "dram1",
"shrdram2";
};
icssg2_cfg: cfg@b226000 {
compatible = "syscon";
reg = <0xb226000 0x200>;
};
icssg2_iep: iep@b22e000 {
compatible = "syscon";
reg = <0xb22e000 0x1000>;
};
icssg2_mii_rt: mii-rt@b232000 {
compatible = "syscon";
reg = <0xb232000 0x100>;
};
icssg2_mii_g_rt: mii-g-rt@b233000 {
compatible = "syscon";
reg = <0xb233000 0x1000>;
};
icssg2_intc: interrupt-controller@b220000 {
compatible = "ti,am654-icssg-intc";
reg = <0xb220000 0x2000>;
interrupt-controller;
#interrupt-cells = <1>;
};
pru2_0: pru@b234000 {
compatible = "ti,am654-pru";
reg = <0xb234000 0x4000>,
<0xb222000 0x100>,
<0xb222400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru2_0-fw";
interrupt-parent = <&icssg2_intc>;
interrupts = <16>, <17>;
interrupt-names = "vring", "kick";
};
rtu2_0: rtu@b204000 {
compatible = "ti,am654-rtu";
reg = <0xb204000 0x2000>,
<0xb223000 0x100>,
<0xb223400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu2_0-fw";
interrupt-parent = <&icssg2_intc>;
interrupts = <20>, <21>;
interrupt-names = "vring", "kick";
};
pru2_1: pru@b238000 {
compatible = "ti,am654-pru";
reg = <0xb238000 0x4000>,
<0xb224000 0x100>,
<0xb224400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru2_1-fw";
interrupt-parent = <&icssg2_intc>;
interrupts = <18>, <19>;
interrupt-names = "vring", "kick";
};
rtu2_1: rtu@b206000 {
compatible = "ti,am654-rtu";
reg = <0xb206000 0x2000>,
<0xb223800 0x100>,
<0xb223c00 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu2_1-fw";
interrupt-parent = <&icssg2_intc>;
interrupts = <22>, <23>;
interrupt-names = "vring", "kick";
};
icssg2_mdio: mdio@b232400 {
compatible = "ti,davinci_mdio";
reg = <0xb232400 0x100>;
clocks = <&k3_clks 64 3>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <0>;
bus_freq = <1000000>;
status = "disabled";
};
};
- };
};

ICSSG2 provide dual Gigabit Ethernet support. Currently mdio clock is part of this node and also the icssg2_rgmii_pins_default pinmux node has the mdio pins as there is no davinci mdio driver.
Currently icssg2 instances are supported. Either mii0 or mii1 can be enabled at a time.
Signed-off-by: Keerthy j-keerthy@ti.com --- arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 118 +++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index 71a7069e74..53399dfff6 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -16,6 +16,63 @@ serial2 = &main_uart0; ethernet0 = &cpsw_port1; }; + + /* Dual Ethernet application node on PRU-ICSSG2 */ + pruss2_eth: pruss2_eth { + compatible = "ti,am654-icssg-prueth"; + pinctrl-names = "default"; + pinctrl-0 = <&icssg2_rgmii_pins_default>; + sram = <&icssg2_sram>; + clocks = <&k3_clks 64 3>; + clock-names = "mdio_fck"; + u-boot,dm-spl; + + prus = <&pru2_0>, <&rtu2_0>, <&pru2_1>, <&rtu2_1>; + firmware-name = "ti-pruss/am65x-pru0-prueth-fw.elf", + "ti-pruss/am65x-rtu0-prueth-fw.elf", + "ti-pruss/am65x-pru1-prueth-fw.elf", + "ti-pruss/am65x-rtu1-prueth-fw.elf"; + mii-g-rt = <&icssg2_mii_g_rt>; + dma-coherent; + dmas = <&mcu_udmap &icssg2 0 UDMA_DIR_TX>, /* egress slice 0 */ + <&mcu_udmap &icssg2 1 UDMA_DIR_TX>, /* egress slice 0 */ + <&mcu_udmap &icssg2 2 UDMA_DIR_TX>, /* egress slice 0 */ + <&mcu_udmap &icssg2 3 UDMA_DIR_TX>, /* mgmnt cmd slice 0 */ + <&mcu_udmap &icssg2 4 UDMA_DIR_TX>, /* egress slice 1 */ + <&mcu_udmap &icssg2 5 UDMA_DIR_TX>, /* egress slice 1 */ + <&mcu_udmap &icssg2 6 UDMA_DIR_TX>, /* egress slice 1 */ + <&mcu_udmap &icssg2 7 UDMA_DIR_TX>, /* mgmnt cmd slice 1 */ + + <&mcu_udmap &icssg2 0 UDMA_DIR_RX>, /* ingress slice 0 */ + <&mcu_udmap &icssg2 1 UDMA_DIR_RX>, /* ingress slice 1 */ + <&mcu_udmap &icssg2 2 UDMA_DIR_RX>, /* mgmnt rsp slice 0 */ + <&mcu_udmap &icssg2 3 UDMA_DIR_RX>; /* mgmnt rsp slice 1 */ + dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", + "tx1-0", "tx1-1", "tx1-2", "tx1-3", + "rx0", "rx1", + "rxmgm0", "rxmgm1"; + + pruss2_emac0: ethernet-mii0 { + phy-handle = <&pruss2_eth0_phy>; + phy-mode = "rgmii-id"; + syscon-rgmii-delay = <&scm_conf 0x4120>; + /* Filled in by bootloader */ + local-mac-address = [00 00 00 00 00 00]; + }; + +/* + * Commenting out the second mii interface as the framework + * supports one interface in a single probe + * So either mii1 or mii2 can be used. In case mii1 is needed + * uncomment mii1 and comment out mii0 + pruss2_emac1: ethernet-mii1 { + phy-handle = <&pruss2_eth1_phy>; + phy-mode = "rgmii-id"; + syscon-rgmii-delay = <&scm_conf 0x4124>; + local-mac-address = [00 00 00 00 00 00]; + }; +*/ + }; };
&cbass_main{ @@ -274,6 +331,47 @@ u-boot,dm-spl; };
+ icssg2_rgmii_pins_default: icssg2_rgmii_pins_default { + pinctrl-single,pins = < + AM65X_IOPAD(0x00ac, PIN_INPUT , 2) /* (AH15) PRG2_PRU1_GPO0.PRG2_RGMII2_RD0 */ + AM65X_IOPAD(0x00b0, PIN_INPUT , 2) /* (AC16) PRG2_PRU1_GPO1.PRG2_RGMII2_RD1 */ + AM65X_IOPAD(0x00b4, PIN_INPUT , 2) /* (AD17) PRG2_PRU1_GPO2.PRG2_RGMII2_RD2 */ + AM65X_IOPAD(0x00b8, PIN_INPUT , 2) /* (AH14) PRG2_PRU1_GPO3.PRG2_RGMII2_RD3 */ + AM65X_IOPAD(0x00cc, PIN_OUTPUT , 2) /* (AD15) PRG2_PRU1_GPO8.PRG2_RGMII2_TD0 */ + AM65X_IOPAD(0x00d0, PIN_OUTPUT , 2) /* (AF14) PRG2_PRU1_GPO9.PRG2_RGMII2_TD1 */ + AM65X_IOPAD(0x00d4, PIN_OUTPUT , 2) /* (AC15) PRG2_PRU1_GPO10.PRG2_RGMII2_TD2 */ + AM65X_IOPAD(0x00d8, PIN_OUTPUT , 2) /* (AD14) PRG2_PRU1_GPO11.PRG2_RGMII2_TD3 */ + AM65X_IOPAD(0x00dc, PIN_INPUT , 2) /* (AE14) PRG2_PRU1_GPO16.PRG2_RGMII2_TXC */ + AM65X_IOPAD(0x00c4, PIN_OUTPUT , 2) /* (AC17) PRG2_PRU1_GPO6.PRG2_RGMII2_TX_CTL */ + AM65X_IOPAD(0x00c0, PIN_INPUT , 2) /* (AG15) PRG2_PRU1_GPO5.PRG2_RGMII2_RXC */ + AM65X_IOPAD(0x00bc, PIN_INPUT , 2) /* (AG14) PRG2_PRU1_GPO4.PRG2_RGMII2_RX_CTL */ + + AM65X_IOPAD(0x0078, PIN_INPUT , 2) /* (AF18) PRG2_PRU0_GPO0.PRG2_RGMII1_RD0 */ + AM65X_IOPAD(0x007c, PIN_INPUT , 2) /* (AE18) PRG2_PRU0_GPO1.PRG2_RGMII1_RD1 */ + AM65X_IOPAD(0x0080, PIN_INPUT , 2) /* (AH17) PRG2_PRU0_GPO2.PRG2_RGMII1_RD2 */ + AM65X_IOPAD(0x0084, PIN_INPUT , 2) /* (AG18) PRG2_PRU0_GPO3.PRG2_RGMII1_RD3 */ + AM65X_IOPAD(0x0098, PIN_OUTPUT , 2) /* (AH16) PRG2_PRU0_GPO8.PRG2_RGMII1_TD0 */ + AM65X_IOPAD(0x009c, PIN_OUTPUT , 2) /* (AG16) PRG2_PRU0_GPO9.PRG2_RGMII1_TD1 */ + AM65X_IOPAD(0x00a0, PIN_OUTPUT , 2) /* (AF16) PRG2_PRU0_GPO10.PRG2_RGMII1_TD2 */ + AM65X_IOPAD(0x00a4, PIN_OUTPUT , 2) /* (AE16) PRG2_PRU0_GPO11.PRG2_RGMII1_TD3 */ + AM65X_IOPAD(0x00a8, PIN_INPUT , 2) /* (AD16) PRG2_PRU0_GPO16.PRG2_RGMII1_TXC */ + AM65X_IOPAD(0x0090, PIN_OUTPUT , 2) /* (AE17) PRG2_PRU0_GPO6.PRG2_RGMII1_TX_CTL */ + AM65X_IOPAD(0x008c, PIN_INPUT , 2) /* (AF17) PRG2_PRU0_GPO5.PRG2_RGMII1_RXC */ + AM65X_IOPAD(0x0088, PIN_INPUT , 2) /* (AG17) PRG2_PRU0_GPO4.PRG2_RGMII1_RX_CTL */ + /* HACK to get MDIO Pins in the right state */ + AM65X_IOPAD(0x0094, PIN_INPUT , 2) /* (AC19) PRG2_PRU0_GPO7.PRG2_MDIO0_MDIO */ + AM65X_IOPAD(0x00c8, PIN_OUTPUT , 2) /* (AE15) PRG2_PRU1_GPO7.PRG2_MDIO0_MDC */ + >; + u-boot,dm-spl; + }; + + icssg2_mdio_pins_default: icssg2_mdio_pins_default { + pinctrl-single,pins = < + AM65X_IOPAD(0x0094, PIN_INPUT , 2) /* (AC19) PRG2_PRU0_GPO7.PRG2_MDIO0_MDIO */ + AM65X_IOPAD(0x00c8, PIN_OUTPUT , 2) /* (AE15) PRG2_PRU1_GPO7.PRG2_MDIO0_MDC */ + >; + u-boot,dm-spl; + }; };
&main_pmx1 { @@ -373,3 +471,23 @@ reg = <0x60000 0x10000>; }; }; + +&icssg2_mdio{ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&icssg2_mdio_pins_default>; + + pruss2_eth0_phy: ethernet-phy@0 { + reg = <0>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + }; + + pruss2_eth1_phy: ethernet-phy@3 { + reg = <3>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + }; +};

On Tue, Aug 06, 2019 at 04:08:42PM +0530, Keerthy wrote:
ICSSG2 provide dual Gigabit Ethernet support. Currently mdio clock is part of this node and also the icssg2_rgmii_pins_default pinmux node has the mdio pins as there is no davinci mdio driver.
Currently icssg2 instances are supported. Either mii0 or mii1 can be enabled at a time.
Signed-off-by: Keerthy j-keerthy@ti.com
arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 118 +++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index 71a7069e74..53399dfff6 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -16,6 +16,63 @@ serial2 = &main_uart0; ethernet0 = &cpsw_port1; };
- /* Dual Ethernet application node on PRU-ICSSG2 */
- pruss2_eth: pruss2_eth {
compatible = "ti,am654-icssg-prueth";
pinctrl-names = "default";
pinctrl-0 = <&icssg2_rgmii_pins_default>;
sram = <&icssg2_sram>;
clocks = <&k3_clks 64 3>;
clock-names = "mdio_fck";
u-boot,dm-spl;
prus = <&pru2_0>, <&rtu2_0>, <&pru2_1>, <&rtu2_1>;
firmware-name = "ti-pruss/am65x-pru0-prueth-fw.elf",
"ti-pruss/am65x-rtu0-prueth-fw.elf",
"ti-pruss/am65x-pru1-prueth-fw.elf",
"ti-pruss/am65x-rtu1-prueth-fw.elf";
mii-g-rt = <&icssg2_mii_g_rt>;
dma-coherent;
dmas = <&mcu_udmap &icssg2 0 UDMA_DIR_TX>, /* egress slice 0 */
<&mcu_udmap &icssg2 1 UDMA_DIR_TX>, /* egress slice 0 */
<&mcu_udmap &icssg2 2 UDMA_DIR_TX>, /* egress slice 0 */
<&mcu_udmap &icssg2 3 UDMA_DIR_TX>, /* mgmnt cmd slice 0 */
<&mcu_udmap &icssg2 4 UDMA_DIR_TX>, /* egress slice 1 */
<&mcu_udmap &icssg2 5 UDMA_DIR_TX>, /* egress slice 1 */
<&mcu_udmap &icssg2 6 UDMA_DIR_TX>, /* egress slice 1 */
<&mcu_udmap &icssg2 7 UDMA_DIR_TX>, /* mgmnt cmd slice 1 */
<&mcu_udmap &icssg2 0 UDMA_DIR_RX>, /* ingress slice 0 */
<&mcu_udmap &icssg2 1 UDMA_DIR_RX>, /* ingress slice 1 */
<&mcu_udmap &icssg2 2 UDMA_DIR_RX>, /* mgmnt rsp slice 0 */
<&mcu_udmap &icssg2 3 UDMA_DIR_RX>; /* mgmnt rsp slice 1 */
dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
"tx1-0", "tx1-1", "tx1-2", "tx1-3",
"rx0", "rx1",
"rxmgm0", "rxmgm1";
pruss2_emac0: ethernet-mii0 {
phy-handle = <&pruss2_eth0_phy>;
phy-mode = "rgmii-id";
syscon-rgmii-delay = <&scm_conf 0x4120>;
/* Filled in by bootloader */
local-mac-address = [00 00 00 00 00 00];
};
+/*
- Commenting out the second mii interface as the framework
- supports one interface in a single probe
- So either mii1 or mii2 can be used. In case mii1 is needed
- uncomment mii1 and comment out mii0
pruss2_emac1: ethernet-mii1 {
phy-handle = <&pruss2_eth1_phy>;
phy-mode = "rgmii-id";
syscon-rgmii-delay = <&scm_conf 0x4124>;
local-mac-address = [00 00 00 00 00 00];
};
+*/
- };
};
&cbass_main{ @@ -274,6 +331,47 @@ u-boot,dm-spl; };
- icssg2_rgmii_pins_default: icssg2_rgmii_pins_default {
pinctrl-single,pins = <
AM65X_IOPAD(0x00ac, PIN_INPUT , 2) /* (AH15) PRG2_PRU1_GPO0.PRG2_RGMII2_RD0 */
Why are there spaces behind the pin direction definitions (PIN_INPUT[space], ...)? I've never seen that before. The pinmix definitions are supposed to be a 1:1 copy from our AM64x pinmux tool for consistency sake. Is the pinmux tool broken?
-- Andreas Dannenberg Texas Instruments Inc
AM65X_IOPAD(0x00b0, PIN_INPUT , 2) /* (AC16) PRG2_PRU1_GPO1.PRG2_RGMII2_RD1 */
AM65X_IOPAD(0x00b4, PIN_INPUT , 2) /* (AD17) PRG2_PRU1_GPO2.PRG2_RGMII2_RD2 */
AM65X_IOPAD(0x00b8, PIN_INPUT , 2) /* (AH14) PRG2_PRU1_GPO3.PRG2_RGMII2_RD3 */
AM65X_IOPAD(0x00cc, PIN_OUTPUT , 2) /* (AD15) PRG2_PRU1_GPO8.PRG2_RGMII2_TD0 */
AM65X_IOPAD(0x00d0, PIN_OUTPUT , 2) /* (AF14) PRG2_PRU1_GPO9.PRG2_RGMII2_TD1 */
AM65X_IOPAD(0x00d4, PIN_OUTPUT , 2) /* (AC15) PRG2_PRU1_GPO10.PRG2_RGMII2_TD2 */
AM65X_IOPAD(0x00d8, PIN_OUTPUT , 2) /* (AD14) PRG2_PRU1_GPO11.PRG2_RGMII2_TD3 */
AM65X_IOPAD(0x00dc, PIN_INPUT , 2) /* (AE14) PRG2_PRU1_GPO16.PRG2_RGMII2_TXC */
AM65X_IOPAD(0x00c4, PIN_OUTPUT , 2) /* (AC17) PRG2_PRU1_GPO6.PRG2_RGMII2_TX_CTL */
AM65X_IOPAD(0x00c0, PIN_INPUT , 2) /* (AG15) PRG2_PRU1_GPO5.PRG2_RGMII2_RXC */
AM65X_IOPAD(0x00bc, PIN_INPUT , 2) /* (AG14) PRG2_PRU1_GPO4.PRG2_RGMII2_RX_CTL */
AM65X_IOPAD(0x0078, PIN_INPUT , 2) /* (AF18) PRG2_PRU0_GPO0.PRG2_RGMII1_RD0 */
AM65X_IOPAD(0x007c, PIN_INPUT , 2) /* (AE18) PRG2_PRU0_GPO1.PRG2_RGMII1_RD1 */
AM65X_IOPAD(0x0080, PIN_INPUT , 2) /* (AH17) PRG2_PRU0_GPO2.PRG2_RGMII1_RD2 */
AM65X_IOPAD(0x0084, PIN_INPUT , 2) /* (AG18) PRG2_PRU0_GPO3.PRG2_RGMII1_RD3 */
AM65X_IOPAD(0x0098, PIN_OUTPUT , 2) /* (AH16) PRG2_PRU0_GPO8.PRG2_RGMII1_TD0 */
AM65X_IOPAD(0x009c, PIN_OUTPUT , 2) /* (AG16) PRG2_PRU0_GPO9.PRG2_RGMII1_TD1 */
AM65X_IOPAD(0x00a0, PIN_OUTPUT , 2) /* (AF16) PRG2_PRU0_GPO10.PRG2_RGMII1_TD2 */
AM65X_IOPAD(0x00a4, PIN_OUTPUT , 2) /* (AE16) PRG2_PRU0_GPO11.PRG2_RGMII1_TD3 */
AM65X_IOPAD(0x00a8, PIN_INPUT , 2) /* (AD16) PRG2_PRU0_GPO16.PRG2_RGMII1_TXC */
AM65X_IOPAD(0x0090, PIN_OUTPUT , 2) /* (AE17) PRG2_PRU0_GPO6.PRG2_RGMII1_TX_CTL */
AM65X_IOPAD(0x008c, PIN_INPUT , 2) /* (AF17) PRG2_PRU0_GPO5.PRG2_RGMII1_RXC */
AM65X_IOPAD(0x0088, PIN_INPUT , 2) /* (AG17) PRG2_PRU0_GPO4.PRG2_RGMII1_RX_CTL */
/* HACK to get MDIO Pins in the right state */
AM65X_IOPAD(0x0094, PIN_INPUT , 2) /* (AC19) PRG2_PRU0_GPO7.PRG2_MDIO0_MDIO */
AM65X_IOPAD(0x00c8, PIN_OUTPUT , 2) /* (AE15) PRG2_PRU1_GPO7.PRG2_MDIO0_MDC */
>;
u-boot,dm-spl;
- };
- icssg2_mdio_pins_default: icssg2_mdio_pins_default {
pinctrl-single,pins = <
AM65X_IOPAD(0x0094, PIN_INPUT , 2) /* (AC19) PRG2_PRU0_GPO7.PRG2_MDIO0_MDIO */
AM65X_IOPAD(0x00c8, PIN_OUTPUT , 2) /* (AE15) PRG2_PRU1_GPO7.PRG2_MDIO0_MDC */
>;
u-boot,dm-spl;
- };
};
&main_pmx1 { @@ -373,3 +471,23 @@ reg = <0x60000 0x10000>; }; };
+&icssg2_mdio{
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&icssg2_mdio_pins_default>;
- pruss2_eth0_phy: ethernet-phy@0 {
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
- };
- pruss2_eth1_phy: ethernet-phy@3 {
reg = <3>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
- };
+};
2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

Enable CONFIG_REMOTEPROC_TI_PRU and related configs. With that enable ICSSG_PRUETH config.
Signed-off-by: Keerthy j-keerthy@ti.com --- configs/am65x_evm_a53_defconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index d43df6a187..dfb5bec794 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -48,6 +48,7 @@ CONFIG_DM=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_REGMAP=y +CONFIG_SYSCON=y CONFIG_SPL_REGMAP=y CONFIG_CLK=y CONFIG_SPL_CLK=y @@ -69,6 +70,7 @@ CONFIG_PHY_TI=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_TI_AM65_CPSW_NUSS=y +CONFIG_TI_AM64_ICSSG_PRUETH=y CONFIG_PHY=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set @@ -77,10 +79,12 @@ CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_SINGLE=y CONFIG_POWER_DOMAIN=y CONFIG_TI_SCI_POWER_DOMAIN=y +CONFIG_REMOTEPROC_TI_PRU=y CONFIG_DM_RESET=y CONFIG_RESET_TI_SCI=y CONFIG_DM_SERIAL=y CONFIG_SOC_TI=y +CONFIG_TI_PRUSS=y CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_SYSRESET_TI_SCI=y

Enable CONFIG_CMD_REMOTEPROC needed to load prueth firmwares.
Signed-off-by: Keerthy j-keerthy@ti.com --- configs/am65x_evm_a53_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index dfb5bec794..a127610380 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -34,6 +34,7 @@ CONFIG_CMD_ASKENV=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y # CONFIG_ISO_PARTITION is not set

Keerthy,
On Tue, Aug 06, 2019 at 04:08:30PM +0530, Keerthy wrote:
The series adds support for icssg_prueth functionality on u-boot. This series is based on top of master branch. rproc init needs to be done from uboot command prompt. The pru/rtu firmware loading is done by prueth driver soon after config paramters are setup.
for everybody's benefit, where does this firmware come from so one can experiment with this patch series?
-- Andreas Dannenberg Texas Instruments Inc
Currently only slice0/1 of icssg2 instance on am6-evm is supported. i.e Both slices of icssg2 instance are supported.
On u-boot prompt following commands to test icssg2_port 0 on am654-evm:
setenv ethact pruss2_eth; setenv serverip 172.24.191.45; fatload mmc 1 ${pru0loadaddr} am65x-pru0-prueth-fw.elf; fatload mmc 1 ${rtu0loadaddr} am65x-rtu0-prueth-fw.elf; rproc init; setenv autoload no; dhcp; tftp 0x82000000 Image; tftp 0x83000000 k3-am654-base-board.dtb; booti 0x82000000 - 0x83000000
This tests tftp on prueth.
Note: Uboot ethernet driver architecture supports once instance per probe. So only one of the ports are supported per instance. So DT of prueth node should have either ethernet-mii0 or ethernet-mii1.
Keerthy (14): net: eth-uclass: eth_get_dev based on SEQ_ALIAS instead of probe order net: eth-uclass: call stop only for active devices misc: uclass: Introduce misc_init_by_ofnode soc: ti: pruss: add a misc driver for PRUSS in TI SoCs remoteproc: pruss: add PRU remoteproc driver net: ti: icssg-prueth: Add ICSSG ethernet driver net: ti: icssg-prueth: Workaround to shutdown the prueth firmware arm: dts: k3-am65-main: Add msmc_ram node arm: dts: k3-am654-base-board-u-boot: Add icssg specific msmc_ram carveout nodes arm: dts: k3-am65-main: Add scm_conf node arm: dts: k3-am65-main: Add pruss nodes for ICSSG2 arm64: dts: ti: am654-base-board: add ICSSG2 Ethernet support configs: am65x_evm_a53_defconfig: Enable CONFIG_REMOTEPROC_TI_PRU configs: am65x_evm_a53_defconfig: Enable CONFIG_CMD_REMOTEPROC
arch/arm/dts/k3-am65-main.dtsi | 212 ++++++++ arch/arm/dts/k3-am65.dtsi | 4 +- arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 130 +++++ configs/am65x_evm_a53_defconfig | 5 + drivers/misc/misc-uclass.c | 25 + drivers/net/ti/Kconfig | 8 + drivers/net/ti/Makefile | 1 + drivers/net/ti/icssg-prueth.c | 525 +++++++++++++++++++ drivers/net/ti/icssg.h | 31 ++ drivers/net/ti/icssg_classifier.c | 397 ++++++++++++++ drivers/remoteproc/Kconfig | 11 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/pru_rproc.c | 384 ++++++++++++++ drivers/soc/ti/Kconfig | 13 + drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 143 +++++ include/misc.h | 9 + include/ti-pruss.h | 13 + net/eth-uclass.c | 7 +- 19 files changed, 1916 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ti/icssg-prueth.c create mode 100644 drivers/net/ti/icssg.h create mode 100644 drivers/net/ti/icssg_classifier.c create mode 100644 drivers/remoteproc/pru_rproc.c create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/ti-pruss.h
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

Andreas,
On 06/08/2019 18:35, Andreas Dannenberg wrote:
Keerthy,
On Tue, Aug 06, 2019 at 04:08:30PM +0530, Keerthy wrote:
The series adds support for icssg_prueth functionality on u-boot. This series is based on top of master branch. rproc init needs to be done from uboot command prompt. The pru/rtu firmware loading is done by prueth driver soon after config paramters are setup.
for everybody's benefit, where does this firmware come from so one can experiment with this patch series?
From here
http://git.yoctoproject.org/cgit/cgit.cgi/meta-ti/tree/recipes-bsp/prueth-fw... http://git.yoctoproject.org/cgit/cgit.cgi/meta-ti/tree/recipes-bsp/emac-lld/...
http://git.ti.com/keystone-rtos/emac-lld/trees/master/firmware/icss_dualmac/...
cheers, -roger
-- Andreas Dannenberg Texas Instruments Inc
Currently only slice0/1 of icssg2 instance on am6-evm is supported. i.e Both slices of icssg2 instance are supported.
On u-boot prompt following commands to test icssg2_port 0 on am654-evm:
setenv ethact pruss2_eth; setenv serverip 172.24.191.45; fatload mmc 1 ${pru0loadaddr} am65x-pru0-prueth-fw.elf; fatload mmc 1 ${rtu0loadaddr} am65x-rtu0-prueth-fw.elf; rproc init; setenv autoload no; dhcp; tftp 0x82000000 Image; tftp 0x83000000 k3-am654-base-board.dtb; booti 0x82000000 - 0x83000000
This tests tftp on prueth.
Note: Uboot ethernet driver architecture supports once instance per probe. So only one of the ports are supported per instance. So DT of prueth node should have either ethernet-mii0 or ethernet-mii1.
Keerthy (14): net: eth-uclass: eth_get_dev based on SEQ_ALIAS instead of probe order net: eth-uclass: call stop only for active devices misc: uclass: Introduce misc_init_by_ofnode soc: ti: pruss: add a misc driver for PRUSS in TI SoCs remoteproc: pruss: add PRU remoteproc driver net: ti: icssg-prueth: Add ICSSG ethernet driver net: ti: icssg-prueth: Workaround to shutdown the prueth firmware arm: dts: k3-am65-main: Add msmc_ram node arm: dts: k3-am654-base-board-u-boot: Add icssg specific msmc_ram carveout nodes arm: dts: k3-am65-main: Add scm_conf node arm: dts: k3-am65-main: Add pruss nodes for ICSSG2 arm64: dts: ti: am654-base-board: add ICSSG2 Ethernet support configs: am65x_evm_a53_defconfig: Enable CONFIG_REMOTEPROC_TI_PRU configs: am65x_evm_a53_defconfig: Enable CONFIG_CMD_REMOTEPROC
arch/arm/dts/k3-am65-main.dtsi | 212 ++++++++ arch/arm/dts/k3-am65.dtsi | 4 +- arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 130 +++++ configs/am65x_evm_a53_defconfig | 5 + drivers/misc/misc-uclass.c | 25 + drivers/net/ti/Kconfig | 8 + drivers/net/ti/Makefile | 1 + drivers/net/ti/icssg-prueth.c | 525 +++++++++++++++++++ drivers/net/ti/icssg.h | 31 ++ drivers/net/ti/icssg_classifier.c | 397 ++++++++++++++ drivers/remoteproc/Kconfig | 11 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/pru_rproc.c | 384 ++++++++++++++ drivers/soc/ti/Kconfig | 13 + drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 143 +++++ include/misc.h | 9 + include/ti-pruss.h | 13 + net/eth-uclass.c | 7 +- 19 files changed, 1916 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ti/icssg-prueth.c create mode 100644 drivers/net/ti/icssg.h create mode 100644 drivers/net/ti/icssg_classifier.c create mode 100644 drivers/remoteproc/pru_rproc.c create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/ti-pruss.h
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

On 07/08/2019 08:51, Roger Quadros wrote:
Andreas,
On 06/08/2019 18:35, Andreas Dannenberg wrote:
Keerthy,
On Tue, Aug 06, 2019 at 04:08:30PM +0530, Keerthy wrote:
The series adds support for icssg_prueth functionality on u-boot. This series is based on top of master branch. rproc init needs to be done from uboot command prompt. The pru/rtu firmware loading is done by prueth driver soon after config paramters are setup.
for everybody's benefit, where does this firmware come from so one can experiment with this patch series?
From here http://git.yoctoproject.org/cgit/cgit.cgi/meta-ti/tree/recipes-bsp/prueth-fw... http://git.yoctoproject.org/cgit/cgit.cgi/meta-ti/tree/recipes-bsp/emac-lld/...
http://git.ti.com/keystone-rtos/emac-lld/trees/master/firmware/icss_dualmac/...
Prebuilt firmware can be obtained from AM65 procSDK [1] rootfs at /lib/firmware/ti-pruss/am65x*.elf
[1] http://software-dl.ti.com/processor-sdk-linux/esd/AM65X/latest/index_FDS.htm...
cheers, -roger
-- Andreas Dannenberg Texas Instruments Inc
Currently only slice0/1 of icssg2 instance on am6-evm is supported. i.e Both slices of icssg2 instance are supported.
On u-boot prompt following commands to test icssg2_port 0 on am654-evm:
setenv ethact pruss2_eth; setenv serverip 172.24.191.45; fatload mmc 1 ${pru0loadaddr} am65x-pru0-prueth-fw.elf; fatload mmc 1 ${rtu0loadaddr} am65x-rtu0-prueth-fw.elf; rproc init; setenv autoload no; dhcp; tftp 0x82000000 Image; tftp 0x83000000 k3-am654-base-board.dtb; booti 0x82000000 - 0x83000000
This tests tftp on prueth.
Note: Uboot ethernet driver architecture supports once instance per probe. So only one of the ports are supported per instance. So DT of prueth node should have either ethernet-mii0 or ethernet-mii1.
Keerthy (14): net: eth-uclass: eth_get_dev based on SEQ_ALIAS instead of probe order net: eth-uclass: call stop only for active devices misc: uclass: Introduce misc_init_by_ofnode soc: ti: pruss: add a misc driver for PRUSS in TI SoCs remoteproc: pruss: add PRU remoteproc driver net: ti: icssg-prueth: Add ICSSG ethernet driver net: ti: icssg-prueth: Workaround to shutdown the prueth firmware arm: dts: k3-am65-main: Add msmc_ram node arm: dts: k3-am654-base-board-u-boot: Add icssg specific msmc_ram carveout nodes arm: dts: k3-am65-main: Add scm_conf node arm: dts: k3-am65-main: Add pruss nodes for ICSSG2 arm64: dts: ti: am654-base-board: add ICSSG2 Ethernet support configs: am65x_evm_a53_defconfig: Enable CONFIG_REMOTEPROC_TI_PRU configs: am65x_evm_a53_defconfig: Enable CONFIG_CMD_REMOTEPROC
arch/arm/dts/k3-am65-main.dtsi | 212 ++++++++ arch/arm/dts/k3-am65.dtsi | 4 +- arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 130 +++++ configs/am65x_evm_a53_defconfig | 5 + drivers/misc/misc-uclass.c | 25 + drivers/net/ti/Kconfig | 8 + drivers/net/ti/Makefile | 1 + drivers/net/ti/icssg-prueth.c | 525 +++++++++++++++++++ drivers/net/ti/icssg.h | 31 ++ drivers/net/ti/icssg_classifier.c | 397 ++++++++++++++ drivers/remoteproc/Kconfig | 11 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/pru_rproc.c | 384 ++++++++++++++ drivers/soc/ti/Kconfig | 13 + drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 143 +++++ include/misc.h | 9 + include/ti-pruss.h | 13 + net/eth-uclass.c | 7 +- 19 files changed, 1916 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ti/icssg-prueth.c create mode 100644 drivers/net/ti/icssg.h create mode 100644 drivers/net/ti/icssg_classifier.c create mode 100644 drivers/remoteproc/pru_rproc.c create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/ti-pruss.h
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
participants (8)
-
Andreas Dannenberg
-
Keerthy
-
keerthy
-
Lokesh Vutla
-
Roger Quadros
-
Simon Glass
-
Suman Anna
-
Tom Rini