1 /* 2 * (C) Copyright 2002 3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 /* 9 * SPI Read/Write Utilities 10 */ 11 12 #include <common.h> 13 #include <command.h> 14 #include <dm.h> 15 #include <errno.h> 16 #include <spi.h> 17 18 /*----------------------------------------------------------------------- 19 * Definitions 20 */ 21 22 #ifndef MAX_SPI_BYTES 23 # define MAX_SPI_BYTES 32 /* Maximum number of bytes we can handle */ 24 #endif 25 26 #ifndef CONFIG_DEFAULT_SPI_BUS 27 # define CONFIG_DEFAULT_SPI_BUS 0 28 #endif 29 #ifndef CONFIG_DEFAULT_SPI_MODE 30 # define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0 31 #endif 32 33 /* 34 * Values from last command. 35 */ 36 static unsigned int bus; 37 static unsigned int cs; 38 static unsigned int mode; 39 static int bitlen; 40 static uchar dout[MAX_SPI_BYTES]; 41 static uchar din[MAX_SPI_BYTES]; 42 43 static int do_spi_xfer(int bus, int cs) 44 { 45 struct spi_slave *slave; 46 int ret = 0; 47 48 #ifdef CONFIG_DM_SPI 49 char name[30], *str; 50 struct udevice *dev; 51 52 snprintf(name, sizeof(name), "generic_%d:%d", bus, cs); 53 str = strdup(name); 54 if (!str) 55 return -ENOMEM; 56 ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv", 57 str, &dev, &slave); 58 if (ret) 59 return ret; 60 #else 61 slave = spi_setup_slave(bus, cs, 1000000, mode); 62 if (!slave) { 63 printf("Invalid device %d:%d\n", bus, cs); 64 return -EINVAL; 65 } 66 #endif 67 68 ret = spi_claim_bus(slave); 69 if (ret) 70 goto done; 71 ret = spi_xfer(slave, bitlen, dout, din, 72 SPI_XFER_BEGIN | SPI_XFER_END); 73 #ifndef CONFIG_DM_SPI 74 /* We don't get an error code in this case */ 75 if (ret) 76 ret = -EIO; 77 #endif 78 if (ret) { 79 printf("Error %d during SPI transaction\n", ret); 80 } else { 81 int j; 82 83 for (j = 0; j < ((bitlen + 7) / 8); j++) 84 printf("%02X", din[j]); 85 printf("\n"); 86 } 87 done: 88 spi_release_bus(slave); 89 #ifndef CONFIG_DM_SPI 90 spi_free_slave(slave); 91 #endif 92 93 return ret; 94 } 95 96 /* 97 * SPI read/write 98 * 99 * Syntax: 100 * spi {dev} {num_bits} {dout} 101 * {dev} is the device number for controlling chip select (see TBD) 102 * {num_bits} is the number of bits to send & receive (base 10) 103 * {dout} is a hexadecimal string of data to send 104 * The command prints out the hexadecimal string received via SPI. 105 */ 106 107 int do_spi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 108 { 109 char *cp = 0; 110 uchar tmp; 111 int j; 112 113 /* 114 * We use the last specified parameters, unless new ones are 115 * entered. 116 */ 117 118 if ((flag & CMD_FLAG_REPEAT) == 0) 119 { 120 if (argc >= 2) { 121 mode = CONFIG_DEFAULT_SPI_MODE; 122 bus = simple_strtoul(argv[1], &cp, 10); 123 if (*cp == ':') { 124 cs = simple_strtoul(cp+1, &cp, 10); 125 } else { 126 cs = bus; 127 bus = CONFIG_DEFAULT_SPI_BUS; 128 } 129 if (*cp == '.') 130 mode = simple_strtoul(cp+1, NULL, 10); 131 } 132 if (argc >= 3) 133 bitlen = simple_strtoul(argv[2], NULL, 10); 134 if (argc >= 4) { 135 cp = argv[3]; 136 for(j = 0; *cp; j++, cp++) { 137 tmp = *cp - '0'; 138 if(tmp > 9) 139 tmp -= ('A' - '0') - 10; 140 if(tmp > 15) 141 tmp -= ('a' - 'A'); 142 if(tmp > 15) { 143 printf("Hex conversion error on %c\n", *cp); 144 return 1; 145 } 146 if((j % 2) == 0) 147 dout[j / 2] = (tmp << 4); 148 else 149 dout[j / 2] |= tmp; 150 } 151 } 152 } 153 154 if ((bitlen < 0) || (bitlen > (MAX_SPI_BYTES * 8))) { 155 printf("Invalid bitlen %d\n", bitlen); 156 return 1; 157 } 158 159 if (do_spi_xfer(bus, cs)) 160 return 1; 161 162 return 0; 163 } 164 165 /***************************************************/ 166 167 U_BOOT_CMD( 168 sspi, 5, 1, do_spi, 169 "SPI utility command", 170 "[<bus>:]<cs>[.<mode>] <bit_len> <dout> - Send and receive bits\n" 171 "<bus> - Identifies the SPI bus\n" 172 "<cs> - Identifies the chip select\n" 173 "<mode> - Identifies the SPI mode to use\n" 174 "<bit_len> - Number of bits to send (base 10)\n" 175 "<dout> - Hexadecimal string that gets sent" 176 ); 177