Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f56be67b authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'spi/topic/mxs', 'spi/topic/pxa',...

Merge remote-tracking branches 'spi/topic/mxs', 'spi/topic/pxa', 'spi/topic/rockchip', 'spi/topic/samsung' and 'spi/topic/sirf' into spi-next
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ Required SoC Specific Properties:
    - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
    - samsung,s3c6410-spi: for s3c6410 platforms
    - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
    - samsung,exynos4210-spi: for exynos4 and exynos5 platforms
    - samsung,exynos7-spi: for exynos7 platforms

- reg: physical base address of the controller and length of memory mapped
  region.
+1 −1
Original line number Diff line number Diff line
@@ -459,7 +459,7 @@ config SPI_S3C24XX_FIQ

config SPI_S3C64XX
	tristate "Samsung S3C64XX series type SPI"
	depends on PLAT_SAMSUNG
	depends on (PLAT_SAMSUNG || ARCH_EXYNOS)
	select S3C64XX_PL080 if ARCH_S3C64XX
	help
	  SPI driver for Samsung S3C64XX and newer SoCs.
+6 −6
Original line number Diff line number Diff line
@@ -182,7 +182,6 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi,
	int min, ret;
	u32 ctrl0;
	struct page *vm_page;
	void *sg_buf;
	struct {
		u32			pio[4];
		struct scatterlist	sg;
@@ -232,13 +231,14 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi,
				ret = -ENOMEM;
				goto err_vmalloc;
			}
			sg_buf = page_address(vm_page) +
				((size_t)buf & ~PAGE_MASK);

			sg_init_table(&dma_xfer[sg_count].sg, 1);
			sg_set_page(&dma_xfer[sg_count].sg, vm_page,
				    min, offset_in_page(buf));
		} else {
			sg_buf = buf;
			sg_init_one(&dma_xfer[sg_count].sg, buf, min);
		}

		sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min);
		ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
			(flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);

@@ -511,7 +511,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
	init_completion(&spi->c);

	ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0,
			       DRIVER_NAME, ssp);
			       dev_name(&pdev->dev), ssp);
	if (ret)
		goto out_master_free;

+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ enum {
	PORT_BSW0,
	PORT_BSW1,
	PORT_BSW2,
	PORT_QUARK_X1000,
};

struct pxa_spi_info {
@@ -92,6 +93,12 @@ static struct pxa_spi_info spi_info_configs[] = {
		.tx_param = &bsw2_tx_param,
		.rx_param = &bsw2_rx_param,
	},
	[PORT_QUARK_X1000] = {
		.type = QUARK_X1000_SSP,
		.port_id = -1,
		.num_chipselect = 1,
		.max_clk_rate = 50000000,
	},
};

static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
@@ -191,6 +198,7 @@ static void pxa2xx_spi_pci_remove(struct pci_dev *dev)

static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
	{ PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 },
	{ PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 },
	{ PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT },
	{ PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 },
	{ PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 },
+264 −40
Original line number Diff line number Diff line
@@ -63,10 +63,64 @@ MODULE_ALIAS("platform:pxa2xx-spi");
				| SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
				| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)

#define QUARK_X1000_SSCR1_CHANGE_MASK (QUARK_X1000_SSCR1_STRF	\
				| QUARK_X1000_SSCR1_EFWR	\
				| QUARK_X1000_SSCR1_RFT		\
				| QUARK_X1000_SSCR1_TFT		\
				| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)

#define LPSS_RX_THRESH_DFLT	64
#define LPSS_TX_LOTHRESH_DFLT	160
#define LPSS_TX_HITHRESH_DFLT	224

struct quark_spi_rate {
	u32 bitrate;
	u32 dds_clk_rate;
	u32 clk_div;
};

/*
 * 'rate', 'dds', 'clk_div' lookup table, which is defined in
 * the Quark SPI datasheet.
 */
