summaryrefslogtreecommitdiff
path: root/drivers/renesas
diff options
context:
space:
mode:
authorJorge Ramirez-Ortiz <jramirez@baylibre.com>2018-09-23 09:39:19 +0200
committerldts <jorge.ramirez.ortiz@gmail.com>2018-10-17 18:40:36 +0200
commit3a81abb607d923a962b31c0177e30b98488b3476 (patch)
tree4b96e2e0096dc59da7bc9b23b28a545667401590 /drivers/renesas
parent070b0f0821148f5569727213817bc7b788535f00 (diff)
rcar_gen3: drivers: cpld
Signed-off-by: ldts <jramirez@baylibre.com>
Diffstat (limited to 'drivers/renesas')
-rw-r--r--drivers/renesas/rcar/cpld/ulcb_cpld.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/renesas/rcar/cpld/ulcb_cpld.c b/drivers/renesas/rcar/cpld/ulcb_cpld.c
new file mode 100644
index 00000000..92e438a4
--- /dev/null
+++ b/drivers/renesas/rcar/cpld/ulcb_cpld.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+
+#define SCLK 8 /* GP_6_8 */
+#define SSTBZ 3 /* GP_2_3 */
+#define MOSI 7 /* GP_6_7 */
+
+#define CPLD_ADDR_RESET 0x80 /* RW */
+
+/* LSI Multiplexed Pin Setting Mask Register */
+#define PFC_PMMR 0xE6060000
+
+/* General output registers */
+#define GPIO_OUTDT2 0xE6052008
+#define GPIO_OUTDT6 0xE6055408
+
+/* General input/output switching registers */
+#define GPIO_INOUTSEL2 0xE6052004
+#define GPIO_INOUTSEL6 0xE6055404
+
+/* GPIO/perihperal function select */
+#define PFC_GPSR2 0xE6060108
+#define PFC_GPSR6 0xE6060118
+
+static void gpio_set_value(uint32_t addr, uint8_t gpio, uint32_t val)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(addr);
+ if (val)
+ reg |= (1 << gpio);
+ else
+ reg &= ~(1 << gpio);
+ mmio_write_32(addr, reg);
+}
+
+static void gpio_direction_output(uint32_t addr, uint8_t gpio)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(addr);
+ reg |= (1 << gpio);
+ mmio_write_32(addr, reg);
+}
+
+static void gpio_pfc(uint32_t addr, uint8_t gpio)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(addr);
+ reg &= ~(1 << gpio);
+ mmio_write_32(PFC_PMMR, ~reg);
+ mmio_write_32(addr, reg);
+}
+
+static void cpld_write(uint8_t addr, uint32_t data)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ /* MSB first */
+ gpio_set_value(GPIO_OUTDT6, MOSI, data & (1 << 31));
+ gpio_set_value(GPIO_OUTDT6, SCLK, 1);
+ data <<= 1;
+ gpio_set_value(GPIO_OUTDT6, SCLK, 0);
+ }
+
+ for (i = 0; i < 8; i++) {
+ /* MSB first */
+ gpio_set_value(GPIO_OUTDT6, MOSI, addr & 0x80);
+ gpio_set_value(GPIO_OUTDT6, SCLK, 1);
+ addr <<= 1;
+ gpio_set_value(GPIO_OUTDT6, SCLK, 0);
+ }
+
+ /* WRITE */
+ gpio_set_value(GPIO_OUTDT6, MOSI, 1);
+ gpio_set_value(GPIO_OUTDT2, SSTBZ, 0);
+ gpio_set_value(GPIO_OUTDT6, SCLK, 1);
+ gpio_set_value(GPIO_OUTDT6, SCLK, 0);
+ gpio_set_value(GPIO_OUTDT2, SSTBZ, 1);
+}
+
+static void cpld_init(void)
+{
+ gpio_pfc(PFC_GPSR6, SCLK);
+ gpio_pfc(PFC_GPSR2, SSTBZ);
+ gpio_pfc(PFC_GPSR6, MOSI);
+
+ gpio_set_value(GPIO_OUTDT6, SCLK, 0);
+ gpio_set_value(GPIO_OUTDT2, SSTBZ, 1);
+ gpio_set_value(GPIO_OUTDT6, MOSI, 0);
+
+ gpio_direction_output(GPIO_INOUTSEL6, SCLK);
+ gpio_direction_output(GPIO_INOUTSEL2, SSTBZ);
+ gpio_direction_output(GPIO_INOUTSEL6, MOSI);
+}
+
+void rcar_cpld_reset_cpu(void)
+{
+ cpld_init();
+
+ cpld_write(CPLD_ADDR_RESET, 1);
+}