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 */ 28static unsigned int bus; 29static unsigned int cs; 30static unsigned int mode; 31static unsigned int freq; 32static int bitlen; 33static uchar dout[MAX_SPI_BYTES]; 34static uchar din[MAX_SPI_BYTES]; 35 36static int do_spi_xfer(int bus, int cs) 37{ 38 struct spi_slave *slave; 39 int ret = 0; 40 41#if CONFIG_IS_ENABLED(DM_SPI) 42 char name[30], *str; 43 struct udevice *dev; 44 45 snprintf(name, sizeof(name), "generic_%d:%d", bus, cs); 46 str = strdup(name); 47 if (!str) 48 return -ENOMEM; 49 ret = _spi_get_bus_and_cs(bus, cs, freq, mode, "spi_generic_drv", 50 str, &dev, &slave); 51 if (ret) 52 return ret; 53#else 54 slave = spi_setup_slave(bus, cs, freq, mode); 55 if (!slave) { 56 printf("Invalid device %d:%d\n", bus, cs); 57 return -EINVAL; 58 } 59#endif 60 61 ret = spi_claim_bus(slave); 62 if (ret) 63 goto done; 64 ret = spi_xfer(slave, bitlen, dout, din, 65 SPI_XFER_BEGIN | SPI_XFER_END); 66#if !CONFIG_IS_ENABLED(DM_SPI) 67 /* We don't get an error code in this case */ 68 if (ret) 69 ret = -EIO; 70#endif 71 if (ret) { 72 printf("Error %d during SPI transaction\n", ret); 73 } else { 74 int j; 75 76 for (j = 0; j < ((bitlen + 7) / 8); j++) 77 printf("%02X", din[j]); 78 printf("\n"); 79 } 80done: 81 spi_release_bus(slave); 82#if !CONFIG_IS_ENABLED(DM_SPI) 83 spi_free_slave(slave); 84#endif 85 86 return ret; 87} 88 89/* 90 * SPI read/write 91 * 92 * Syntax: 93 * spi {dev} {num_bits} {dout} 94 * {dev} is the device number for controlling chip select (see TBD) 95 * {num_bits} is the number of bits to send & receive (base 10) 96 * {dout} is a hexadecimal string of data to send 97 * The command prints out the hexadecimal string received via SPI. 98 */ 99 100int do_spi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 101{ 102 char *cp = 0; 103 uchar tmp; 104 int j; 105 106 /* 107 * We use the last specified parameters, unless new ones are 108 * entered. 109 */ 110 if (freq == 0) 111 freq = 1000000; 112 113 if ((flag & CMD_FLAG_REPEAT) == 0) 114 { 115 if (argc < 2) 116 return CMD_RET_USAGE; 117 118 if (argc >= 2) { 119 mode = CONFIG_DEFAULT_SPI_MODE; 120 bus = dectoul(argv[1], &cp); 121 if (*cp == ':') { 122 cs = dectoul(cp + 1, &cp); 123 } else { 124 cs = bus; 125 bus = CONFIG_DEFAULT_SPI_BUS; 126 } 127 if (*cp == '.') 128 mode = dectoul(cp + 1, &cp); 129 if (*cp == '@') 130 freq = dectoul(cp + 1, &cp); 131 } 132 if (argc >= 3) 133 bitlen = dectoul(argv[2], NULL); 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 167U_BOOT_CMD( 168 sspi, 5, 1, do_spi, 169 "SPI utility command", 170 "[<bus>:]<cs>[.<mode>][@<freq>] <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 "<freq> - Identifies the SPI bus frequency in Hz\n" 175 "<bit_len> - Number of bits to send (base 10)\n" 176 "<dout> - Hexadecimal string that gets sent" 177); 178