static const struct quark_spi_rate quark_spi_rate_table[] = {
/*	bitrate,	dds_clk_rate,	clk_div */
	{50000000,	0x800000,	0},
	{40000000,	0x666666,	0},
	{25000000,	0x400000,	0},
	{20000000,	0x666666,	1},
	{16667000,	0x800000,	2},
	{13333000,	0x666666,	2},
	{12500000,	0x200000,	0},
	{10000000,	0x800000,	4},
	{8000000,	0x666666,	4},
	{6250000,	0x400000,	3},
	{5000000,	0x400000,	4},
	{4000000,	0x666666,	9},
	{3125000,	0x80000,	0},
	{2500000,	0x400000,	9},
	{2000000,	0x666666,	19},
	{1563000,	0x40000,	0},
	{1250000,	0x200000,	9},
	{1000000,	0x400000,	24},
	{800000,	0x666666,	49},
	{781250,	0x20000,	0},
	{625000,	0x200000,	19},
	{500000,	0x400000,	49},
	{400000,	0x666666,	99},
	{390625,	0x10000,	0},
	{250000,	0x400000,	99},
	{200000,	0x666666,	199},
	{195313,	0x8000,		0},
	{125000,	0x100000,	49},
	{100000,	0x200000,	124},
	{50000,		0x100000,	124},
	{25000,		0x80000,	124},
	{10016,		0x20000,	77},
	{5040,		0x20000,	154},
	{1002,		0x8000,		194},
};

/* Offset from drv_data->lpss_base */
#define GENERAL_REG		0x08
#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
@@ -80,6 +134,96 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
	return drv_data->ssp_type == LPSS_SSP;
}

static bool is_quark_x1000_ssp(const struct driver_data *drv_data)
{
	return drv_data->ssp_type == QUARK_X1000_SSP;
}

static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data)
{
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		return QUARK_X1000_SSCR1_CHANGE_MASK;
	default:
		return SSCR1_CHANGE_MASK;
	}
}

static u32
pxa2xx_spi_get_rx_default_thre(const struct driver_data *drv_data)
{
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		return RX_THRESH_QUARK_X1000_DFLT;
	default:
		return RX_THRESH_DFLT;
	}
}

static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data)
{
	void __iomem *reg = drv_data->ioaddr;
	u32 mask;

	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		mask = QUARK_X1000_SSSR_TFL_MASK;
		break;
	default:
		mask = SSSR_TFL_MASK;
		break;
	}

	return (read_SSSR(reg) & mask) == mask;
}

static void pxa2xx_spi_clear_rx_thre(const struct driver_data *drv_data,
				     u32 *sccr1_reg)
{
	u32 mask;

	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		mask = QUARK_X1000_SSCR1_RFT;
		break;
	default:
		mask = SSCR1_RFT;
		break;
	}
	*sccr1_reg &= ~mask;
}

static void pxa2xx_spi_set_rx_thre(const struct driver_data *drv_data,
				   u32 *sccr1_reg, u32 threshold)
{
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		*sccr1_reg |= QUARK_X1000_SSCR1_RxTresh(threshold);
		break;
	default:
		*sccr1_reg |= SSCR1_RxTresh(threshold);
		break;
	}
}

static u32 pxa2xx_configure_sscr0(const struct driver_data *drv_data,
				  u32 clk_div, u8 bits)
{
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		return clk_div
			| QUARK_X1000_SSCR0_Motorola
			| QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits)
			| SSCR0_SSE;
	default:
		return clk_div
			| SSCR0_Motorola
			| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
			| SSCR0_SSE
			| (bits > 16 ? SSCR0_EDSS : 0);
	}
}

/*
 * Read and write LPSS SSP private registers. Caller must first check that
 * is_lpss_ssp() returns true before these can be called.
@@ -234,7 +378,7 @@ static int null_writer(struct driver_data *drv_data)
	void __iomem *reg = drv_data->ioaddr;
	u8 n_bytes = drv_data->n_bytes;

	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
	if (pxa2xx_spi_txfifo_full(drv_data)
		|| (drv_data->tx == drv_data->tx_end))
		return 0;

@@ -262,7 +406,7 @@ static int u8_writer(struct driver_data *drv_data)
{
	void __iomem *reg = drv_data->ioaddr;

	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
	if (pxa2xx_spi_txfifo_full(drv_data)
		|| (drv_data->tx == drv_data->tx_end))
		return 0;

@@ -289,7 +433,7 @@ static int u16_writer(struct driver_data *drv_data)
{
	void __iomem *reg = drv_data->ioaddr;

	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
	if (pxa2xx_spi_txfifo_full(drv_data)
		|| (drv_data->tx == drv_data->tx_end))
		return 0;

@@ -316,7 +460,7 @@ static int u32_writer(struct driver_data *drv_data)
{
	void __iomem *reg = drv_data->ioaddr;

	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
	if (pxa2xx_spi_txfifo_full(drv_data)
		|| (drv_data->tx == drv_data->tx_end))
		return 0;

@@ -508,8 +652,9 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
		 * remaining RX bytes.
		 */
		if (pxa25x_ssp_comp(drv_data)) {
			u32 rx_thre;

			sccr1_reg &= ~SSCR1_RFT;
			pxa2xx_spi_clear_rx_thre(drv_data, &sccr1_reg);

			bytes_left = drv_data->rx_end - drv_data->rx;
			switch (drv_data->n_bytes) {
@@ -519,10 +664,11 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
				bytes_left >>= 1;
			}

			if (bytes_left > RX_THRESH_DFLT)
				bytes_left = RX_THRESH_DFLT;
			rx_thre = pxa2xx_spi_get_rx_default_thre(drv_data);
			if (rx_thre > bytes_left)
				rx_thre = bytes_left;

			sccr1_reg |= SSCR1_RxTresh(bytes_left);
			pxa2xx_spi_set_rx_thre(drv_data, &sccr1_reg, rx_thre);
		}
		write_SSCR1(sccr1_reg, reg);
	}
