diff mbox

[U-Boot,19/21] arm/km: correct init of 88e6352 switch in the reset_phy function

Message ID 1332344980-8658-20-git-send-email-holger.brunck@keymile.com
State Superseded
Headers show

Commit Message

Holger Brunck March 21, 2012, 3:49 p.m. UTC
From: Valentin Longchamp <valentin.longchamp@keymile.com>

This is achieved thanks to the support read/write regs for the external
88e6352 switch. The functions for this are added into an own file
managed_switch.c. This is compiled if the define CONFIG_KM_MANAGED_SW_ADDR
was set in the board setup. This define specifies the phy address.

Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
cc: Gerlando Falauto <gerlando.falauto@keymile.com>
cc: Prafulla Wadaskar <prafulla@marvell.com>
cc: Holger Brunck <holger.brunck@keymile.com>
---
 board/keymile/common/common.h         |    6 +
 board/keymile/km_arm/Makefile         |    4 +
 board/keymile/km_arm/km_arm.c         |   26 +++++-
 board/keymile/km_arm/managed_switch.c |  166 +++++++++++++++++++++++++++++++++
 include/configs/km_kirkwood.h         |   13 +++
 5 files changed, 214 insertions(+), 1 deletions(-)
 create mode 100644 board/keymile/km_arm/managed_switch.c
diff mbox

Patch

