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