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