Commit 0f021255 authored by Mark Brown's avatar Mark Brown

spi: s3c64xx: add support for google,gs101-spi

Merge series from Tudor Ambarus <tudor.ambarus@linaro.org>:

The Google GCS101 uses a variant of the Samsung SPI controller IP.
parents 9538edeb e010c049
......@@ -17,6 +17,7 @@ properties:
compatible:
oneOf:
- enum:
- google,gs101-spi
- samsung,s3c2443-spi # for S3C2443, S3C2416 and S3C2450
- samsung,s3c6410-spi
- samsung,s5pv210-spi # for S5PV210 and S5PC110
......
......@@ -17,7 +17,7 @@
#include <linux/platform_data/spi-s3c64xx.h>
#define MAX_SPI_PORTS 12
#define MAX_SPI_PORTS 16
#define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1)
#define AUTOSUSPEND_TIMEOUT 2000
......@@ -142,6 +142,7 @@ struct s3c64xx_spi_dma_data {
* prescaler unit.
* @clk_ioclk: True if clock is present on this device
* @has_loopback: True if loopback mode can be supported
* @use_32bit_io: True if the SoC allows only 32-bit register accesses.
*
* The Samsung s3c64xx SPI controller are used on various Samsung SoC's but
* differ in some aspects such as the size of the fifo and spi bus clock
......@@ -158,6 +159,7 @@ struct s3c64xx_spi_port_config {
bool clk_from_cmu;
bool clk_ioclk;
bool has_loopback;
bool use_32bit_io;
};
/**
......@@ -414,6 +416,56 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host,
}
static void s3c64xx_iowrite8_32_rep(volatile void __iomem *addr,
const void *buffer, unsigned int count)
{
if (count) {
const u8 *buf = buffer;
do {
__raw_writel(*buf++, addr);
} while (--count);
}
}
static void s3c64xx_iowrite16_32_rep(volatile void __iomem *addr,
const void *buffer, unsigned int count)
{
if (count) {
const u16 *buf = buffer;
do {
__raw_writel(*buf++, addr);
} while (--count);
}
}
static void s3c64xx_iowrite_rep(const struct s3c64xx_spi_driver_data *sdd,
struct spi_transfer *xfer)
{
void __iomem *addr = sdd->regs + S3C64XX_SPI_TX_DATA;
const void *buf = xfer->tx_buf;
unsigned int len = xfer->len;
switch (sdd->cur_bpw) {
case 32:
iowrite32_rep(addr, buf, len / 4);
break;
case 16:
if (sdd->port_conf->use_32bit_io)
s3c64xx_iowrite16_32_rep(addr, buf, len / 2);
else
iowrite16_rep(addr, buf, len / 2);
break;
default:
if (sdd->port_conf->use_32bit_io)
s3c64xx_iowrite8_32_rep(addr, buf, len);
else
iowrite8_rep(addr, buf, len);
break;
}
}
static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd,
struct spi_transfer *xfer, int dma_mode)
{
......@@ -447,20 +499,7 @@ static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd,
modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
ret = prepare_dma(&sdd->tx_dma, &xfer->tx_sg);
} else {
switch (sdd->cur_bpw) {
case 32:
iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
xfer->tx_buf, xfer->len / 4);
break;
case 16:
iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
xfer->tx_buf, xfer->len / 2);
break;
default:
iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
xfer->tx_buf, xfer->len);
break;
}
s3c64xx_iowrite_rep(sdd, xfer);
}
}
......@@ -1495,6 +1534,19 @@ static const struct s3c64xx_spi_port_config fsd_spi_port_config = {
.quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
};
static const struct s3c64xx_spi_port_config gs101_spi_port_config = {
.fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f},
.rx_lvl_offset = 15,
.tx_st_done = 25,
.clk_div = 4,
.high_speed = true,
.clk_from_cmu = true,
.has_loopback = true,
.use_32bit_io = true,
.quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
};
static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
{
.name = "s3c2443-spi",
......@@ -1507,6 +1559,9 @@ static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
};
static const struct of_device_id s3c64xx_spi_dt_match[] = {
{ .compatible = "google,gs101-spi",
.data = &gs101_spi_port_config,
},
{ .compatible = "samsung,s3c2443-spi",
.data = (void *)&s3c2443_spi_port_config,
},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment