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