+ soft_spi_cs_deactivate(dev);
+
+ return 0;
+}
+
+static int soft_spi_set_speed(struct udevice *dev, unsigned int speed)
+{
+ /* Accept any speed */
+ return 0;
+}
+
+static int soft_spi_set_mode(struct udevice *dev, unsigned int mode)
+{
+ struct soft_spi_priv *priv = dev_get_priv(dev);
+
+ priv->mode = mode;
+
+ return 0;
+}
+
+static const struct dm_spi_ops soft_spi_ops = {
+ .claim_bus = soft_spi_claim_bus,
+ .release_bus = soft_spi_release_bus,
+ .xfer = soft_spi_xfer,
+ .set_speed = soft_spi_set_speed,
+ .set_mode = soft_spi_set_mode,
+};
+
+static int soft_spi_ofdata_to_platdata(struct udevice *dev)
+{
+ struct soft_spi_platdata *plat = dev->platdata;
+ const void *blob = gd->fdt_blob;
+ int node = dev->of_offset;
+
+ plat->spi_delay_us = fdtdec_get_int(blob, node, "spi-delay-us", 0);
+
+ return 0;
+}
+
+static int soft_spi_probe(struct udevice *dev)
+{
+ struct spi_slave *slave = dev_get_parent_priv(dev);
+ struct soft_spi_platdata *plat = dev->platdata;
+ int cs_flags, clk_flags;
+ int ret;
+
+ cs_flags = (slave->mode & SPI_CS_HIGH) ? 0 : GPIOD_ACTIVE_LOW;
+ clk_flags = (slave->mode & SPI_CPOL) ? GPIOD_ACTIVE_LOW : 0;
+
+ if (gpio_request_by_name(dev, "cs-gpios", 0, &plat->cs,
+ GPIOD_IS_OUT | cs_flags) ||
+ gpio_request_by_name(dev, "gpio-sck", 0, &plat->sclk,
+ GPIOD_IS_OUT | clk_flags))
+ return -EINVAL;
+
+ ret = gpio_request_by_name(dev, "gpio-mosi", 0, &plat->mosi,
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+ if (ret)
+ plat->flags |= SPI_MASTER_NO_TX;