diff --git a/board/keymile/common/common.h b/board/keymile/common/common.h
index 6c1f640..49225b8 100644
--- a/board/keymile/common/common.h
+++ b/board/keymile/common/common.h
@@ -125,6 +125,12 @@  struct bfticu_iomap {
 int ethernet_present(void);
 int ivm_read_eeprom(void);
 
+
+int ext_switch_reg_write(const char *devname, u8 phy_addr, u8 port,
+	u8 reg, u16 data);
+int ext_switch_reg_read(const char *devname, u8 phy_addr, u8 port,
+	u8 reg, u16 *data);
+
 int set_km_env(void);
 int fdt_set_node_and_value(void *blob,
 			char *nodename,
diff --git a/board/keymile/km_arm/Makefile b/board/keymile/km_arm/Makefile
index aa51255..06079e9 100644
--- a/board/keymile/km_arm/Makefile
+++ b/board/keymile/km_arm/Makefile
@@ -31,6 +31,10 @@  LIB	= $(obj)lib$(BOARD).o
 
 COBJS	:= $(BOARD).o ../common/common.o ../common/ivm.o
 
+ifdef CONFIG_KM_MANAGED_SW_ADDR
+COBJS	+= managed_switch.o
+endif
+
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
 SOBJS	:= $(addprefix $(obj),$(SOBJS))
diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c
index 4b83439..f4be40f 100644
--- a/board/keymile/km_arm/km_arm.c
+++ b/board/keymile/km_arm/km_arm.c
@@ -9,6 +9,9 @@ 
  * (C) Copyright 2010
  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
  *
+ * (C) Copyright 2011, 2012
+ * Valentin Lontgchamp, Keymile AG, valentin.longchamp@keymile.com
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -36,6 +39,7 @@ 
 #include <spi.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
+#include <asm/errno.h>
 #include <asm/arch/kirkwood.h>
 #include <asm/arch/mpp.h>
 
@@ -367,7 +371,27 @@  void reset_phy(void)
 	/* reset the phy */
 	miiphy_reset(name, CONFIG_PHY_BASE_ADR);
 }
-#elif !defined(CONFIG_KM_PIGGY4_88E6352)
+#elif defined(CONFIG_KM_PIGGY4_88E6352)
+
+#if defined(CONFIG_KM_MANAGED_SW_ADDR)
+void reset_phy(void)
+{
+	char *name = "egiga0";
+
+	if (miiphy_set_current_dev(name))
+		return;
+
+	/* enable autoneg on port 0 phy */
+	ext_switch_reg_write(name, CONFIG_KM_MANAGED_SW_ADDR, 0, 0, 0x3300);
+
+	/* egress broadcast franes on all macs, with forwarding */
+	ext_switch_reg_write(name, CONFIG_KM_MANAGED_SW_ADDR, 16, 4, 0x000f);
+	ext_switch_reg_write(name, CONFIG_KM_MANAGED_SW_ADDR, 20, 4, 0x000f);
+	ext_switch_reg_write(name, CONFIG_KM_MANAGED_SW_ADDR, 21, 4, 0x000f);
+}
+#endif
+
+#else
 /* Configure and enable MV88E1118 PHY on the piggy*/
 void reset_phy(void)
 {
diff --git a/board/keymile/km_arm/managed_switch.c b/board/keymile/km_arm/managed_switch.c
new file mode 100644
index 0000000..482c18d
--- /dev/null
+++ b/board/keymile/km_arm/managed_switch.c
@@ -0,0 +1,166 @@ 
+/*
+ * (C) Copyright 2012
+ * Valentin Lontgchamp, Keymile AG, valentin.longchamp@keymile.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <miiphy.h>
+#include <asm/errno.h>
+
+#define SMI_HDR		((0x8 | 0x1) << 12)
+#define SMI_BUSY_MASK	(0x8000)
+#define SMIRD_OP	(0x2 << 10)
+#define SMIWR_OP	(0x1 << 10)
+#define SMI_MASK	0x1f
+#define PORT_SHIFT	5
+
+#define COMMAND_REG	0
+#define DATA_REG	1
+
+static int ext_switch_wait_rdy(const char *devname, u8 phy_addr)
+{
+	u16 command;
+	u32 timeout = 100;
+	int ret;
+
+	/* wait till the SMI is not busy */
+	do {
+		/* read command register */
+		ret = miiphy_read(devname, phy_addr, COMMAND_REG, &command);
+		if (ret < 0) {
+			printf("%s: Error reading command register\n",
+				__func__);
+			return ret;
+		}
+		if (timeout-- == 0) {
+			printf("Err..(%s) SMI busy timeout\n", __func__);
+			return -EFAULT;
+		}
+	} while (command & SMI_BUSY_MASK);
+
+	return 0;
+}
+
+int ext_switch_reg_read(const char *devname, u8 phy_addr, u8 port,
+	u8 reg, u16 *data)
+{
+	int ret;
+	u16 command;
+
+	ret = ext_switch_wait_rdy(devname, phy_addr);
+	if (ret)
+		return ret;
+
+	command = SMI_HDR | SMIRD_OP | ((port&SMI_MASK) << PORT_SHIFT) |
+			(reg & SMI_MASK);
+	debug("%s: write to command: %#x\n", __func__, command);
+	ret = miiphy_write(devname, phy_addr, COMMAND_REG, command);
+	if (ret)
+		return ret;
+
+	ret = ext_switch_wait_rdy(devname, phy_addr);
+	if (ret)
+		return ret;
+
+	ret = miiphy_read(devname, phy_addr, DATA_REG, data);
+
+	return ret;
+}
+
+int ext_switch_reg_write(const char *devname, u8 phy_addr, u8 port,
+	u8 reg, u16 data)
+{
+	int ret;
+	u16 value;
+
+	ret = ext_switch_wait_rdy(devname, phy_addr);
+	if (ret)
+		return ret;
+
+	debug("%s: write to data: %#x\n", __func__, data);
+	ret = miiphy_write(devname, phy_addr, DATA_REG, data);
+	if (ret)
+		return ret;
+
+	value = SMI_HDR | SMIWR_OP | ((port & SMI_MASK) << PORT_SHIFT) |
+			(reg & SMI_MASK);
+	debug("%s: write to command: %#x\n", __func__, value);
+	ret = miiphy_write(devname, phy_addr, COMMAND_REG, value);
+	if (ret)
+		return ret;
+
+	ret = ext_switch_wait_rdy(devname, phy_addr);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int do_sw_reg_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *name = "egiga0";
+	u16 value = 0, phyaddr, reg, port;
+	int ret;
+
+	if (argc < 4)
+		return cmd_usage(cmdtp);
+
+	phyaddr = simple_strtoul(argv[1], NULL, 16);
+	port = simple_strtoul(argv[2], NULL, 10);
+	reg = simple_strtoul(argv[3], NULL, 10);
+
+	ret = ext_switch_reg_read(name, phyaddr, port, reg, &value);
+	printf("%#x\n", value);
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	sw_reg_read,	4,	1,	do_sw_reg_read,
+	"read the switch registers",
+	"<phyaddr> <port> <reg>\n"
+	);
+
+int do_sw_reg_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *name = "egiga0";
+	u16 value = 0, phyaddr, reg, port;
+	int ret;
+
+	if (argc < 5)
+		return cmd_usage(cmdtp);
+
+	phyaddr = simple_strtoul(argv[1], NULL, 16);
+	port = simple_strtoul(argv[2], NULL, 10);
+	reg = simple_strtoul(argv[3], NULL, 10);
+	value = simple_strtoul(argv[4], NULL, 16);
+
+	ret = ext_switch_reg_write(name, phyaddr, port, reg, value);
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	sw_reg_write,	5,	1,	do_sw_reg_write,
+	"write the the switch registers",
+	"<phyaddr> <port> <reg> <value>\n"
+	);
+
diff --git a/include/configs/km_kirkwood.h b/include/configs/km_kirkwood.h
index fbe714b..059fdbc 100644
--- a/include/configs/km_kirkwood.h
+++ b/include/configs/km_kirkwood.h
@@ -58,6 +58,7 @@ 
 #define CONFIG_KM_FPGA_CONFIG
 #define CONFIG_KM_PIGGY4_88E6352
 
+#define CONFIG_KM_MANAGED_SW_ADDR	0x10
 /* KM_MGCOGE3UN */
 #elif defined(CONFIG_KM_MGCOGE3UN)
 #define CONFIG_IDENT_STRING		"\nKeymile COGE3UN"
@@ -131,6 +132,18 @@ 
 	MVGBE_SET_GMII_SPEED_TO_1000	    |\
 	MVGBE_SET_MII_SPEED_TO_100)
 
+/*
+ * There is no phy on the eth interface, but an external switch
+ * For kmcoge5un it is completely unmanaged, so we disable an access to it
+ * For km_nusa, we an MDIO(MII) interface that can configure the switch trough
+ * an indirect access, so we do not disable the MII
+ */
+#ifndef CONFIG_KM_MANAGED_SW_ADDR
+#undef CONFIG_MII
+#undef CONFIG_CMD_MII
+#undef CONFIG_RESET_PHY_R
+#endif
+
 #endif
 
 #ifdef CONFIG_KM_PIGGY4_88E6061