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