2 * Copyright (c) 2014 Google, Inc
5 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
7 * Influenced by code from:
8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
10 * SPDX-License-Identifier: GPL-2.0+
21 DECLARE_GLOBAL_DATA_PTR
;
23 struct soft_spi_platdata
{
25 struct gpio_desc sclk
;
26 struct gpio_desc mosi
;
27 struct gpio_desc miso
;
32 #define SPI_MASTER_NO_RX BIT(0)
33 #define SPI_MASTER_NO_TX BIT(1)
35 struct soft_spi_priv
{
39 static int soft_spi_scl(struct udevice
*dev
, int bit
)
41 struct udevice
*bus
= dev_get_parent(dev
);
42 struct soft_spi_platdata
*plat
= dev_get_platdata(bus
);
44 dm_gpio_set_value(&plat
->sclk
, bit
);
49 static int soft_spi_sda(struct udevice
*dev
, int bit
)
51 struct udevice
*bus
= dev_get_parent(dev
);
52 struct soft_spi_platdata
*plat
= dev_get_platdata(bus
);
54 dm_gpio_set_value(&plat
->mosi
, bit
);
59 static int soft_spi_cs_activate(struct udevice
*dev
)
61 struct udevice
*bus
= dev_get_parent(dev
);
62 struct soft_spi_platdata
*plat
= dev_get_platdata(bus
);
64 dm_gpio_set_value(&plat
->cs
, 0);
65 dm_gpio_set_value(&plat
->sclk
, 0);
66 dm_gpio_set_value(&plat
->cs
, 1);
71 static int soft_spi_cs_deactivate(struct udevice
*dev
)
73 struct udevice
*bus
= dev_get_parent(dev
);
74 struct soft_spi_platdata
*plat
= dev_get_platdata(bus
);
76 dm_gpio_set_value(&plat
->cs
, 0);
81 static int soft_spi_claim_bus(struct udevice
*dev
)
84 * Make sure the SPI clock is in idle state as defined for
87 return soft_spi_scl(dev
, 0);
90 static int soft_spi_release_bus(struct udevice
*dev
)
96 /*-----------------------------------------------------------------------
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.
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).
108 static int soft_spi_xfer(struct udevice
*dev
, unsigned int bitlen
,
109 const void *dout
, void *din
, unsigned long flags
)
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
);
116 const u8
*txd
= dout
;
118 int cpha
= priv
->mode
& SPI_CPHA
;
121 debug("spi_xfer: slave %s:%s dout %08X din %08X bitlen %u\n",
122 dev
->parent
->name
, dev
->name
, *(uint
*)txd
, *(uint
*)rxd
,
125 if (flags
& SPI_XFER_BEGIN
)
126 soft_spi_cs_activate(dev
);
128 for (j
= 0; j
< bitlen
; j
++) {
130 * Check if it is time to work on a new byte.
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
);
150 soft_spi_scl(dev
, 0);
152 soft_spi_scl(dev
, 1);
154 if ((plat
->flags
& SPI_MASTER_NO_RX
) == 0)
155 tmpdin
|= dm_gpio_get_value(&plat
->miso
);
157 udelay(plat
->spi_delay_us
);
159 soft_spi_scl(dev
, 1);
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
167 if ((bitlen
% 8) != 0)
168 tmpdin
<<= 8 - (bitlen
% 8);
172 if (flags
& SPI_XFER_END
)
173 soft_spi_cs_deactivate(dev
);
178 static int soft_spi_set_speed(struct udevice
*dev
, unsigned int speed
)
180 /* Accept any speed */
184 static int soft_spi_set_mode(struct udevice
*dev
, unsigned int mode
)
186 struct soft_spi_priv
*priv
= dev_get_priv(dev
);
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
,
201 static int soft_spi_ofdata_to_platdata(struct udevice
*dev
)
203 struct soft_spi_platdata
*plat
= dev
->platdata
;
204 const void *blob
= gd
->fdt_blob
;
205 int node
= dev_of_offset(dev
);
207 plat
->spi_delay_us
= fdtdec_get_int(blob
, node
, "spi-delay-us", 0);
212 static int soft_spi_probe(struct udevice
*dev
)
214 struct spi_slave
*slave
= dev_get_parent_priv(dev
);
215 struct soft_spi_platdata
*plat
= dev
->platdata
;
216 int cs_flags
, clk_flags
;
219 cs_flags
= (slave
->mode
& SPI_CS_HIGH
) ? 0 : GPIOD_ACTIVE_LOW
;
220 clk_flags
= (slave
->mode
& SPI_CPOL
) ? GPIOD_ACTIVE_LOW
: 0;
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
))
228 ret
= gpio_request_by_name(dev
, "gpio-mosi", 0, &plat
->mosi
,
229 GPIOD_IS_OUT
| GPIOD_IS_OUT_ACTIVE
);
231 plat
->flags
|= SPI_MASTER_NO_TX
;
233 ret
= gpio_request_by_name(dev
, "gpio-miso", 0, &plat
->miso
,
236 plat
->flags
|= SPI_MASTER_NO_RX
;
238 if ((plat
->flags
& (SPI_MASTER_NO_RX
| SPI_MASTER_NO_TX
)) ==
239 (SPI_MASTER_NO_RX
| SPI_MASTER_NO_TX
))
245 static const struct udevice_id soft_spi_ids
[] = {
246 { .compatible
= "spi-gpio" },
250 U_BOOT_DRIVER(soft_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
,