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