1 /* 2 * ULCB board CPLD access support 3 * 4 * Copyright (C) 2017 Renesas Electronics Corporation 5 * Copyright (C) 2017 Cogent Embedded, Inc. 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <spi.h> 12 #include <asm/io.h> 13 #include <asm/gpio.h> 14 15 #define SCLK GPIO_GP_6_8 16 #define SSTBZ GPIO_GP_2_3 17 #define MOSI GPIO_GP_6_7 18 #define MISO GPIO_GP_6_10 19 20 #define CPLD_ADDR_MODE 0x00 /* RW */ 21 #define CPLD_ADDR_MUX 0x02 /* RW */ 22 #define CPLD_ADDR_DIPSW6 0x08 /* R */ 23 #define CPLD_ADDR_RESET 0x80 /* RW */ 24 #define CPLD_ADDR_VERSION 0xFF /* R */ 25 26 static int cpld_initialized; 27 28 int spi_cs_is_valid(unsigned int bus, unsigned int cs) 29 { 30 /* Always valid */ 31 return 1; 32 } 33 34 void spi_cs_activate(struct spi_slave *slave) 35 { 36 /* Always active */ 37 } 38 39 void spi_cs_deactivate(struct spi_slave *slave) 40 { 41 /* Always active */ 42 } 43 44 void ulcb_softspi_sda(int set) 45 { 46 gpio_set_value(MOSI, set); 47 } 48 49 void ulcb_softspi_scl(int set) 50 { 51 gpio_set_value(SCLK, set); 52 } 53 54 unsigned char ulcb_softspi_read(void) 55 { 56 return !!gpio_get_value(MISO); 57 } 58 59 static void cpld_rw(u8 write) 60 { 61 gpio_set_value(MOSI, write); 62 gpio_set_value(SSTBZ, 0); 63 gpio_set_value(SCLK, 1); 64 gpio_set_value(SCLK, 0); 65 gpio_set_value(SSTBZ, 1); 66 } 67 68 static u32 cpld_read(u8 addr) 69 { 70 u32 data = 0; 71 72 spi_xfer(NULL, 8, &addr, NULL, SPI_XFER_BEGIN | SPI_XFER_END); 73 74 cpld_rw(0); 75 76 spi_xfer(NULL, 32, NULL, &data, SPI_XFER_BEGIN | SPI_XFER_END); 77 78 return swab32(data); 79 } 80 81 static void cpld_write(u8 addr, u32 data) 82 { 83 data = swab32(data); 84 85 spi_xfer(NULL, 32, &data, NULL, SPI_XFER_BEGIN | SPI_XFER_END); 86 87 spi_xfer(NULL, 8, NULL, &addr, SPI_XFER_BEGIN | SPI_XFER_END); 88 89 cpld_rw(1); 90 } 91 92 static void cpld_init(void) 93 { 94 if (cpld_initialized) 95 return; 96 97 /* PULL-UP on MISO line */ 98 setbits_le32(PFC_PUEN5, PUEN_SSI_SDATA4); 99 100 gpio_request(SCLK, NULL); 101 gpio_request(SSTBZ, NULL); 102 gpio_request(MOSI, NULL); 103 gpio_request(MISO, NULL); 104 105 gpio_direction_output(SCLK, 0); 106 gpio_direction_output(SSTBZ, 1); 107 gpio_direction_output(MOSI, 0); 108 gpio_direction_input(MISO); 109 110 /* Dummy read */ 111 cpld_read(CPLD_ADDR_VERSION); 112 113 cpld_initialized = 1; 114 } 115 116 static int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 117 { 118 u32 addr, val; 119 120 cpld_init(); 121 122 if (argc == 2 && strcmp(argv[1], "info") == 0) { 123 printf("CPLD version:\t\t\t0x%08x\n", 124 cpld_read(CPLD_ADDR_VERSION)); 125 printf("H3 Mode setting (MD0..28):\t0x%08x\n", 126 cpld_read(CPLD_ADDR_MODE)); 127 printf("Multiplexer settings:\t\t0x%08x\n", 128 cpld_read(CPLD_ADDR_MUX)); 129 printf("DIPSW (SW6):\t\t\t0x%08x\n", 130 cpld_read(CPLD_ADDR_DIPSW6)); 131 return 0; 132 } 133 134 if (argc < 3) 135 return CMD_RET_USAGE; 136 137 addr = simple_strtoul(argv[2], NULL, 16); 138 if (!(addr == CPLD_ADDR_VERSION || addr == CPLD_ADDR_MODE || 139 addr == CPLD_ADDR_MUX || addr == CPLD_ADDR_DIPSW6 || 140 addr == CPLD_ADDR_RESET)) { 141 printf("Invalid CPLD register address\n"); 142 return CMD_RET_USAGE; 143 } 144 145 if (argc == 3 && strcmp(argv[1], "read") == 0) { 146 printf("0x%x\n", cpld_read(addr)); 147 } else if (argc == 4 && strcmp(argv[1], "write") == 0) { 148 val = simple_strtoul(argv[3], NULL, 16); 149 cpld_write(addr, val); 150 } 151 152 return 0; 153 } 154 155 U_BOOT_CMD( 156 cpld, 4, 1, do_cpld, 157 "CPLD access", 158 "info\n" 159 "cpld read addr\n" 160 "cpld write addr val\n" 161 ); 162 163 void reset_cpu(ulong addr) 164 { 165 cpld_init(); 166 cpld_write(CPLD_ADDR_RESET, 1); 167 } 168