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