diff mbox

[U-Boot,v2] board/p1010rdb: add pin mux and sdhc support in any boot

Message ID 1371436351-18795-1-git-send-email-Shengzhou.Liu@freescale.com
State Superseded
Delegated to: Andy Fleming
Headers show

Commit Message

Shengzhou Liu June 17, 2013, 2:32 a.m. UTC
SDHC pins are multiplexed with IFC and ULPI interfaces.
This patch intends to enable SDHC function in case of
NOR/NAND/SPI boot aside from SD boot.

If "esdhc" is configured in hwconfig, u-boot will configure
multiplexing pins from default IFC to SDHC at runtime to
enable SD function. And add minimal necessary mux command for
ifc/sdhc/ulpi to conveniently configure multiplexing pins
without reboot or updating u-boot.

Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
---
v2: updated description.

 board/freescale/p1010rdb/p1010rdb.c | 128 +++++++++++++++++++++++++++++++++---
 include/configs/P1010RDB.h          |  11 ++--
 2 files changed, 125 insertions(+), 14 deletions(-)

Comments

Andy Fleming July 16, 2013, 10:29 p.m. UTC | #1
On Sun, Jun 16, 2013 at 9:32 PM, Shengzhou Liu
<Shengzhou.Liu@freescale.com>wrote:

> SDHC pins are multiplexed with IFC and ULPI interfaces.
> This patch intends to enable SDHC function in case of
> NOR/NAND/SPI boot aside from SD boot.
>
> If "esdhc" is configured in hwconfig, u-boot will configure
> multiplexing pins from default IFC to SDHC at runtime to
> enable SD function. And add minimal necessary mux command for
> ifc/sdhc/ulpi to conveniently configure multiplexing pins
> without reboot or updating u-boot.
>
> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> ---
> v2: updated description.
>
>  board/freescale/p1010rdb/p1010rdb.c | 128
> +++++++++++++++++++++++++++++++++---
>  include/configs/P1010RDB.h          |  11 ++--
>  2 files changed, 125 insertions(+), 14 deletions(-)
>
> diff --git a/board/freescale/p1010rdb/p1010rdb.c
> b/board/freescale/p1010rdb/p1010rdb.c
> index 0c30d76..5a2f1f0 100644
> --- a/board/freescale/p1010rdb/p1010rdb.c
> +++ b/board/freescale/p1010rdb/p1010rdb.c
>


> +static int pin_mux_cmd(cmd_tbl_t *cmdtp, int flag, int argc,
> +                                       char * const argv[])
> +{
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +       if (strcmp(argv[1], "ifc") == 0)
> +               config_pin_mux(MUX_TYPE_IFC);
> +       else if (strcmp(argv[1], "sdhc") == 0)
> +               config_pin_mux(MUX_TYPE_SDHC);
> +       else if (strcmp(argv[1], "ulpi") == 0)
> +               config_pin_mux(MUX_TYPE_ULPI);
> +       else
> +               return CMD_RET_USAGE;
> +       return 0;
> +}
> +
> +U_BOOT_CMD(
> +       mux, 2, 0, pin_mux_cmd,
> +       "configure multiplexing pin for IFC/SDHC/ULPI buses",
> +       "bus_type[ifc/sdhc/ulpi] (e.g. mux sdhc)"
>


This command name is very generic, but the command is highly-specific to
this board. Ideally, you'd come up with code that could be reused by other
boards that have similar issues. It should be fairly straightforward to
implement a version of this code which allowed arbitrary pin muxing code to
register with a name. It would require some discussion on the list. If
you're not willing to do that, at least rename the command so it's clear it
is just for this board.


Andy
diff mbox

Patch

diff --git a/board/freescale/p1010rdb/p1010rdb.c b/board/freescale/p1010rdb/p1010rdb.c
index 0c30d76..5a2f1f0 100644
--- a/board/freescale/p1010rdb/p1010rdb.c
+++ b/board/freescale/p1010rdb/p1010rdb.c
@@ -37,10 +37,8 @@ 
 #include <asm/fsl_serdes.h>
 #include <asm/fsl_ifc.h>
 #include <asm/fsl_pci.h>
-
-#ifndef CONFIG_SDCARD
 #include <hwconfig.h>
-#endif
+#include <i2c.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -49,6 +47,19 @@  DECLARE_GLOBAL_DATA_PTR;
 #define MUX_CPLD_TDM			0x01
 #define MUX_CPLD_SPICS0_FLASH		0x00
 #define MUX_CPLD_SPICS0_SLIC		0x02
+#define PMUXCR1_IFC_MASK	0x00ffff00
+#define PMUXCR1_SDHC_MASK	0x00fff000
+#define PMUXCR1_SDHC_ENABLE	0x00555000
+#define PMUXCR1_ULPI_MASK	0x00ffffc0
+#define PMUXCR1_ULPI_ENABLE	0x00aaaa80
+
+enum {
+	MUX_TYPE_IFC,
+	MUX_TYPE_SDHC,
+	MUX_TYPE_ULPI,
+};
+
+uint pin_mux;
 
 #ifndef CONFIG_SDCARD
 struct cpld_data {
@@ -262,6 +273,16 @@  void fdt_del_sdhc(void *blob)
 	}
 }
 
