xref: /rk3399_rockchip-uboot/board/renesas/stout/cpld.c (revision 13a3972585af60ec367d209cedbd3601e0c77467)
1*21871138SVladimir Barinov /*
2*21871138SVladimir Barinov  * Stout board CPLD access support
3*21871138SVladimir Barinov  *
4*21871138SVladimir Barinov  * Copyright (C) 2015 Renesas Electronics Europe GmbH
5*21871138SVladimir Barinov  * Copyright (C) 2015 Renesas Electronics Corporation
6*21871138SVladimir Barinov  * Copyright (C) 2015 Cogent Embedded, Inc.
7*21871138SVladimir Barinov  *
8*21871138SVladimir Barinov  * SPDX-License-Identifier: GPL-2.0
9*21871138SVladimir Barinov  */
10*21871138SVladimir Barinov 
11*21871138SVladimir Barinov #include <common.h>
12*21871138SVladimir Barinov #include <asm/io.h>
13*21871138SVladimir Barinov #include <asm/gpio.h>
14*21871138SVladimir Barinov #include "cpld.h"
15*21871138SVladimir Barinov 
16*21871138SVladimir Barinov #define SCLK			GPIO_GP_3_24
17*21871138SVladimir Barinov #define SSTBZ			GPIO_GP_3_25
18*21871138SVladimir Barinov #define MOSI			GPIO_GP_3_26
19*21871138SVladimir Barinov #define MISO			GPIO_GP_3_27
20*21871138SVladimir Barinov 
21*21871138SVladimir Barinov #define CPLD_ADDR_MODE		0x00 /* RW */
22*21871138SVladimir Barinov #define CPLD_ADDR_MUX		0x01 /* RW */
23*21871138SVladimir Barinov #define CPLD_ADDR_HDMI		0x02 /* RW */
24*21871138SVladimir Barinov #define CPLD_ADDR_DIPSW		0x08 /* R */
25*21871138SVladimir Barinov #define CPLD_ADDR_RESET		0x80 /* RW */
26*21871138SVladimir Barinov #define CPLD_ADDR_VERSION	0xFF /* R */
27*21871138SVladimir Barinov 
cpld_read(u8 addr)28*21871138SVladimir Barinov static u32 cpld_read(u8 addr)
29*21871138SVladimir Barinov {
30*21871138SVladimir Barinov 	int i;
31*21871138SVladimir Barinov 	u32 data = 0;
32*21871138SVladimir Barinov 
33*21871138SVladimir Barinov 	for (i = 0; i < 8; i++) {
34*21871138SVladimir Barinov 		gpio_set_value(MOSI, addr & 0x80); /* MSB first */
35*21871138SVladimir Barinov 		gpio_set_value(SCLK, 1);
36*21871138SVladimir Barinov 		addr <<= 1;
37*21871138SVladimir Barinov 		gpio_set_value(SCLK, 0);
38*21871138SVladimir Barinov 	}
39*21871138SVladimir Barinov 
40*21871138SVladimir Barinov 	gpio_set_value(MOSI, 0); /* READ */
41*21871138SVladimir Barinov 	gpio_set_value(SSTBZ, 0);
42*21871138SVladimir Barinov 	gpio_set_value(SCLK, 1);
43*21871138SVladimir Barinov 	gpio_set_value(SCLK, 0);
44*21871138SVladimir Barinov 	gpio_set_value(SSTBZ, 1);
45*21871138SVladimir Barinov 
46*21871138SVladimir Barinov 	for (i = 0; i < 32; i++) {
47*21871138SVladimir Barinov 		gpio_set_value(SCLK, 1);
48*21871138SVladimir Barinov 		data <<= 1;
49*21871138SVladimir Barinov 		data |= gpio_get_value(MISO); /* MSB first */
50*21871138SVladimir Barinov 		gpio_set_value(SCLK, 0);
51*21871138SVladimir Barinov 	}
52*21871138SVladimir Barinov 
53*21871138SVladimir Barinov 	return data;
54*21871138SVladimir Barinov }
55*21871138SVladimir Barinov 
cpld_write(u8 addr,u32 data)56*21871138SVladimir Barinov static void cpld_write(u8 addr, u32 data)
57*21871138SVladimir Barinov {
58*21871138SVladimir Barinov 	int i;
59*21871138SVladimir Barinov 
60*21871138SVladimir Barinov 	for (i = 0; i < 32; i++) {
61*21871138SVladimir Barinov 		gpio_set_value(MOSI, data & (1 << 31)); /* MSB first */
62*21871138SVladimir Barinov 		gpio_set_value(SCLK, 1);
63*21871138SVladimir Barinov 		data <<= 1;
64*21871138SVladimir Barinov 		gpio_set_value(SCLK, 0);
65*21871138SVladimir Barinov 	}
66*21871138SVladimir Barinov 
67*21871138SVladimir Barinov 	for (i = 0; i < 8; i++) {
68*21871138SVladimir Barinov 		gpio_set_value(MOSI, addr & 0x80); /* MSB first */
69*21871138SVladimir Barinov 		gpio_set_value(SCLK, 1);
70*21871138SVladimir Barinov 		addr <<= 1;
71*21871138SVladimir Barinov 		gpio_set_value(SCLK, 0);
72*21871138SVladimir Barinov 	}
73*21871138SVladimir Barinov 
74*21871138SVladimir Barinov 	gpio_set_value(MOSI, 1); /* WRITE */
75*21871138SVladimir Barinov 	gpio_set_value(SSTBZ, 0);
76*21871138SVladimir Barinov 	gpio_set_value(SCLK, 1);
77*21871138SVladimir Barinov 	gpio_set_value(SCLK, 0);
78*21871138SVladimir Barinov 	gpio_set_value(SSTBZ, 1);
79*21871138SVladimir Barinov }
80*21871138SVladimir Barinov 
81*21871138SVladimir Barinov /* LSI pin pull-up control */
82*21871138SVladimir Barinov #define PUPR3		0xe606010C
83*21871138SVladimir Barinov #define PUPR3_SD3_DAT1	(1 << 27)
84*21871138SVladimir Barinov 
cpld_init(void)85*21871138SVladimir Barinov void cpld_init(void)
86*21871138SVladimir Barinov {
87*21871138SVladimir Barinov 	u32 val;
88*21871138SVladimir Barinov 
89*21871138SVladimir Barinov 	/* PULL-UP on MISO line */
90*21871138SVladimir Barinov 	val = readl(PUPR3);
91*21871138SVladimir Barinov 	val |= PUPR3_SD3_DAT1;
92*21871138SVladimir Barinov 	writel(val, PUPR3);
93*21871138SVladimir Barinov 
94*21871138SVladimir Barinov 	gpio_request(SCLK, NULL);
95*21871138SVladimir Barinov 	gpio_request(SSTBZ, NULL);
96*21871138SVladimir Barinov 	gpio_request(MOSI, NULL);
97*21871138SVladimir Barinov 	gpio_request(MISO, NULL);
98*21871138SVladimir Barinov 
99*21871138SVladimir Barinov 	gpio_direction_output(SCLK, 0);
100*21871138SVladimir Barinov 	gpio_direction_output(SSTBZ, 1);
101*21871138SVladimir Barinov 	gpio_direction_output(MOSI, 0);
102*21871138SVladimir Barinov 	gpio_direction_input(MISO);
103*21871138SVladimir Barinov 
104*21871138SVladimir Barinov 	/* dummy read */
105*21871138SVladimir Barinov 	cpld_read(CPLD_ADDR_VERSION);
106*21871138SVladimir Barinov 
107*21871138SVladimir Barinov 	printf("CPLD version:              0x%08x\n",
108*21871138SVladimir Barinov 	       cpld_read(CPLD_ADDR_VERSION));
109*21871138SVladimir Barinov 	printf("H2 Mode setting (MD0..28): 0x%08x\n",
110*21871138SVladimir Barinov 	       cpld_read(CPLD_ADDR_MODE));
111*21871138SVladimir Barinov 	printf("Multiplexer settings:      0x%08x\n",
112*21871138SVladimir Barinov 	       cpld_read(CPLD_ADDR_MUX));
113*21871138SVladimir Barinov 	printf("HDMI setting:              0x%08x\n",
114*21871138SVladimir Barinov 	       cpld_read(CPLD_ADDR_HDMI));
115*21871138SVladimir Barinov 	printf("DIPSW (SW3):               0x%08x\n",
116*21871138SVladimir Barinov 	       cpld_read(CPLD_ADDR_DIPSW));
117*21871138SVladimir Barinov 
118*21871138SVladimir Barinov #ifdef CONFIG_SH_SDHI
119*21871138SVladimir Barinov 	/* switch MUX to SD0 */
120*21871138SVladimir Barinov 	val = cpld_read(CPLD_ADDR_MUX);
121*21871138SVladimir Barinov 	val &= ~MUX_MSK_SD0;
122*21871138SVladimir Barinov 	val |= MUX_VAL_SD0;
123*21871138SVladimir Barinov 	cpld_write(CPLD_ADDR_MUX, val);
124*21871138SVladimir Barinov #endif
125*21871138SVladimir Barinov }
126*21871138SVladimir Barinov 
do_cpld(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])127*21871138SVladimir Barinov static int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
128*21871138SVladimir Barinov {
129*21871138SVladimir Barinov 	u32 addr, val;
130*21871138SVladimir Barinov 
131*21871138SVladimir Barinov 	if (argc < 3)
132*21871138SVladimir Barinov 		return CMD_RET_USAGE;
133*21871138SVladimir Barinov 
134*21871138SVladimir Barinov 	addr = simple_strtoul(argv[2], NULL, 16);
135*21871138SVladimir Barinov 	if (!(addr == CPLD_ADDR_VERSION || addr == CPLD_ADDR_MODE ||
136*21871138SVladimir Barinov 	      addr == CPLD_ADDR_MUX || addr == CPLD_ADDR_HDMI ||
137*21871138SVladimir Barinov 	      addr == CPLD_ADDR_DIPSW || addr == CPLD_ADDR_RESET)) {
138*21871138SVladimir Barinov 		printf("cpld invalid addr\n");
139*21871138SVladimir Barinov 		return CMD_RET_USAGE;
140*21871138SVladimir Barinov 	}
141*21871138SVladimir Barinov 
142*21871138SVladimir Barinov 	if (argc == 3 && strcmp(argv[1], "read") == 0) {
143*21871138SVladimir Barinov 		printf("0x%x\n", cpld_read(addr));
144*21871138SVladimir Barinov 	} else if (argc == 4 && strcmp(argv[1], "write") == 0) {
145*21871138SVladimir Barinov 		val = simple_strtoul(argv[3], NULL, 16);
146*21871138SVladimir Barinov 		if (addr == CPLD_ADDR_MUX) {
147*21871138SVladimir Barinov 			/* never mask SCIFA0 console */
148*21871138SVladimir Barinov 			val &= ~MUX_MSK_SCIFA0_USB;
149*21871138SVladimir Barinov 			val |= MUX_VAL_SCIFA0_USB;
150*21871138SVladimir Barinov 		}
151*21871138SVladimir Barinov 		cpld_write(addr, val);
152*21871138SVladimir Barinov 	}
153*21871138SVladimir Barinov 
154*21871138SVladimir Barinov 	return 0;
155*21871138SVladimir Barinov }
156*21871138SVladimir Barinov 
157*21871138SVladimir Barinov U_BOOT_CMD(
158*21871138SVladimir Barinov 	cpld, 4, 1, do_cpld,
159*21871138SVladimir Barinov 	"CPLD access",
160*21871138SVladimir Barinov 	"read addr\n"
161*21871138SVladimir Barinov 	"cpld write addr val\n"
162*21871138SVladimir Barinov );
163*21871138SVladimir Barinov 
reset_cpu(ulong addr)164*21871138SVladimir Barinov void reset_cpu(ulong addr)
165*21871138SVladimir Barinov {
166*21871138SVladimir Barinov 	cpld_write(CPLD_ADDR_RESET, 1);
167*21871138SVladimir Barinov }
168