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

login
register
mail settings
Submitter ramneek mehresh
Date Aug. 5, 2013, 10:43 a.m.
Message ID <1375699430-14865-1-git-send-email-ramneek.mehresh@freescale.com>
Download mbox | patch
Permalink /patch/264630/
State Rejected
Delegated to: York Sun
Headers show

Comments

ramneek mehresh - Aug. 5, 2013, 10:43 a.m.
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@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(-)
York Sun - Aug. 13, 2013, 9:57 p.m.
On 08/05/2013 03:43 AM, Ramneek Mehresh wrote:
> 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@freescale.com>

Same here, we don't submit rev1 errata workaround.

York

Patch

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) */