
On 17.08.2018 12:58, Marek BehĂșn wrote:
Check if Mox modules are connected in supported mode, then configure the MDIO addresses of switch modules.
Signed-off-by: Marek Behun marek.behun@nic.cz
arch/arm/dts/armada-3720-turris-mox.dts | 11 ++ board/CZ.NIC/turris_mox/turris_mox.c | 235 +++++++++++++++++++++++++++++++- 2 files changed, 245 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts index a817f20920..05904387d2 100644 --- a/arch/arm/dts/armada-3720-turris-mox.dts +++ b/arch/arm/dts/armada-3720-turris-mox.dts @@ -114,6 +114,17 @@ spi-max-frequency = <20000000>; m25p,fast-read; };
moxtet@1 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cznic,moxtet";
reg = <1>;
devrst-gpio = <&gpiosb 2 GPIO_ACTIVE_LOW>;
spi-max-frequency = <1000000>;
spi-cpol;
spi-cpha;
}; };
&uart0 {
diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 224179434b..21a3e63864 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -4,11 +4,13 @@ */
#include <common.h> +#include <asm/gpio.h> #include <asm/io.h> #include <dm.h> #include <clk.h> #include <spi.h> #include <mvebu/comphy.h> +#include <miiphy.h> #include <linux/string.h> #include <linux/libfdt.h> #include <fdt_support.h> @@ -251,12 +253,131 @@ int comphy_update_map(struct comphy_map *serdes_map, int count) return 0; }
+#define SW_SMI_CMD_R(d, r) (0x9800 | (((d) & 0x1f) << 5) | ((r) & 0x1f)) +#define SW_SMI_CMD_W(d, r) (0x9400 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
+static int sw_multi_read(struct mii_dev *bus, int sw, int dev, int reg) +{
- bus->write(bus, sw, 0, 0, SW_SMI_CMD_R(dev, reg));
- mdelay(5);
- return bus->read(bus, sw, 0, 1);
+}
+static void sw_multi_write(struct mii_dev *bus, int sw, int dev, int reg,
u16 val)
+{
- bus->write(bus, sw, 0, 1, val);
- bus->write(bus, sw, 0, 0, SW_SMI_CMD_W(dev, reg));
- mdelay(5);
+}
+static int sw_scratch_read(struct mii_dev *bus, int sw, int reg) +{
- sw_multi_write(bus, sw, 0x1c, 0x1a, (reg & 0x7f) << 8);
- return sw_multi_read(bus, sw, 0x1c, 0x1a) & 0xff;
+}
+static void sw_led_write(struct mii_dev *bus, int sw, int port, int reg,
u16 val)
+{
- sw_multi_write(bus, sw, port, 0x16, 0x8000 | ((reg & 7) << 12)
| (val & 0x7ff));
+}
+static void sw_blink_leds(struct mii_dev *bus, int peridot, int topaz) +{
- int i, p;
- struct {
int port;
u16 val;
int wait;
- } regs[] = {
{ 2, 0xef, 1 }, { 2, 0xfe, 1 }, { 2, 0x33, 0 },
{ 4, 0xef, 1 }, { 4, 0xfe, 1 }, { 4, 0x33, 0 },
{ 3, 0xfe, 1 }, { 3, 0xef, 1 }, { 3, 0x33, 0 },
{ 1, 0xfe, 1 }, { 1, 0xef, 1 }, { 1, 0x33, 0 }
- };
- for (i = 0; i < 12; ++i) {
for (p = 0; p < peridot; ++p) {
sw_led_write(bus, 0x10 + p, regs[i].port, 0,
regs[i].val);
sw_led_write(bus, 0x10 + p, regs[i].port + 4, 0,
regs[i].val);
}
if (topaz) {
sw_led_write(bus, 0x2, 0x10 + regs[i].port, 0,
regs[i].val);
}
if (regs[i].wait)
mdelay(75);
- }
+}
+static void check_switch_address(struct mii_dev *bus, int addr) +{
- if (sw_scratch_read(bus, addr, 0x70) >> 3 != addr)
printf("Check of switch MDIO address failed for 0x%02x\n",
addr);
+}
+static int sfp, pci, topaz, peridot, usb, passpci; +static int sfp_pos, peridot_pos[3]; +static int module_count;
+static int configure_peridots(void) +{
- int node, i, ret;
- struct gpio_desc gpio = {};
- u8 dout[MAX_MOX_MODULES];
- node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "cznic,moxtet");
- if (node < 0) {
printf("Cannot find Moxtet bus device node!\n");
return -1;
- }
- gpio_request_by_name_nodev(offset_to_ofnode(node), "devrst-gpio", 0,
&gpio, GPIOD_IS_OUT);
- if (!dm_gpio_is_valid(&gpio)) {
printf("Cannot find reset GPIO for Moxtet bus!\n");
return -1;
- }
- memset(dout, 0, MAX_MOX_MODULES);
- /* set addresses of Peridot modules */
- for (i = 0; i < peridot; ++i)
dout[module_count - peridot_pos[i]] = (~i) & 3;
- /*
* if there is a SFP module connected to the last Peridot module, set
* the P10_SMODE to 1 for the Peridot module
*/
- if (sfp)
dout[module_count - peridot_pos[i - 1]] |= 1 << 3;
- dm_gpio_set_value(&gpio, 1);
- mdelay(10);
- ret = mox_do_spi(NULL, dout, module_count + 1);
- mdelay(10);
- dm_gpio_set_value(&gpio, 0);
- mdelay(50);
- return ret;
+}
- int last_stage_init(void) { int ret, i; const u8 *topology;
- int module_count; mox_version_t version;
struct mii_dev *bus;
ret = mox_get_topology(&topology, &module_count, &version); if (ret) {
@@ -293,6 +414,118 @@ int last_stage_init(void) } }
/* now check if modules are connected in supported mode */
for (i = 0; i < module_count; ++i) {
switch (topology[i]) {
case MOX_MODULE_SFP:
if (sfp) {
printf("Error: Only one SFP module is "
"supported!\n");
} else if (topaz) {
printf("Error: SFP module cannot be connected "
"after Topaz Switch module!\n");
} else {
sfp_pos = i;
++sfp;
}
break;
case MOX_MODULE_PCI:
if (pci) {
printf("Error: Only one Mini-PCIe module is "
"supported!\n");
} else if (usb) {
printf("Error: Mini-PCIe module cannot come "
"after USB 3.0 module!\n");
} else if (i && (i != 1 || !passpci)) {
printf("Error: Mini-PCIe module should be the "
"first connected module or come right "
"after Passthrough Mini-PCIe module!\n");
} else {
++pci;
}
break;
case MOX_MODULE_TOPAZ:
if (topaz) {
printf("Error: Only one Topaz module is "
"supported!\n");
} else if (peridot >= 3) {
printf("Error: At most two Peridot modules "
"can come before Topaz module!\n");
} else {
++topaz;
}
break;
case MOX_MODULE_PERIDOT:
if (sfp || topaz) {
printf("Error: Peridot module must come before "
"SFP or Topaz module!\n");
} else if (peridot >= 3) {
printf("Error: At most three Peridot modules "
"are supported!\n");
} else {
peridot_pos[peridot] = i;
++peridot;
}
break;
case MOX_MODULE_USB3:
if (pci) {
printf("Error: USB 3.0 module cannot come "
"after Mini-PCIe module!\n");
} else if (usb) {
printf("Error: Only one USB 3.0 module is "
"supported!\n");
} else if (i && (i != 1 || !passpci)) {
printf("Error: USB 3.0 module should be the "
"first connected module or come right "
"after Passthrough Mini-PCIe module!\n");
} else {
++usb;
}
break;
case MOX_MODULE_PASSPCI:
if (passpci) {
printf("Error: Only one Passthrough Mini-PCIe "
"module is supported!\n");
} else if (i != 0) {
printf("Error: Passthrough Mini-PCIe module "
"should be the first connected "
"module!\n");
} else {
++passpci;
}
}
}
/* now configure modules */
if (peridot > 0) {
if (configure_peridots() < 0) {
printf("Cannot configure Peridot modules!\n");
peridot = 0;
}
}
if (peridot || topaz) {
/*
* now check if the addresses are set by reading Scratch & Misc
* register 0x70 of Peridot (and potentially Topaz) modules
*/
bus = miiphy_get_dev_by_name("neta@30000");
if (!bus) {
printf("Cannot get MDIO bus device!\n");
} else {
for (i = 0; i < peridot; ++i)
check_switch_address(bus, 0x10 + i);
if (topaz)
check_switch_address(bus, 0x2);
sw_blink_leds(bus, peridot, topaz);
}
}
printf("\n");
return 0;
This patch does not apply currently. I'm skipping it from this series for now. I'm currently pushing my Marvell branch upstream and would like to get the first batch of patches accepted. After Tom has pulled these patches, please rebase on top of this new master.
Thanks, Stefan