summaryrefslogtreecommitdiff
path: root/drivers/spi/pl022_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/pl022_spi.c')
-rw-r--r--drivers/spi/pl022_spi.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
index 828eab3d342..fc7388b379d 100644
--- a/drivers/spi/pl022_spi.c
+++ b/drivers/spi/pl022_spi.c
@@ -12,9 +12,11 @@
#include <clk.h>
#include <common.h>
#include <dm.h>
-#include <dm/platform_data/spi_pl022.h>
+#include <dm/device_compat.h>
+#include <fdtdec.h>
#include <linux/io.h>
#include <asm/global_data.h>
+#include <asm/gpio.h>
#include <spi.h>
#define SSP_CR0 0x000
@@ -66,6 +68,15 @@
#define SSP_SR_MASK_RFF (0x1 << 3) /* Receive FIFO full */
#define SSP_SR_MASK_BSY (0x1 << 4) /* Busy Flag */
+struct pl022_spi_pdata {
+ fdt_addr_t addr;
+ fdt_size_t size;
+ unsigned int freq;
+#if CONFIG_IS_ENABLED(DM_GPIO)
+ struct gpio_desc cs_gpio;
+#endif
+};
+
struct pl022_spi_slave {
void *base;
unsigned int freq;
@@ -107,7 +118,7 @@ static int pl022_spi_probe(struct udevice *bus)
return 0;
}
-static void flush(struct pl022_spi_slave *ps)
+static void pl022_spi_flush(struct pl022_spi_slave *ps)
{
do {
while (readw(ps->base + SSP_SR) & SSP_SR_MASK_RNE)
@@ -126,7 +137,7 @@ static int pl022_spi_claim_bus(struct udevice *dev)
reg |= SSP_CR1_MASK_SSE;
writew(reg, ps->base + SSP_CR1);
- flush(ps);
+ pl022_spi_flush(ps);
return 0;
}
@@ -137,7 +148,7 @@ static int pl022_spi_release_bus(struct udevice *dev)
struct pl022_spi_slave *ps = dev_get_priv(bus);
u16 reg;
- flush(ps);
+ pl022_spi_flush(ps);
/* Disable the SPI hardware */
reg = readw(ps->base + SSP_CR1);
@@ -147,6 +158,17 @@ static int pl022_spi_release_bus(struct udevice *dev)
return 0;
}
+static void pl022_spi_set_cs(struct udevice *dev, bool on)
+{
+#if CONFIG_IS_ENABLED(DM_GPIO)
+ struct udevice *bus = dev->parent;
+ struct pl022_spi_pdata *plat = dev_get_plat(bus);
+
+ if (dm_gpio_is_valid(&plat->cs_gpio))
+ dm_gpio_set_value(&plat->cs_gpio, on ? 1 : 0);
+#endif
+}
+
static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
@@ -159,7 +181,7 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,
if (bitlen == 0)
/* Finish any previously submitted transfers */
- return 0;
+ goto done;
/*
* TODO: The controller can do non-multiple-of-8 bit
@@ -172,9 +194,13 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,
if (bitlen % 8) {
/* Errors always terminate an ongoing transfer */
flags |= SPI_XFER_END;
- return -1;
+ ret = -1;
+ goto done;
}
+ if (flags & SPI_XFER_BEGIN)
+ pl022_spi_set_cs(dev, true);
+
len = bitlen / 8;
while (len_tx < len) {
@@ -201,6 +227,10 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,
}
}
+done:
+ if (flags & SPI_XFER_END)
+ pl022_spi_set_cs(dev, false);
+
return ret;
}
@@ -303,11 +333,18 @@ static int pl022_spi_of_to_plat(struct udevice *bus)
plat->freq = clk_get_rate(&clkdev);
+#if CONFIG_IS_ENABLED(DM_GPIO)
+ ret = gpio_request_by_name(bus, "cs-gpios", 0, &plat->cs_gpio,
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+ if (ret < 0 && ret != -ENOENT)
+ return ret;
+#endif
+
return 0;
}
static const struct udevice_id pl022_spi_ids[] = {
- { .compatible = "arm,pl022-spi" },
+ { .compatible = "arm,pl022" },
{ }
};
#endif