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