1 /*
2  * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <lib/mmio.h>
8 #include "ulcb_cpld.h"
9 
10 #define SCLK			8	/* GP_6_8 */
11 #define SSTBZ			3	/* GP_2_3 */
12 #define MOSI			7	/* GP_6_7 */
13 
14 #define CPLD_ADDR_RESET		0x80	/* RW */
15 
16 /* LSI Multiplexed Pin Setting Mask Register */
17 #define PFC_PMMR		0xE6060000
18 
19 /* General output registers */
20 #define GPIO_OUTDT2		0xE6052008
21 #define GPIO_OUTDT6		0xE6055408
22 
23 /* General input/output switching registers */
24 #define GPIO_INOUTSEL2		0xE6052004
25 #define GPIO_INOUTSEL6		0xE6055404
26 
27 /* General IO/Interrupt Switching Register */
28 #define GPIO_IOINTSEL6		0xE6055400
29 
30 /* GPIO/perihperal function select */
31 #define PFC_GPSR2		0xE6060108
32 #define PFC_GPSR6		0xE6060118
33 
gpio_set_value(uint32_t addr,uint8_t gpio,uint32_t val)34 static void gpio_set_value(uint32_t addr, uint8_t gpio, uint32_t val)
35 {
36 	uint32_t reg;
37 
38 	reg = mmio_read_32(addr);
39 	if (val)
40 		reg |= (1 << gpio);
41 	else
42 		reg &= ~(1 << gpio);
43 	mmio_write_32(addr, reg);
44 }
45 
gpio_direction_output(uint32_t addr,uint8_t gpio)46 static void gpio_direction_output(uint32_t addr, uint8_t gpio)
47 {
48 	uint32_t reg;
49 
50 	reg = mmio_read_32(addr);
51 	reg |= (1 << gpio);
52 	mmio_write_32(addr, reg);
53 }
54 
gpio_pfc(uint32_t addr,uint8_t gpio)55 static void gpio_pfc(uint32_t addr, uint8_t gpio)
56 {
57 	uint32_t reg;
58 
59 	reg = mmio_read_32(addr);
60 	reg &= ~(1 << gpio);
61 	mmio_write_32(PFC_PMMR, ~reg);
62 	mmio_write_32(addr, reg);
63 }
64 
cpld_write(uint8_t addr,uint32_t data)65 static void cpld_write(uint8_t addr, uint32_t data)
66 {
67 	int i;
68 
69 	for (i = 0; i < 32; i++) {
70 		/* MSB first */
71 		gpio_set_value(GPIO_OUTDT6, MOSI, data & (1U << 31));
72 		gpio_set_value(GPIO_OUTDT6, SCLK, 1);
73 		data <<= 1;
74 		gpio_set_value(GPIO_OUTDT6, SCLK, 0);
75 	}
76 
77 	for (i = 0; i < 8; i++) {
78 		/* MSB first */
79 		gpio_set_value(GPIO_OUTDT6, MOSI, addr & 0x80);
80 		gpio_set_value(GPIO_OUTDT6, SCLK, 1);
81 		addr <<= 1;
82 		gpio_set_value(GPIO_OUTDT6, SCLK, 0);
83 	}
84 
85 	/* WRITE */
86 	gpio_set_value(GPIO_OUTDT6, MOSI, 1);
87 	gpio_set_value(GPIO_OUTDT2, SSTBZ, 0);
88 	gpio_set_value(GPIO_OUTDT6, SCLK, 1);
89 	gpio_set_value(GPIO_OUTDT6, SCLK, 0);
90 	gpio_set_value(GPIO_OUTDT2, SSTBZ, 1);
91 }
92 
cpld_init(void)93 static void cpld_init(void)
94 {
95 	gpio_pfc(PFC_GPSR6, SCLK);
96 	gpio_pfc(PFC_GPSR2, SSTBZ);
97 	gpio_pfc(PFC_GPSR6, MOSI);
98 
99 	gpio_set_value(GPIO_IOINTSEL6, SCLK, 0);
100 	gpio_set_value(GPIO_OUTDT6, SCLK, 0);
101 	gpio_set_value(GPIO_OUTDT2, SSTBZ, 1);
102 	gpio_set_value(GPIO_OUTDT6, MOSI, 0);
103 
104 	gpio_direction_output(GPIO_INOUTSEL6, SCLK);
105 	gpio_direction_output(GPIO_INOUTSEL2, SSTBZ);
106 	gpio_direction_output(GPIO_INOUTSEL6, MOSI);
107 }
108 
rcar_cpld_reset_cpu(void)109 void rcar_cpld_reset_cpu(void)
110 {
111 	cpld_init();
112 
113 	cpld_write(CPLD_ADDR_RESET, 1);
114 }
115