xref: /openbmc/u-boot/cmd/spi.c (revision a5c289b9bca3805fa35e42f389dc8225c6b916be)
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  	if (!str)
55  		return -ENOMEM;
56  	ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv",
57  				 str, &dev, &slave);
58  	if (ret)
59  		return ret;
60  #else
61  	slave = spi_setup_slave(bus, cs, 1000000, mode);
62  	if (!slave) {
63  		printf("Invalid device %d:%d\n", bus, cs);
64  		return -EINVAL;
65  	}
66  #endif
67  
68  	ret = spi_claim_bus(slave);
69  	if (ret)
70  		goto done;
71  	ret = spi_xfer(slave, bitlen, dout, din,
72  		       SPI_XFER_BEGIN | SPI_XFER_END);
73  #ifndef CONFIG_DM_SPI
74  	/* We don't get an error code in this case */
75  	if (ret)
76  		ret = -EIO;
77  #endif
78  	if (ret) {
79  		printf("Error %d during SPI transaction\n", ret);
80  	} else {
81  		int j;
82  
83  		for (j = 0; j < ((bitlen + 7) / 8); j++)
84  			printf("%02X", din[j]);
85  		printf("\n");
86  	}
87  done:
88  	spi_release_bus(slave);
89  #ifndef CONFIG_DM_SPI
90  	spi_free_slave(slave);
91  #endif
92  
93  	return ret;
94  }
95  
96  /*
97   * SPI read/write
98   *
99   * Syntax:
100   *   spi {dev} {num_bits} {dout}
101   *     {dev} is the device number for controlling chip select (see TBD)
102   *     {num_bits} is the number of bits to send & receive (base 10)
103   *     {dout} is a hexadecimal string of data to send
104   * The command prints out the hexadecimal string received via SPI.
105   */
106  
107  int do_spi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
108  {
109  	char  *cp = 0;
110  	uchar tmp;
111  	int   j;
112  
113  	/*
114  	 * We use the last specified parameters, unless new ones are
115  	 * entered.
116  	 */
117  
118  	if ((flag & CMD_FLAG_REPEAT) == 0)
119  	{
120  		if (argc >= 2) {
121  			mode = CONFIG_DEFAULT_SPI_MODE;
122  			bus = simple_strtoul(argv[1], &cp, 10);
123  			if (*cp == ':') {
124  				cs = simple_strtoul(cp+1, &cp, 10);
125  			} else {
126  				cs = bus;
127  				bus = CONFIG_DEFAULT_SPI_BUS;
128  			}
129  			if (*cp == '.')
130  				mode = simple_strtoul(cp+1, NULL, 10);
131  		}
132  		if (argc >= 3)
133  			bitlen = simple_strtoul(argv[2], NULL, 10);
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  
167  U_BOOT_CMD(
168  	sspi,	5,	1,	do_spi,
169  	"SPI utility command",
170  	"[<bus>:]<cs>[.<mode>] <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  	"<bit_len> - Number of bits to send (base 10)\n"
175  	"<dout>    - Hexadecimal string that gets sent"
176  );
177