@@ -585,6 +731,28 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
	return drv_data->transfer_handler(drv_data);
}

/*
 * The Quark SPI data sheet gives a table, and for the given 'rate',
 * the 'dds' and 'clk_div' can be found in the table.
 */
static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(quark_spi_rate_table); i++) {
		if (rate >= quark_spi_rate_table[i].bitrate) {
			*dds = quark_spi_rate_table[i].dds_clk_rate;
			*clk_div = quark_spi_rate_table[i].clk_div;
			return quark_spi_rate_table[i].bitrate;
		}
	}

	*dds = quark_spi_rate_table[i-1].dds_clk_rate;
	*clk_div = quark_spi_rate_table[i-1].clk_div;

	return quark_spi_rate_table[i-1].bitrate;
}

static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
{
	unsigned long ssp_clk = drv_data->max_clk_rate;
@@ -598,6 +766,20 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
		return ((ssp_clk / rate - 1) & 0xfff) << 8;
}

static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
					   struct chip_data *chip, int rate)
{
	u32 clk_div;

	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		quark_x1000_set_clk_regvals(rate, &chip->dds_rate, &clk_div);
		return clk_div << 8;
	default:
		return ssp_get_clk_div(drv_data, rate);
	}
}

static void pump_transfers(unsigned long data)
{
	struct driver_data *drv_data = (struct driver_data *)data;
@@ -613,6 +795,7 @@ static void pump_transfers(unsigned long data)
	u32 cr1;
	u32 dma_thresh = drv_data->cur_chip->dma_threshold;
	u32 dma_burst = drv_data->cur_chip->dma_burst_size;
	u32 change_mask = pxa2xx_spi_get_ssrc1_change_mask(drv_data);

	/* Get current state information */
	message = drv_data->cur_msg;
@@ -699,7 +882,7 @@ static void pump_transfers(unsigned long data)
		if (transfer->bits_per_word)
			bits = transfer->bits_per_word;

		clk_div = ssp_get_clk_div(drv_data, speed);
		clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, speed);

		if (bits <= 8) {
			drv_data->n_bytes = 1;
@@ -731,11 +914,7 @@ static void pump_transfers(unsigned long data)
						     "pump_transfers: DMA burst size reduced to match bits_per_word\n");
		}

		cr0 = clk_div
			| SSCR0_Motorola
			| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
			| SSCR0_SSE
			| (bits > 16 ? SSCR0_EDSS : 0);
		cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
	}

	message->state = RUNNING_STATE;
