1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2014 Google, Inc 4 * 5 * (C) Copyright 2002 6 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. 7 * 8 * Influenced by code from: 9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 10 */ 11 12 #include <common.h> 13 #include <dm.h> 14 #include <errno.h> 15 #include <fdtdec.h> 16 #include <malloc.h> 17 #include <spi.h> 18 #include <asm/gpio.h> 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 struct soft_spi_platdata { 23 struct gpio_desc cs; 24 struct gpio_desc sclk; 25 struct gpio_desc mosi; 26 struct gpio_desc miso; 27 int spi_delay_us; 28 int flags; 29 }; 30 31 #define SPI_MASTER_NO_RX BIT(0) 32 #define SPI_MASTER_NO_TX BIT(1) 33 34 struct soft_spi_priv { 35 unsigned int mode; 36 }; 37 38 static int soft_spi_scl(struct udevice *dev, int bit) 39 { 40 struct udevice *bus = dev_get_parent(dev); 41 struct soft_spi_platdata *plat = dev_get_platdata(bus); 42 43 dm_gpio_set_value(&plat->sclk, bit); 44 45 return 0; 46 } 47 48 static int soft_spi_sda(struct udevice *dev, int bit) 49 { 50 struct udevice *bus = dev_get_parent(dev); 51 struct soft_spi_platdata *plat = dev_get_platdata(bus); 52 53 dm_gpio_set_value(&plat->mosi, bit); 54 55 return 0; 56 } 57 58 static int soft_spi_cs_activate(struct udevice *dev) 59 { 60 struct udevice *bus = dev_get_parent(dev); 61 struct soft_spi_platdata *plat = dev_get_platdata(bus); 62 63 dm_gpio_set_value(&plat->cs, 0); 64 dm_gpio_set_value(&plat->sclk, 0); 65 dm_gpio_set_value(&plat->cs, 1); 66 67 return 0; 68 } 69 70 static int soft_spi_cs_deactivate(struct udevice *dev) 71 { 72 struct udevice *bus = dev_get_parent(dev); 73 struct soft_spi_platdata *plat = dev_get_platdata(bus); 74 75 dm_gpio_set_value(&plat->cs, 0); 76 77 return 0; 78 } 79 80 static int soft_spi_claim_bus(struct udevice *dev) 81 { 82 /* 83 * Make sure the SPI clock is in idle state as defined for 84 * this slave. 85 */ 86 return soft_spi_scl(dev, 0); 87 } 88 89 static int soft_spi_release_bus(struct udevice *dev) 90 { 91 /* Nothing to do */ 92 return 0; 93 } 94 95 /*----------------------------------------------------------------------- 96 * SPI transfer 97 * 98 * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks 99 * "bitlen" bits in the SPI MISO port. That's just the way SPI works. 100 * 101 * The source of the outgoing bits is the "dout" parameter and the 102 * destination of the input bits is the "din" parameter. Note that "dout" 103 * and "din" can point to the same memory location, in which case the 104 * input data overwrites the output data (since both are buffered by 105 * temporary variables, this is OK). 106 */ 107 static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen, 108 const void *dout, void *din, unsigned long flags) 109 { 110 struct udevice *bus = dev_get_parent(dev); 111 struct soft_spi_priv *priv = dev_get_priv(bus); 112 struct soft_spi_platdata *plat = dev_get_platdata(bus); 113 uchar tmpdin = 0; 114 uchar tmpdout = 0; 115 const u8 *txd = dout; 116 u8 *rxd = din; 117 int cpha = priv->mode & SPI_CPHA; 118 unsigned int j; 119 120 debug("spi_xfer: slave %s:%s dout %08X din %08X bitlen %u\n", 121 dev->parent->name, dev->name, *(uint *)txd, *(uint *)rxd, 122 bitlen); 123 124 if (flags & SPI_XFER_BEGIN) 125 soft_spi_cs_activate(dev); 126 127 for (j = 0; j < bitlen; j++) { 128 /* 129 * Check if it is time to work on a new byte. 130 */ 131 if ((j % 8) == 0) { 132 if (txd) 133 tmpdout = *txd++; 134 else 135 tmpdout = 0; 136 if (j != 0) { 137 if (rxd) 138 *rxd++ = tmpdin; 139 } 140 tmpdin = 0; 141 } 142 143 if (!cpha) 144 soft_spi_scl(dev, 0); 145 if ((plat->flags & SPI_MASTER_NO_TX) == 0) 146 soft_spi_sda(dev, !!(tmpdout & 0x80)); 147 udelay(plat->spi_delay_us); 148 if (cpha) 149 soft_spi_scl(dev, 0); 150 else 151 soft_spi_scl(dev, 1); 152 tmpdin <<= 1; 153 if ((plat->flags & SPI_MASTER_NO_RX) == 0) 154 tmpdin |= dm_gpio_get_value(&plat->miso); 155 tmpdout <<= 1; 156 udelay(plat->spi_delay_us); 157 if (cpha) 158 soft_spi_scl(dev, 1); 159 } 160 /* 161 * If the number of bits isn't a multiple of 8, shift the last 162 * bits over to left-justify them. Then store the last byte 163 * read in. 164 */ 165 if (rxd) { 166 if ((bitlen % 8) != 0) 167 tmpdin <<= 8 - (bitlen % 8); 168 *rxd++ = tmpdin; 169 } 170 171 if (flags & SPI_XFER_END) 172 soft_spi_cs_deactivate(dev); 173 174 return 0; 175 } 176 177 static int soft_spi_set_speed(struct udevice *dev, unsigned int speed) 178 { 179 /* Accept any speed */ 180 return 0; 181 } 182 183 static int soft_spi_set_mode(struct udevice *dev, unsigned int mode) 184 { 185 struct soft_spi_priv *priv = dev_get_priv(dev); 186 187 priv->mode = mode; 188 189 return 0; 190 } 191 192 static const struct dm_spi_ops soft_spi_ops = { 193 .claim_bus = soft_spi_claim_bus, 194 .release_bus = soft_spi_release_bus, 195 .xfer = soft_spi_xfer, 196 .set_speed = soft_spi_set_speed, 197 .set_mode = soft_spi_set_mode, 198 }; 199 200 static int soft_spi_ofdata_to_platdata(struct udevice *dev) 201 { 202 struct soft_spi_platdata *plat = dev->platdata; 203 const void *blob = gd->fdt_blob; 204 int node = dev_of_offset(dev); 205 206 plat->spi_delay_us = fdtdec_get_int(blob, node, "spi-delay-us", 0); 207 208 return 0; 209 } 210 211 static int soft_spi_probe(struct udevice *dev) 212 { 213 struct spi_slave *slave = dev_get_parent_priv(dev); 214 struct soft_spi_platdata *plat = dev->platdata; 215 int cs_flags, clk_flags; 216 int ret; 217 218 cs_flags = (slave->mode & SPI_CS_HIGH) ? 0 : GPIOD_ACTIVE_LOW; 219 clk_flags = (slave->mode & SPI_CPOL) ? GPIOD_ACTIVE_LOW : 0; 220 221 if (gpio_request_by_name(dev, "cs-gpios", 0, &plat->cs, 222 GPIOD_IS_OUT | cs_flags) || 223 gpio_request_by_name(dev, "gpio-sck", 0, &plat->sclk, 224 GPIOD_IS_OUT | clk_flags)) 225 return -EINVAL; 226 227 ret = gpio_request_by_name(dev, "gpio-mosi", 0, &plat->mosi, 228 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 229 if (ret) 230 plat->flags |= SPI_MASTER_NO_TX; 231 232 ret = gpio_request_by_name(dev, "gpio-miso", 0, &plat->miso, 233 GPIOD_IS_IN); 234 if (ret) 235 plat->flags |= SPI_MASTER_NO_RX; 236 237 if ((plat->flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX)) == 238 (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX)) 239 return -EINVAL; 240 241 return 0; 242 } 243 244 static const struct udevice_id soft_spi_ids[] = { 245 { .compatible = "spi-gpio" }, 246 { } 247 }; 248 249 U_BOOT_DRIVER(soft_spi) = { 250 .name = "soft_spi", 251 .id = UCLASS_SPI, 252 .of_match = soft_spi_ids, 253 .ops = &soft_spi_ops, 254 .ofdata_to_platdata = soft_spi_ofdata_to_platdata, 255 .platdata_auto_alloc_size = sizeof(struct soft_spi_platdata), 256 .priv_auto_alloc_size = sizeof(struct soft_spi_priv), 257 .probe = soft_spi_probe, 258 }; 259