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 <command.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <spi.h>
15 
16 /*-----------------------------------------------------------------------
17  * Definitions
18  */
19 
20 #ifndef MAX_SPI_BYTES
21 #   define MAX_SPI_BYTES 32	/* Maximum number of bytes we can handle */
22 #endif
23 
24 /*
25  * Values from last command.
26  */
27 static unsigned int	bus;
28 static unsigned int	cs;
29 static unsigned int	mode;
30 static unsigned int	freq;
31 static int		bitlen;
32 static uchar		dout[MAX_SPI_BYTES];
33 static uchar		din[MAX_SPI_BYTES];
34 
do_spi_xfer(int bus,int cs)35 static int do_spi_xfer(int bus, int cs)
36 {
37 	struct spi_slave *slave;
38 	int ret = 0;
39 
40 #if CONFIG_IS_ENABLED(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, freq, mode, "spi_generic_drv",
49 				  str, &dev, &slave);
50 	if (ret)
51 		return ret;
52 #else
53 	slave = spi_setup_slave(bus, cs, freq, 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 #if !CONFIG_IS_ENABLED(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 #if !CONFIG_IS_ENABLED(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 
do_spi(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])99 int do_spi(struct cmd_tbl *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 	if (freq == 0)
110 		freq = 1000000;
111 
112 	if ((flag & CMD_FLAG_REPEAT) == 0)
113 	{
114 		if (argc < 2)
115 			return CMD_RET_USAGE;
116 
117 		if (argc >= 2) {
118 			mode = CONFIG_DEFAULT_SPI_MODE;
119 			bus = dectoul(argv[1], &cp);
120 			if (*cp == ':') {
121 				cs = dectoul(cp + 1, &cp);
122 			} else {
123 				cs = bus;
124 				bus = CONFIG_DEFAULT_SPI_BUS;
125 			}
126 			if (*cp == '.')
127 				mode = dectoul(cp + 1, &cp);
128 			if (*cp == '@')
129 				freq = dectoul(cp + 1, &cp);
130 		}
131 		if (argc >= 3)
132 			bitlen = dectoul(argv[2], NULL);
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>][@<freq>] <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 	"<freq>    - Identifies the SPI bus frequency in Hz\n"
174 	"<bit_len> - Number of bits to send (base 10)\n"
175 	"<dout>    - Hexadecimal string that gets sent"
176 );
177