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