@@ -771,17 +950,20 @@ static void pump_transfers(unsigned long data)
			write_SSITF(chip->lpss_tx_threshold, reg);
	}

	if (is_quark_x1000_ssp(drv_data) &&
	    (read_DDS_RATE(reg) != chip->dds_rate))
		write_DDS_RATE(chip->dds_rate, reg);

	/* see if we need to reload the config registers */
	if ((read_SSCR0(reg) != cr0)
		|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
			(cr1 & SSCR1_CHANGE_MASK)) {
	if ((read_SSCR0(reg) != cr0) ||
	    (read_SSCR1(reg) & change_mask) != (cr1 & change_mask)) {

		/* stop the SSP, and update the other bits */
		write_SSCR0(cr0 & ~SSCR0_SSE, reg);
		if (!pxa25x_ssp_comp(drv_data))
			write_SSTO(chip->timeout, reg);
		/* first set CR1 without interrupt and service enables */
		write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
		write_SSCR1(cr1 & change_mask, reg);
		/* restart the SSP */
		write_SSCR0(cr0, reg);

@@ -875,14 +1057,22 @@ static int setup(struct spi_device *spi)
	unsigned int clk_div;
	uint tx_thres, tx_hi_thres, rx_thres;

	if (is_lpss_ssp(drv_data)) {
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		tx_thres = TX_THRESH_QUARK_X1000_DFLT;
		tx_hi_thres = 0;
		rx_thres = RX_THRESH_QUARK_X1000_DFLT;
		break;
	case LPSS_SSP:
		tx_thres = LPSS_TX_LOTHRESH_DFLT;
		tx_hi_thres = LPSS_TX_HITHRESH_DFLT;
		rx_thres = LPSS_RX_THRESH_DFLT;
	} else {
		break;
	default:
		tx_thres = TX_THRESH_DFLT;
		tx_hi_thres = 0;
		rx_thres = RX_THRESH_DFLT;
		break;
	}

	/* Only alloc on first setup */
@@ -935,9 +1125,6 @@ static int setup(struct spi_device *spi)
		chip->enable_dma = drv_data->master_info->enable_dma;
	}

	chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
			(SSCR1_TxTresh(tx_thres) & SSCR1_TFT);

	chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
	chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres)
				| SSITF_TxHiThresh(tx_hi_thres);
@@ -956,15 +1143,24 @@ static int setup(struct spi_device *spi)
		}
	}

	clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
	clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, spi->max_speed_hz);
	chip->speed_hz = spi->max_speed_hz;

	chip->cr0 = clk_div
			| SSCR0_Motorola
			| SSCR0_DataSize(spi->bits_per_word > 16 ?
				spi->bits_per_word - 16 : spi->bits_per_word)
			| SSCR0_SSE
			| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
	chip->cr0 = pxa2xx_configure_sscr0(drv_data, clk_div,
					   spi->bits_per_word);
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		chip->threshold = (QUARK_X1000_SSCR1_RxTresh(rx_thres)
				   & QUARK_X1000_SSCR1_RFT)
				   | (QUARK_X1000_SSCR1_TxTresh(tx_thres)
				   & QUARK_X1000_SSCR1_TFT);
		break;
	default:
		chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
			(SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
		break;
	}

	chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
	chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
@@ -993,6 +1189,7 @@ static int setup(struct spi_device *spi)
		chip->read = u16_reader;
		chip->write = u16_writer;
	} else if (spi->bits_per_word <= 32) {
		if (!is_quark_x1000_ssp(drv_data))
			chip->cr0 |= SSCR0_EDSS;
		chip->n_bytes = 4;
		chip->read = u32_reader;
@@ -1144,7 +1341,15 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
	drv_data->ioaddr = ssp->mmio_base;
	drv_data->ssdr_physical = ssp->phys_base + SSDR;
	if (pxa25x_ssp_comp(drv_data)) {
		switch (drv_data->ssp_type) {
		case QUARK_X1000_SSP:
			master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
			break;
		default:
			master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
			break;
		}

		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
		drv_data->dma_cr1 = 0;
		drv_data->clear_sr = SSSR_ROR;
@@ -1182,6 +1387,20 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)

	/* Load default SSP configuration */
	write_SSCR0(0, drv_data->ioaddr);
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		write_SSCR1(QUARK_X1000_SSCR1_RxTresh(
					RX_THRESH_QUARK_X1000_DFLT) |
			    QUARK_X1000_SSCR1_TxTresh(
					TX_THRESH_QUARK_X1000_DFLT),
			    drv_data->ioaddr);

		/* using the Motorola SPI protocol and use 8 bit frame */
		write_SSCR0(QUARK_X1000_SSCR0_Motorola
			    | QUARK_X1000_SSCR0_DataSize(8),
			    drv_data->ioaddr);
		break;
	default:
		write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
			    SSCR1_TxTresh(TX_THRESH_DFLT),
			    drv_data->ioaddr);
@@ -1189,8 +1408,13 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
			    | SSCR0_Motorola
			    | SSCR0_DataSize(8),
			    drv_data->ioaddr);
		break;
	}

	if (!pxa25x_ssp_comp(drv_data))
		write_SSTO(0, drv_data->ioaddr);

	if (!is_quark_x1000_ssp(drv_data))
		write_SSPSP(0, drv_data->ioaddr);

	lpss_ssp_setup(drv_data);
Loading