Home | History | Annotate | Download | only in cmd
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2002
      4  * Gerald Van Baren, Custom IDEAS, vanbaren (at) 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