summaryrefslogtreecommitdiff
path: root/board/renesas/stout/cpld.c
diff options
context:
space:
mode:
authorVladimir Barinov <vladimir.barinov@cogentembedded.com>2015-07-20 20:49:59 +0300
committerNobuhiro Iwamatsu <iwamatsu@nigauri.org>2015-08-31 17:32:59 +0900
commit21871138b7686b36dd8ae97cab5dc1e9c5c6e183 (patch)
treee44c863566f312a23394dfc10560e4192f7707bc /board/renesas/stout/cpld.c
parentb8f91e2c92b7a8e01234fe384186202a24238f92 (diff)
arm: rmobile: Add Stout board support
Stout is an entry level development board based on R-Car H2 SoC (R8A7790) This commit supports the following peripherals: - SCIFA, I2C, Ethernet, QSPI, SDHI0/2, CPLD Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Diffstat (limited to 'board/renesas/stout/cpld.c')
-rw-r--r--board/renesas/stout/cpld.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/board/renesas/stout/cpld.c b/board/renesas/stout/cpld.c
new file mode 100644
index 0000000000..5640e1d28e
--- /dev/null
+++ b/board/renesas/stout/cpld.c
@@ -0,0 +1,167 @@
+/*
+ * Stout board CPLD access support
+ *
+ * Copyright (C) 2015 Renesas Electronics Europe GmbH
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include "cpld.h"
+
+#define SCLK GPIO_GP_3_24
+#define SSTBZ GPIO_GP_3_25
+#define MOSI GPIO_GP_3_26
+#define MISO GPIO_GP_3_27
+
+#define CPLD_ADDR_MODE 0x00 /* RW */
+#define CPLD_ADDR_MUX 0x01 /* RW */
+#define CPLD_ADDR_HDMI 0x02 /* RW */
+#define CPLD_ADDR_DIPSW 0x08 /* R */
+#define CPLD_ADDR_RESET 0x80 /* RW */
+#define CPLD_ADDR_VERSION 0xFF /* R */
+
+static u32 cpld_read(u8 addr)
+{
+ int i;
+ u32 data = 0;
+
+ for (i = 0; i < 8; i++) {
+ gpio_set_value(MOSI, addr & 0x80); /* MSB first */
+ gpio_set_value(SCLK, 1);
+ addr <<= 1;
+ gpio_set_value(SCLK, 0);
+ }
+
+ gpio_set_value(MOSI, 0); /* READ */
+ gpio_set_value(SSTBZ, 0);
+ gpio_set_value(SCLK, 1);
+ gpio_set_value(SCLK, 0);
+ gpio_set_value(SSTBZ, 1);
+
+ for (i = 0; i < 32; i++) {
+ gpio_set_value(SCLK, 1);
+ data <<= 1;
+ data |= gpio_get_value(MISO); /* MSB first */
+ gpio_set_value(SCLK, 0);
+ }
+
+ return data;
+}
+
+static void cpld_write(u8 addr, u32 data)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ gpio_set_value(MOSI, data & (1 << 31)); /* MSB first */
+ gpio_set_value(SCLK, 1);
+ data <<= 1;
+ gpio_set_value(SCLK, 0);
+ }
+
+ for (i = 0; i < 8; i++) {
+ gpio_set_value(MOSI, addr & 0x80); /* MSB first */
+ gpio_set_value(SCLK, 1);
+ addr <<= 1;
+ gpio_set_value(SCLK, 0);
+ }
+
+ gpio_set_value(MOSI, 1); /* WRITE */
+ gpio_set_value(SSTBZ, 0);
+ gpio_set_value(SCLK, 1);
+ gpio_set_value(SCLK, 0);
+ gpio_set_value(SSTBZ, 1);
+}
+
+/* LSI pin pull-up control */
+#define PUPR3 0xe606010C
+#define PUPR3_SD3_DAT1 (1 << 27)
+
+void cpld_init(void)
+{
+ u32 val;
+
+ /* PULL-UP on MISO line */
+ val = readl(PUPR3);
+ val |= PUPR3_SD3_DAT1;
+ writel(val, PUPR3);
+
+ gpio_request(SCLK, NULL);
+ gpio_request(SSTBZ, NULL);
+ gpio_request(MOSI, NULL);
+ gpio_request(MISO, NULL);
+
+ gpio_direction_output(SCLK, 0);
+ gpio_direction_output(SSTBZ, 1);
+ gpio_direction_output(MOSI, 0);
+ gpio_direction_input(MISO);
+
+ /* dummy read */
+ cpld_read(CPLD_ADDR_VERSION);
+
+ printf("CPLD version: 0x%08x\n",
+ cpld_read(CPLD_ADDR_VERSION));
+ printf("H2 Mode setting (MD0..28): 0x%08x\n",
+ cpld_read(CPLD_ADDR_MODE));
+ printf("Multiplexer settings: 0x%08x\n",
+ cpld_read(CPLD_ADDR_MUX));
+ printf("HDMI setting: 0x%08x\n",
+ cpld_read(CPLD_ADDR_HDMI));
+ printf("DIPSW (SW3): 0x%08x\n",
+ cpld_read(CPLD_ADDR_DIPSW));
+
+#ifdef CONFIG_SH_SDHI
+ /* switch MUX to SD0 */
+ val = cpld_read(CPLD_ADDR_MUX);
+ val &= ~MUX_MSK_SD0;
+ val |= MUX_VAL_SD0;
+ cpld_write(CPLD_ADDR_MUX, val);
+#endif
+}
+
+static int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ u32 addr, val;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[2], NULL, 16);
+ if (!(addr == CPLD_ADDR_VERSION || addr == CPLD_ADDR_MODE ||
+ addr == CPLD_ADDR_MUX || addr == CPLD_ADDR_HDMI ||
+ addr == CPLD_ADDR_DIPSW || addr == CPLD_ADDR_RESET)) {
+ printf("cpld invalid addr\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (argc == 3 && strcmp(argv[1], "read") == 0) {
+ printf("0x%x\n", cpld_read(addr));
+ } else if (argc == 4 && strcmp(argv[1], "write") == 0) {
+ val = simple_strtoul(argv[3], NULL, 16);
+ if (addr == CPLD_ADDR_MUX) {
+ /* never mask SCIFA0 console */
+ val &= ~MUX_MSK_SCIFA0_USB;
+ val |= MUX_VAL_SCIFA0_USB;
+ }
+ cpld_write(addr, val);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ cpld, 4, 1, do_cpld,
+ "CPLD access",
+ "read addr\n"
+ "cpld write addr val\n"
+);
+
+void reset_cpu(ulong addr)
+{
+ cpld_write(CPLD_ADDR_RESET, 1);
+}