+void fdt_del_ifc(void *blob)
+{
+	int nodeoff = 0;
+
+	while ((nodeoff = fdt_node_offset_by_compatible(blob, 0,
+			"fsl,ifc")) >= 0) {
+		fdt_del_node(blob, nodeoff);
+	}
+}
+
 void fdt_disable_uart1(void *blob)
 {
 	int nodeoff;
@@ -305,9 +326,13 @@  void ft_board_setup(void *blob, bd_t *bd)
 		fdt_del_flexcan(blob);
 		fdt_del_node_and_alias(blob, "ethernet2");
 	}
-#ifndef CONFIG_SDCARD
-	/* disable sdhc due to sdhc bug */
-	fdt_del_sdhc(blob);
+
+	/* Delete IFC node as IFC pins are multiplexing with SDHC */
+	if (pin_mux != MUX_TYPE_IFC)
+		fdt_del_ifc(blob);
+	else
+		fdt_del_sdhc(blob);
+
 	if (hwconfig_subarg_cmp("fsl_p1010mux", "tdm_can", "can")) {
 		fdt_del_tdm(blob);
 		fdt_del_spi_slic(blob);
@@ -325,13 +350,72 @@  void ft_board_setup(void *blob, bd_t *bd)
 		fdt_del_flexcan(blob);
 		fdt_disable_uart1(blob);
 	}
-#endif
 }
 #endif
 
+int config_pin_mux(int if_type)
+{
+	ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u8 tmp;
+	uint orig_bus = i2c_get_bus_num();
+
+	i2c_set_bus_num(CONFIG_SYS_PCA9557_BUS_NUM);
+	tmp = 0xf0;
+	if (i2c_write(CONFIG_SYS_I2C_PCA9557_ADDR, 3, 1, &tmp, 1) < 0)
+		goto wr_err;
+
+	switch (if_type) {
+	case MUX_TYPE_IFC:
+		tmp = 0x01;
+		if (i2c_write(CONFIG_SYS_I2C_PCA9557_ADDR, 1, 1, &tmp, 1) < 0)
+			goto wr_err;
+		pin_mux = MUX_TYPE_IFC;
+		clrbits_be32(&gur->pmuxcr, PMUXCR1_IFC_MASK);
+		debug("pin mux is configured for IFC, SDHC disabled\n");
+		break;
+	case MUX_TYPE_SDHC:
+		tmp = 0x05;
+		if (i2c_write(CONFIG_SYS_I2C_PCA9557_ADDR, 1, 1, &tmp, 1) < 0)
+			goto wr_err;
+		pin_mux = MUX_TYPE_SDHC;
+		clrsetbits_be32(&gur->pmuxcr, PMUXCR1_SDHC_MASK,
+							PMUXCR1_SDHC_ENABLE);
+		debug("pin mux is configured for SDHC, IFC disabled\n");
+		break;
+	case MUX_TYPE_ULPI:
+		tmp = 0x06;
+		if (i2c_write(CONFIG_SYS_I2C_PCA9557_ADDR, 1, 1, &tmp, 1) < 0)
+			goto wr_err;
+		pin_mux = MUX_TYPE_ULPI;
+		clrsetbits_be32(&gur->pmuxcr, PMUXCR1_ULPI_MASK,
+							PMUXCR1_ULPI_ENABLE);
+		debug("pin mux is configured for ULPI, IFC & SDHC disabled\n");
+		break;
+	default:
+		printf("wrong mux interface type\n");
+		i2c_set_bus_num(orig_bus);
+		return -1;
+	}
+	i2c_set_bus_num(orig_bus);
+	return 0;
+wr_err:
+	printf("pca9557: i2c write failed\n");
+	i2c_set_bus_num(orig_bus);
+	return -1;
+}
+
 #ifndef CONFIG_SDCARD
