Unverified Commit 0f021255 authored by Mark Brown's avatar Mark Brown
Browse files

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+70 −15
Original line number Diff line number Diff line
@@ -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,
	},