All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] arm,davinci: update for enbw_cmc board
Date: Sat,  5 May 2012 08:32:50 +0200	[thread overview]
Message-ID: <1336199570-22151-1-git-send-email-hs@denx.de> (raw)

- change gpio pin settings:

  - gpio pin 6[13] (PLC reset) default value low
  - gpio pin 6[0] (TPM reset) default value low
  - 4 new GPIO pins
      pin  i/o   name
    - 3[9] input Board Type
    - 2[7] input HW-ID0
    - 2[6] input HW-ID1
    - 2[3] input HW-ID2

- read board type and hw id from gpio pins on the enbw_cmc board,
  and use board type for setting up different gpio pin settings.

- do not pass "davinci_mmc.use_dma=0" to linux, as MMC now
  works with DMA.

- update logbuf support:
  store post word in RTC scratch register

- add support for configuring KSZ8864RMN switch through
  a config file on u-boot startup. For more infos see:
  doc/README.switch_config

Signed-off-by: Heiko Schocher <hs@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Tom Rini <tom.rini@gmail.com>
Cc: Christian Riesch <christian.riesch@omicron.at>
Cc: Sandeep Paulraj <s-paulraj@ti.com>
---
 board/enbw/enbw_cmc/enbw_cmc.c |  345 +++++++++++++++++++++++++++++++++++++---
 doc/README.switch_config       |   25 +++
 include/configs/enbw_cmc.h     |   20 ++-
 3 files changed, 362 insertions(+), 28 deletions(-)
 create mode 100644 doc/README.switch_config

diff --git a/board/enbw/enbw_cmc/enbw_cmc.c b/board/enbw/enbw_cmc/enbw_cmc.c
index 6c0d931..22cef1d 100644
--- a/board/enbw/enbw_cmc/enbw_cmc.c
+++ b/board/enbw/enbw_cmc/enbw_cmc.c
@@ -35,6 +35,8 @@
 #include <mmc.h>
 #include <net.h>
 #include <netdev.h>
+#include <spi.h>
+#include <linux/ctype.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/da850_lowlevel.h>
@@ -86,16 +88,22 @@ static const struct pinmux_config enbw_pins[] = {
 	{ pinmux(5), 1, 0 },
 	{ pinmux(5), 1, 3 },
 	{ pinmux(5), 1, 7 },
-	{ pinmux(6), 1, 0 },
-	{ pinmux(6), 1, 1 },
+	{ pinmux(5), 1, 5 },
+	{ pinmux(5), 1, 4 },
+	{ pinmux(5), 1, 3 },
+	{ pinmux(5), 1, 2 },
+	{ pinmux(5), 1, 1 },
+	{ pinmux(5), 1, 0 },
+	{ pinmux(6), 8, 0 },
+	{ pinmux(6), 8, 1 },
 	{ pinmux(6), 8, 2 },
 	{ pinmux(6), 8, 3 },
-	{ pinmux(6), 1, 4 },
+	{ pinmux(6), 8, 4 },
 	{ pinmux(6), 8, 5 },
 	{ pinmux(6), 1, 7 },
 	{ pinmux(7), 8, 2 },
 	{ pinmux(7), 1, 3 },
-	{ pinmux(7), 1, 6 },
+	{ pinmux(7), 8, 6 },
 	{ pinmux(7), 1, 7 },
 	{ pinmux(13), 8, 2 },
 	{ pinmux(13), 8, 3 },
@@ -163,24 +171,37 @@ struct gpio_config {
 	unsigned char value;
 };
 
-static const struct gpio_config enbw_gpio_config[] = {
+static const struct gpio_config enbw_gpio_config_hut[] = {
+	{ "RS485 enable",	8, 11, 1, 0 },
+	{ "RS485 iso",		8, 10, 1, 1 },
+	{ "W2HUT RS485 Rx ena",	8,  9, 1, 0 },
+	{ "W2HUT RS485 iso",	8,  8, 1, 1 },
+};
+
+static const struct gpio_config enbw_gpio_config_w[] = {
 	{ "RS485 enable",	8, 11, 1, 0 },
 	{ "RS485 iso",		8, 10, 1, 0 },
 	{ "W2HUT RS485 Rx ena",	8,  9, 1, 0 },
 	{ "W2HUT RS485 iso",	8,  8, 1, 0 },
+};
+
+static const struct gpio_config enbw_gpio_config[] = {
 	{ "LAN reset",		7, 15, 1, 1 },
 	{ "ena 11V PLC",	7, 14, 1, 0 },
 	{ "ena 1.5V PLC",	7, 13, 1, 0 },
 	{ "disable VBUS",	7, 12, 1, 1 },
-	{ "PLC reset",		6, 13, 1, 1 },
+	{ "PLC reset",		6, 13, 1, 0 },
 	{ "LCM RS",		6, 12, 1, 0 },
 	{ "LCM R/W",		6, 11, 1, 0 },
 	{ "PLC pairing",	6, 10, 1, 1 },
 	{ "PLC MDIO CLK",	6,  9, 1, 0 },
 	{ "HK218",		6,  8, 1, 0 },
 	{ "HK218 Rx",		6,  1, 1, 1 },
-	{ "TPM reset",		6,  0, 1, 1 },
-	{ "LCM E",		2,  2, 1, 1 },
+	{ "TPM reset",		6,  0, 1, 0 },
+	{ "Board-Type",		3,  9, 0, 0 },
+	{ "HW-ID0",		2,  7, 0, 0 },
+	{ "HW-ID1",		2,  6, 0, 0 },
+	{ "HW-ID2",		2,  3, 0, 0 },
 	{ "PV-IF RxD ena",	0, 15, 1, 1 },
 	{ "LED1",		1, 15, 1, 1 },
 	{ "LED2",		0,  1, 1, 1 },
@@ -229,34 +250,57 @@ static void enbw_cmc_switch(int port, int on)
 	}
 }
 
-int board_init(void)
+static int enbw_cmc_init_gpio(const struct gpio_config *conf, int sz)
 {
 	int i, ret;
 
-#ifndef CONFIG_USE_IRQ
-	irq_init();
-#endif
-	/* address of boot parameters, not used as booting with DTT */
-	gd->bd->bi_boot_params = 0;
-
-	for (i = 0; i < ARRAY_SIZE(enbw_gpio_config); i++) {
-		int gpio = enbw_gpio_config[i].bank * 16 +
-			enbw_gpio_config[i].gpio;
+	for (i = 0; i < sz; i++) {
+		int gpio = conf[i].bank * 16 +
+			conf[i].gpio;
 
-		ret = gpio_request(gpio, enbw_gpio_config[i].name);
+		ret = gpio_request(gpio, conf[i].name);
 		if (ret) {
 			printf("%s: Could not get %s gpio\n", __func__,
-				enbw_gpio_config[i].name);
-			return -1;
+				conf[i].name);
+			return ret;
 		}
 
-		if (enbw_gpio_config[i].out)
+		if (conf[i].out)
 			gpio_direction_output(gpio,
-				enbw_gpio_config[i].value);
+				conf[i].value);
 		else
 			gpio_direction_input(gpio);
 	}
 
+	return 0;
+}
+
+int board_init(void)
+{
+	int board_type, hw_id;
+
+#ifndef CONFIG_USE_IRQ
+	irq_init();
+#endif
+	/* address of boot parameters, not used as booting with DTT */
+	gd->bd->bi_boot_params = 0;
+
+	enbw_cmc_init_gpio(enbw_gpio_config, ARRAY_SIZE(enbw_gpio_config));
+
+	/* detect HW version */
+	board_type = gpio_get_value(CONFIG_ENBW_CMC_BOARD_TYPE);
+	hw_id = gpio_get_value(CONFIG_ENBW_CMC_HW_ID_BIT0) +
+		(gpio_get_value(CONFIG_ENBW_CMC_HW_ID_BIT1) << 1) +
+		(gpio_get_value(CONFIG_ENBW_CMC_HW_ID_BIT2) << 2);
+	printf("BOARD: CMC-%s hw id: %d\n", (board_type ? "w2" : "hut"),
+		hw_id);
+	if (board_type)
+		enbw_cmc_init_gpio(enbw_gpio_config_w,
+			ARRAY_SIZE(enbw_gpio_config_w));
+	else
+		enbw_cmc_init_gpio(enbw_gpio_config_hut,
+			ARRAY_SIZE(enbw_gpio_config_hut));
+
 	/* setup the SUSPSRC for ARM to control emulation suspend */
 	clrbits_le32(&davinci_syscfg_regs->suspsrc,
 		(DAVINCI_SYSCFG_SUSPSRC_EMAC | DAVINCI_SYSCFG_SUSPSRC_I2C |
@@ -267,14 +311,229 @@ int board_init(void)
 }
 
 #ifdef CONFIG_DRIVER_TI_EMAC
+
+#define KSZ_CMD_READ	0x03
+#define KSZ_CMD_WRITE	0x02
+#define KSZ_ID		0x95
+
+static int enbw_cmc_switch_read(struct spi_slave *spi, u8 reg, u8 *val)
+{
+	unsigned long flags = SPI_XFER_BEGIN;
+	int ret;
+	int cmd_len;
+	u8 cmd[2];
+
+	cmd[0] = KSZ_CMD_READ;
+	cmd[1] = reg;
+	cmd_len = 2;
+
+	ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
+	if (ret) {
+		debug("Failed to send command (%zu bytes): %d\n",
+				cmd_len, ret);
+		return -EINVAL;
+	}
+	flags |= SPI_XFER_END;
+	*val = 0;
+	cmd_len = 1;
+	ret = spi_xfer(spi, cmd_len * 8, NULL, val, flags);
+	if (ret) {
+		debug("Failed to read (%zu bytes): %d\n",
+				cmd_len, ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int enbw_cmc_switch_read_ident(struct spi_slave *spi)
+{
+	int ret;
+	u8 val;
+
+	ret = enbw_cmc_switch_read(spi, 0, &val);
+	if (ret) {
+		debug("Failed to read\n");
+		return -EINVAL;
+	}
+
+	if (val != KSZ_ID)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int enbw_cmc_switch_write(struct spi_slave *spi, unsigned long reg,
+		unsigned long val)
+{
+	unsigned long flags = SPI_XFER_BEGIN;
+	int ret;
+	int cmd_len;
+	u8 cmd[3];
+
+	cmd[0] = KSZ_CMD_WRITE;
+	cmd[1] = reg;
+	cmd[2] = val;
+	cmd_len = 3;
+	flags |= SPI_XFER_END;
+
+	ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
+	if (ret) {
+		debug("Failed to send command (%zu bytes): %d\n",
+				cmd_len, ret);
+		return -EINVAL;
+	}
+
+	udelay(1000);
+	ret = enbw_cmc_switch_read(spi, reg, &cmd[0]);
+	if (ret) {
+		debug("Failed to read\n");
+		return -EINVAL;
+	}
+	if (val != cmd[0])
+		debug("warning: reg: %lx va: %x soll: %lx\n",
+			reg, cmd[0], val);
+
+	return 0;
+}
+
+static int enbw_cmc_eof(unsigned char *ptr)
+{
+	if (*ptr == 0xff)
+		return 1;
+
+	return 0;
+}
+
+static unsigned char *enbw_cmc_getnewline(unsigned char *ptr)
+{
+	while (*ptr != 0x0a) {
+		ptr++;
+		if (enbw_cmc_eof(ptr))
+			return NULL;
+	}
+
+	ptr++;
+	return ptr;
+}
+
+static unsigned char *enbw_cmc_getvalue(unsigned char *ptr, int *value)
+{
+	int	end = 0;
+	*value = -EINVAL;
+
+	if (!isxdigit(*ptr))
+		end = 1;
+	while (end) {
+		if ((*ptr == '#') || (*ptr == ';')) {
+			ptr = enbw_cmc_getnewline(ptr);
+			return ptr;
+		}
+		if (ptr != NULL) {
+			if (isxdigit(*ptr)) {
+				end = 0;
+			} else if (*ptr == 0x0a) {
+				ptr++;
+				return ptr;
+			} else {
+				ptr++;
+				if (enbw_cmc_eof(ptr))
+					return NULL;
+			}
+		} else {
+			return NULL;
+		}
+	}
+	*value = (int)simple_strtoul((const char *)ptr, (char **)&ptr, 16);
+	ptr++;
+	return ptr;
+}
+
+static int enbw_cmc_config_switch(unsigned long addr)
+{
+	struct spi_slave *spi;
+	unsigned char *ptr = (unsigned char *)addr;
+	int value, reg;
+	int ret;
+	int bus, cs, max_hz, spi_mode;
+
+	debug("configure switch with file on addr: 0x%lx\n", addr);
+
+	bus = 0;
+	cs = 0;
+	max_hz = 1000000;
+	spi_mode = 0;
+
+	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
+	if (!spi) {
+		printf("Failed to set up slave\n");
+		return -EINVAL;
+	}
+
+	ret = spi_claim_bus(spi);
+	if (ret) {
+		debug("Failed to claim SPI bus: %d\n", ret);
+		goto err_claim_bus;
+	}
+
+	ret = enbw_cmc_switch_read_ident(spi);
+	if (ret)
+		goto err_claim_bus;
+
+	ptr = (unsigned char *)addr;
+	while (ptr != NULL) {
+		ptr = enbw_cmc_getvalue(ptr, &reg);
+		if (ptr != NULL) {
+			ptr = enbw_cmc_getvalue(ptr, &value);
+			if ((ptr != NULL) && (value >= 0))
+				if (enbw_cmc_switch_write(spi, reg, value))
+					goto err_read;
+		}
+	}
+	return 0;
+
+err_read:
+	spi_release_bus(spi);
+err_claim_bus:
+	spi_free_slave(spi);
+	return -EINVAL;
+}
+
+static int do_switch(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	unsigned long addr;
+
+	if (argc < 2)
+		return cmd_usage(cmdtp);
+
+	addr = simple_strtoul(argv[1], NULL, 16);
+	enbw_cmc_config_switch(addr);
+
+	return 0;
+}
+
+U_BOOT_CMD(switch, 3, 1, do_switch,
+	"switch addr",
+	"[addr]"
+);
+
 /*
  * Initializes on-board ethernet controllers.
  */
 int board_eth_init(bd_t *bis)
 {
-#ifdef CONFIG_DRIVER_TI_EMAC
+	const char *s;
+	size_t len;
+
 	davinci_emac_mii_mode_sel(0);
-#endif /* CONFIG_DRIVER_TI_EMAC */
+
+	/* send a config file to the switch */
+	s = hwconfig_subarg("switch", "config", &len);
+	if (len) {
+		unsigned long addr = simple_strtoul(s, NULL, 16);
+
+		enbw_cmc_config_switch(addr);
+	}
 
 	if (!davinci_emac_initialize()) {
 		printf("Error: Ethernet init failed!\n");
@@ -546,6 +805,29 @@ ulong bootcount_load(void)
 }
 #endif
 
+ulong post_word_load(void)
+{
+	struct davinci_rtc *reg =
+		(struct davinci_rtc *)CONFIG_SYS_POST_WORD_ADDR;
+
+	return in_be32(&reg->scratch2);
+}
+
+void post_word_store(ulong value)
+{
+	struct davinci_rtc *reg =
+		(struct davinci_rtc *)CONFIG_SYS_POST_WORD_ADDR;
+
+	/*
+	 * write RTC kick register to enable write
+	 * for RTC Scratch registers. Cratch0 and 1 are
+	 * used for bootcount values.
+	 */
+	writel(RTC_KICK0R_WE, &reg->kick0r);
+	writel(RTC_KICK1R_WE, &reg->kick1r);
+	out_be32(&reg->scratch2, value);
+}
+
 void board_gpio_init(void)
 {
 	struct davinci_gpio *gpio = davinci_gpio_bank01;
@@ -558,6 +840,19 @@ void board_gpio_init(void)
 	clrbits_le32(&gpio->out_data, 0x8000407e);
 	/* set LED 1 - 5 to state on */
 	setbits_le32(&gpio->out_data, 0x8000001e);
+
+	/*
+	 * set some gpio pins to low, this is needed early,
+	 * so we have no gpio Interface here
+	 * gpios:
+	 * 8[8]  Mode PV select  low
+	 * 8[9]  Debug Rx Enable low
+	 * 8[10] Mode Select PV  low
+	 * 8[11] Counter Interface RS485 Rx-Enable low
+	 */
+	gpio = davinci_gpio_bank8;
+	clrbits_le32(&gpio->dir, 0x00000f00);
+	clrbits_le32(&gpio->out_data, 0x0f00);
 }
 
 int board_late_init(void)
diff --git a/doc/README.switch_config b/doc/README.switch_config
new file mode 100644
index 0000000..f890373
--- /dev/null
+++ b/doc/README.switch_config
@@ -0,0 +1,25 @@
+On the enbw_cmc board is a KSZ8864RMN switch which needs
+configured through spi before working. This is done on
+startup from u-boot through a config file stored at an
+address specified in the "hwconfig" environment variable,
+subcommand "config".
+
+For example on the enbw_cmc board:
+
+hwconfig=switch:lan=on,pwl=off,config=0x60160000
+
+The file has the following structure:
+
+- a comment starts with a '#' or a ';' and ends with a newline
+- The switch needs for its config a reg/value pair, so we
+  have two columns in the file:
+    reg  : contains the register address
+    value: contains a 8 bit register value
+  This 2 columns are seperated through space or tab.
+
+example (minimal configuration on the enbw_cmc board):
+
+;reg    value   comment
+;-----------------------------------------
+0x01	0x00
+0x01	0x01    ; Start Switch with this configuration
diff --git a/include/configs/enbw_cmc.h b/include/configs/enbw_cmc.h
index 29b0d33..1c434ff 100644
--- a/include/configs/enbw_cmc.h
+++ b/include/configs/enbw_cmc.h
@@ -103,6 +103,14 @@
 #define CONFIG_SYS_DTT_HYSTERESIS	3
 
 /*
+ * SPI Configuration
+ */
+#define CONFIG_DAVINCI_SPI
+#define CONFIG_SYS_SPI_BASE		DAVINCI_SPI1_BASE
+#define CONFIG_SYS_SPI_CLK		clk_get(DAVINCI_SPI1_CLKID)
+#define CONFIG_CMD_SPI
+
+/*
  * Flash & Environment
  */
 #ifdef CONFIG_USE_NAND
@@ -226,9 +234,9 @@
 	"key_magic_2=2\0"						\
 	"key_magic_3=3\0"						\
 	"magic_keys=0123\0"						\
-	"hwconfig=switch:lan=on,pwl=off\0"				\
+	"hwconfig=switch:lan=on,pwl=off,config=0x60100000\0"		\
 	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0"		\
-	"addmisc=setenv bootargs ${bootargs} davinci_mmc.use_dma=0\0"	\
+	"addmisc=setenv bootargs ${bootargs}\0"				\
 	"mtdids=" MTDIDS_DEFAULT "\0"					\
 	"mtdparts=" MTDPARTS_DEFAULT "\0"				\
 	"logversion=2\0"						\
@@ -338,6 +346,11 @@
 #define CONFIG_CMD_FAT
 #define CONFIG_CMD_MMC
 
+/* GPIO */
+#define CONFIG_ENBW_CMC_BOARD_TYPE	57
+#define CONFIG_ENBW_CMC_HW_ID_BIT0	39
+#define CONFIG_ENBW_CMC_HW_ID_BIT1	38
+#define CONFIG_ENBW_CMC_HW_ID_BIT2	35
 
 /* FDT support */
 #define CONFIG_OF_LIBFDT
@@ -440,7 +453,8 @@
 #define CONFIG_SYS_DV_NOR_BOOT_CFG	(0x11)
 
 #define CONFIG_POST	(CONFIG_SYS_POST_MEMORY)
-#define CONFIG_SYS_POST_WORD_ADDR 0x8001FFF0
+#define CONFIG_POST_EXTERNAL_WORD_FUNCS
+#define CONFIG_SYS_POST_WORD_ADDR DAVINCI_RTC_BASE
 #define CONFIG_LOGBUFFER
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
 
-- 
1.7.7.6

             reply	other threads:[~2012-05-05  6:32 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-05  6:32 Heiko Schocher [this message]
2012-05-14 16:45 ` [U-Boot] [PATCH] arm,davinci: update for enbw_cmc board Tom Rini
2012-05-14 17:32   ` Tom Rini
2012-05-15  7:19     ` Heiko Schocher
2012-05-15  6:24 ` [U-Boot] [PATCH v2] " Heiko Schocher
2012-07-02  4:53   ` Heiko Schocher
2012-07-02 15:05     ` Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1336199570-22151-1-git-send-email-hs@denx.de \
    --to=hs@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.