+void board_reset(void)
+{
+	/* mux to IFC to enable CPLD for reset */
+	if (pin_mux != MUX_TYPE_IFC)
+		config_pin_mux(MUX_TYPE_IFC);
+}
+#endif
+
 int misc_init_r(void)
 {
+#ifndef CONFIG_SDCARD
 	struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE);
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 
@@ -355,6 +439,34 @@  int misc_init_r(void)
 		out_8(&cpld_data->spi_cs0_sel, MUX_CPLD_SPICS0_FLASH);
 	}
 
+	if (hwconfig("esdhc")) {
+		pin_mux = MUX_TYPE_SDHC;
+		config_pin_mux(MUX_TYPE_SDHC);
+	}
+#else
+	pin_mux = MUX_TYPE_SDHC;
+#endif
 	return 0;
 }
-#endif
+
+static int pin_mux_cmd(cmd_tbl_t *cmdtp, int flag, int argc,
+					char * const argv[])
+{
+	if (argc < 2)
+		return CMD_RET_USAGE;
+	if (strcmp(argv[1], "ifc") == 0)
+		config_pin_mux(MUX_TYPE_IFC);
+	else if (strcmp(argv[1], "sdhc") == 0)
+		config_pin_mux(MUX_TYPE_SDHC);
+	else if (strcmp(argv[1], "ulpi") == 0)
+		config_pin_mux(MUX_TYPE_ULPI);
+	else
+		return CMD_RET_USAGE;
+	return 0;
+}
+
+U_BOOT_CMD(
+	mux, 2, 0, pin_mux_cmd,
+	"configure multiplexing pin for IFC/SDHC/ULPI buses",
+	"bus_type[ifc/sdhc/ulpi] (e.g. mux sdhc)"
+);
diff --git a/include/configs/P1010RDB.h b/include/configs/P1010RDB.h
index 5185597..259bb6a 100644
--- a/include/configs/P1010RDB.h
+++ b/include/configs/P1010RDB.h
@@ -156,11 +156,9 @@ 
 #define CONFIG_DDR_CLK_FREQ	66666666 /* DDRCLK on P1010 RDB */
 #define CONFIG_SYS_CLK_FREQ	66666666 /* SYSCLK for P1010 RDB */
 
-#ifndef CONFIG_SDCARD
 #define CONFIG_MISC_INIT_R
-#endif
-
 #define CONFIG_HWCONFIG
+
 /*
  * These can be toggled for performance analysis, otherwise use default.
  */
@@ -485,6 +483,8 @@  extern unsigned long get_sdram_size(void);
 #define CONFIG_SYS_I2C_SLAVE		0x7F
 #define CONFIG_SYS_I2C_OFFSET		0x3000
 #define CONFIG_SYS_I2C2_OFFSET		0x3100
+#define CONFIG_SYS_I2C_PCA9557_ADDR	0x18
+#define CONFIG_SYS_PCA9557_BUS_NUM	0
 
 /* I2C EEPROM */
 #undef CONFIG_ID_EEPROM
@@ -570,11 +570,10 @@  extern unsigned long get_sdram_size(void);
 #define CONFIG_LBA48
 #endif /* #ifdef CONFIG_FSL_SATA  */
 
-/*  SD interface will only be available in case of SD boot */
 #ifdef CONFIG_SDCARD
-#define CONFIG_MMC
-#define CONFIG_DEF_HWCONFIG		esdhc
+#define CONFIG_DEF_HWCONFIG	esdhc
 #endif
+#define CONFIG_MMC
 
 #ifdef CONFIG_MMC
 #define CONFIG_CMD_MMC