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

Submitted by ramneek mehresh on Aug. 5, 2013, 10:43 a.m.

Details

Message ID 1375699430-14865-1-git-send-email-ramneek.mehresh@freescale.com
State Rejected
Delegated to: York Sun
Headers show

Commit Message

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(-)

Comments

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 hide | download patch | download mbox

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