[U-Boot] [PATCH 2/2]powerpc/fdt: Modify USB device-tree fixup for erratum-A006918

Ramneek Mehresh ramneek.mehresh at freescale.com
Mon Aug 5 12:43:50 CEST 2013


Erratum-A006918 prevents internal UTMI phy pll from starting
sometimes. Workaround involves restarting phy pll maximum seven
times with 1ms delay in each loop. If pll still fails to start
after max retries, "status" property is set to "fail-erratum-a006918"
to stop kernel from using this device

Signed-off-by: Ramneek Mehresh <ramneek.mehresh at freescale.com>
---
Applies on git://git.denx.de/u-boot.git
(branch master)

 arch/powerpc/cpu/mpc8xxx/fdt.c | 91 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 74 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/cpu/mpc8xxx/fdt.c b/arch/powerpc/cpu/mpc8xxx/fdt.c
index eb7cbbc..0661d70 100644
--- a/arch/powerpc/cpu/mpc8xxx/fdt.c
+++ b/arch/powerpc/cpu/mpc8xxx/fdt.c
@@ -12,6 +12,7 @@
 #include <fdt_support.h>
 #include <asm/mp.h>
 #include <asm/fsl_serdes.h>
+#include <fsl_usb.h>
 #include <phy.h>
 #include <hwconfig.h>
 
@@ -72,57 +73,103 @@ void ft_fixup_num_cores(void *blob) {
 #endif /* defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) */
 
 #if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB)
-static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
-				const char *phy_type, int start_offset)
+static const char *fdt_usb_get_node_type(void *blob, int start_offset,
+						int *node_offset)
 {
 	const char *compat_dr = "fsl-usb2-dr";
 	const char *compat_mph = "fsl-usb2-mph";
-	const char *prop_mode = "dr_mode";
-	const char *prop_type = "phy_type";
 	const char *node_type = NULL;
-	int node_offset;
-	int err;
 
-	node_offset = fdt_node_offset_by_compatible(blob,
+	*node_offset = fdt_node_offset_by_compatible(blob,
 			start_offset, compat_mph);
-	if (node_offset < 0) {
-		node_offset = fdt_node_offset_by_compatible(blob,
+	if (*node_offset < 0) {
+		*node_offset = fdt_node_offset_by_compatible(blob,
 			start_offset, compat_dr);
-		if (node_offset < 0) {
-			printf("WARNING: could not find compatible"
+		if (*node_offset < 0) {
+			printf("ERROR: could not find compatible"
 				" node %s or %s: %s.\n", compat_mph,
-				compat_dr, fdt_strerror(node_offset));
+				compat_dr, fdt_strerror(*node_offset));
 			return -1;
-		} else
+		} else {
 			node_type = compat_dr;
-	} else
+		}
+	} else {
 		node_type = compat_mph;
+	}
+
+	return node_type;
+}
+
+static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
+				const char *phy_type, int start_offset)
+{
+	const char *prop_mode = "dr_mode";
+	const char *prop_type = "phy_type";
+	const char *node_type = NULL;
+	int node_offset;
+	int err;
+
+	node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset);
+	if (node_offset < 0)
+		return -1;
 
 	if (mode) {
 		err = fdt_setprop(blob, node_offset, prop_mode, mode,
 				  strlen(mode) + 1);
-		if (err < 0)
-			printf("WARNING: could not set %s for %s: %s.\n",
+
+		if (err < 0) {
+			printf("ERROR: could not set %s for %s: %s.\n",
 			       prop_mode, node_type, fdt_strerror(err));
+		}
 	}
 
 	if (phy_type) {
 		err = fdt_setprop(blob, node_offset, prop_type, phy_type,
 				  strlen(phy_type) + 1);
 		if (err < 0)
-			printf("WARNING: could not set %s for %s: %s.\n",
+			printf("ERROR: could not set %s for %s: %s.\n",
 			       prop_type, node_type, fdt_strerror(err));
 	}
 
 	return node_offset;
 }
 
+static int fdt_fixup_usb_erratum(void *blob, const char *erratum,
+					int start_offset)
+{
+	const char *prop_erratum_a006918 = "fail-erratum-a006918";
+	const char *node_type = NULL;
+	const char *prop_type = "status";
+	int node_offset, err;
+
+	node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset);
+	if (!node_type)
+		return -1;
+
+	if (!strcmp(erratum, "erratum_a006918")) {
+		err = fdt_setprop(blob, node_offset, prop_type,
+				  prop_erratum_a006918,
+				  strlen(prop_erratum_a006918) + 1);
+
+		if (err < 0) {
+			printf("ERROR: could not set %s for %s: %s.\n",
+			       prop_erratum_a006918, node_type,
+					fdt_strerror(err));
+		}
+	}
+
+	return node_offset;
+}
+
 void fdt_fixup_dr_usb(void *blob, bd_t *bd)
 {
 	const char *modes[] = { "host", "peripheral", "otg" };
 	const char *phys[] = { "ulpi", "utmi" };
 	const char *dr_mode_type = NULL;
 	const char *dr_phy_type = NULL;
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006918
+	int usb_erratum_a006918_off = -1;
+#endif
 	int usb_mode_off = -1;
 	int usb_phy_off = -1;
 	char str[5];
@@ -173,6 +220,16 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd)
 
 		if (usb_phy_off < 0)
 			return;
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006918
+		if (has_fsl_erratum_a006918) {
+			usb_erratum_a006918_off = fdt_fixup_usb_erratum(blob,
+				"erratum_a006918", usb_erratum_a006918_off);
+
+			if (usb_erratum_a006918_off < 0)
+				return;
+		}
+#endif
 	}
 }
 #endif /* defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB) */
-- 
1.7.11.7





More information about the U-Boot mailing list