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

Commit 244a60c2 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'spi/topic/armada', 'spi/topic/ath79',...

Merge remote-tracking branches 'spi/topic/armada', 'spi/topic/ath79', 'spi/topic/bcm-qspi' and 'spi/topic/bcm53xx' into spi-next
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -162,7 +162,8 @@ config SPI_BCM63XX_HSSPI

config SPI_BCM_QSPI
	tristate "Broadcom BSPI and MSPI controller support"
	depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || COMPILE_TEST
	depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || \
			BMIPS_GENERIC || COMPILE_TEST
	default ARCH_BCM_IPROC
	help
	  Enables support for the Broadcom SPI flash and MSPI controller.
+6 −8
Original line number Diff line number Diff line
@@ -170,12 +170,12 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
	val &= ~(A3700_SPI_DATA_PIN0 | A3700_SPI_DATA_PIN1);

	switch (pin_mode) {
	case 1:
	case SPI_NBITS_SINGLE:
		break;
	case 2:
	case SPI_NBITS_DUAL:
		val |= A3700_SPI_DATA_PIN0;
		break;
	case 4:
	case SPI_NBITS_QUAD:
		val |= A3700_SPI_DATA_PIN1;
		break;
	default:
@@ -340,7 +340,6 @@ static irqreturn_t a3700_spi_interrupt(int irq, void *dev_id)
	spireg_write(a3700_spi, A3700_SPI_INT_STAT_REG, cause);

	/* Wake up the transfer */
	if (a3700_spi->wait_mask & cause)
	complete(&a3700_spi->done);

	return IRQ_HANDLED;
@@ -562,6 +561,7 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi)
		val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG);
		if (a3700_spi->buf_len >= 4) {
			u32 data = le32_to_cpu(val);

			memcpy(a3700_spi->rx_buf, &data, 4);

			a3700_spi->buf_len -= 4;
@@ -901,7 +901,6 @@ static int a3700_spi_remove(struct platform_device *pdev)
	struct a3700_spi *spi = spi_master_get_devdata(master);

	clk_unprepare(spi->clk);
	spi_master_put(master);

	return 0;
}
@@ -909,7 +908,6 @@ static int a3700_spi_remove(struct platform_device *pdev)
static struct platform_driver a3700_spi_driver = {
	.driver = {
		.name	= DRIVER_NAME,
		.owner	= THIS_MODULE,
		.of_match_table = of_match_ptr(a3700_spi_dt_ids),
	},
	.probe		= a3700_spi_probe,
+12 −11
Original line number Diff line number Diff line
@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
	}

	if (spi->chip_select) {
	if (gpio_is_valid(spi->cs_gpio)) {
		/* SPI is normally active-low */
		gpio_set_value(spi->cs_gpio, cs_high);
		gpio_set_value_cansleep(spi->cs_gpio, cs_high);
	} else {
		u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);

		if (cs_high)
			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
			sp->ioc_base |= cs_bit;
		else
			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
			sp->ioc_base &= ~cs_bit;

		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
	}
@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
	int status;

	if (spi->chip_select && !gpio_is_valid(spi->cs_gpio))
		return -EINVAL;

	status = 0;
	if (spi->chip_select) {
	if (gpio_is_valid(spi->cs_gpio)) {
		unsigned long flags;

		flags = GPIOF_DIR_OUT;
@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
		status = gpio_request_one(spi->cs_gpio, flags,
					  dev_name(&spi->dev));
	} else {
		u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);

		if (spi->mode & SPI_CS_HIGH)
			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
			sp->ioc_base &= ~cs_bit;
		else
			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
			sp->ioc_base |= cs_bit;

		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
	}
@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi_device *spi)

static void ath79_spi_cleanup_cs(struct spi_device *spi)
{
	if (spi->chip_select) {
	if (gpio_is_valid(spi->cs_gpio)) {
		gpio_free(spi->cs_gpio);
	}
}
+128 −66
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@
#define BSPI_BPP_MODE_SELECT_MASK		BIT(8)
#define BSPI_BPP_ADDR_SELECT_MASK		BIT(16)

#define BSPI_READ_LENGTH			256
#define BSPI_READ_LENGTH			512

/* MSPI register offsets */
#define MSPI_SPCR0_LSB				0x000
@@ -192,9 +192,11 @@ struct bcm_qspi_dev_id {
	void *dev;
};


struct qspi_trans {
	struct spi_transfer *trans;
	int byte;
	bool mspi_last_trans;
};

struct bcm_qspi {
@@ -616,6 +618,16 @@ static int bcm_qspi_setup(struct spi_device *spi)
	return 0;
}

static bool bcm_qspi_mspi_transfer_is_last(struct bcm_qspi *qspi,
					   struct qspi_trans *qt)
{
	if (qt->mspi_last_trans &&
	    spi_transfer_is_last(qspi->master, qt->trans))
		return true;
	else
		return false;
}

static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
					struct qspi_trans *qt, int flags)
{
@@ -629,7 +641,6 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,

	if (qt->byte >= qt->trans->len) {
		/* we're at the end of the spi_transfer */

		/* in TX mode, need to pause for a delay or CS change */
		if (qt->trans->delay_usecs &&
		    (flags & TRANS_STATUS_BREAK_DELAY))
@@ -641,7 +652,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
			goto done;

		dev_dbg(&qspi->pdev->dev, "advance msg exit\n");
		if (spi_transfer_is_last(qspi->master, qt->trans))
		if (bcm_qspi_mspi_transfer_is_last(qspi, qt))
			ret = TRANS_STATUS_BREAK_EOM;
		else
			ret = TRANS_STATUS_BREAK_NO_BYTES;
@@ -813,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
				    struct spi_flash_read_message *msg)
{
	struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
	u32 addr = 0, len, len_words;
	u32 addr = 0, len, rdlen, len_words;
	int ret = 0;
	unsigned long timeo = msecs_to_jiffies(100);
	struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
@@ -826,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
	bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0);

	/*
	 * when using flex mode mode we need to send
	 * when using flex mode we need to send
	 * the upper address byte to bspi
	 */
	if (bcm_qspi_bspi_ver_three(qspi) == false) {
@@ -840,27 +851,33 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
	else
		addr = msg->from & 0x00ffffff;

	/* set BSPI RAF buffer max read length */
	len = msg->len;
	if (len > BSPI_READ_LENGTH)
		len = BSPI_READ_LENGTH;

	if (bcm_qspi_bspi_ver_three(qspi) == true)
		addr = (addr + 0xc00000) & 0xffffff;

	/*
	 * read into the entire buffer by breaking the reads
	 * into RAF buffer read lengths
	 */
	len = msg->len;
	qspi->bspi_rf_msg_idx = 0;

	do {
		if (len > BSPI_READ_LENGTH)
			rdlen = BSPI_READ_LENGTH;
		else
			rdlen = len;

		reinit_completion(&qspi->bspi_done);
		bcm_qspi_enable_bspi(qspi);
	len_words = (len + 3) >> 2;
		len_words = (rdlen + 3) >> 2;
		qspi->bspi_rf_msg = msg;
		qspi->bspi_rf_msg_status = 0;
	qspi->bspi_rf_msg_idx = 0;
	qspi->bspi_rf_msg_len = len;
	dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len);

		qspi->bspi_rf_msg_len = rdlen;
		dev_dbg(&qspi->pdev->dev,
			"bspi xfr addr 0x%x len 0x%x", addr, rdlen);
		bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr);
		bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
		bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);

		if (qspi->soc_intc) {
			/*
			 * clear soc MSPI and BSPI interrupts and enable
@@ -872,16 +889,89 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,

		/* Must flush previous writes before starting BSPI operation */
		mb();

		bcm_qspi_bspi_lr_start(qspi);
		if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) {
			dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n");
			ret = -ETIMEDOUT;
	} else {
		/* set the return length for the caller */
		msg->retlen = len;
			break;
		}

		/* set msg return length */
		msg->retlen += rdlen;
		addr += rdlen;
		len -= rdlen;
	} while (len);

	return ret;
}

static int bcm_qspi_transfer_one(struct spi_master *master,
				 struct spi_device *spi,
				 struct spi_transfer *trans)
{
	struct bcm_qspi *qspi = spi_master_get_devdata(master);
	int slots;
	unsigned long timeo = msecs_to_jiffies(100);

	bcm_qspi_chip_select(qspi, spi->chip_select);
	qspi->trans_pos.trans = trans;
	qspi->trans_pos.byte = 0;

	while (qspi->trans_pos.byte < trans->len) {
		reinit_completion(&qspi->mspi_done);

		slots = write_to_hw(qspi, spi);
		if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
			dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
			return -ETIMEDOUT;
		}

		read_from_hw(qspi, slots);
	}

	return 0;
}

static int bcm_qspi_mspi_flash_read(struct spi_device *spi,
				    struct spi_flash_read_message *msg)
{
	struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
	struct spi_transfer t[2];
	u8 cmd[6];
	int ret;

	memset(cmd, 0, sizeof(cmd));
	memset(t, 0, sizeof(t));

	/* tx */
	/* opcode is in cmd[0] */
	cmd[0] = msg->read_opcode;
	cmd[1] = msg->from >> (msg->addr_width * 8 -  8);
	cmd[2] = msg->from >> (msg->addr_width * 8 - 16);
	cmd[3] = msg->from >> (msg->addr_width * 8 - 24);
	cmd[4] = msg->from >> (msg->addr_width * 8 - 32);
	t[0].tx_buf = cmd;
	t[0].len = msg->addr_width + msg->dummy_bytes + 1;
	t[0].bits_per_word = spi->bits_per_word;
	t[0].tx_nbits = msg->opcode_nbits;
	/* lets mspi know that this is not last transfer */
	qspi->trans_pos.mspi_last_trans = false;
	ret = bcm_qspi_transfer_one(spi->master, spi, &t[0]);

	/* rx */
	qspi->trans_pos.mspi_last_trans = true;
	if (!ret) {
		/* rx */
		t[1].rx_buf = msg->buf;
		t[1].len = msg->len;
		t[1].rx_nbits =  msg->data_nbits;
		t[1].bits_per_word = spi->bits_per_word;
		ret = bcm_qspi_transfer_one(spi->master, spi, &t[1]);
	}

	if (!ret)
		msg->retlen = msg->len;

	return ret;
}

@@ -918,8 +1008,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
		mspi_read = true;

	if (mspi_read)
		/* this will make the m25p80 read to fallback to mspi read */
		return -EAGAIN;
		return bcm_qspi_mspi_flash_read(spi, msg);

	io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
	addrlen = msg->addr_width;
@@ -931,33 +1020,6 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
	return ret;
}

static int bcm_qspi_transfer_one(struct spi_master *master,
				 struct spi_device *spi,
				 struct spi_transfer *trans)
{
	struct bcm_qspi *qspi = spi_master_get_devdata(master);
	int slots;
	unsigned long timeo = msecs_to_jiffies(100);

	bcm_qspi_chip_select(qspi, spi->chip_select);
	qspi->trans_pos.trans = trans;
	qspi->trans_pos.byte = 0;

	while (qspi->trans_pos.byte < trans->len) {
		reinit_completion(&qspi->mspi_done);

		slots = write_to_hw(qspi, spi);
		if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
			dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
			return -ETIMEDOUT;
		}

		read_from_hw(qspi, slots);
	}

	return 0;
}

static void bcm_qspi_cleanup(struct spi_device *spi)
{
	struct bcm_qspi_parms *xp = spi_get_ctldata(spi);
@@ -1187,6 +1249,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
	qspi->pdev = pdev;
	qspi->trans_pos.trans = NULL;
	qspi->trans_pos.byte = 0;
	qspi->trans_pos.mspi_last_trans = true;
	qspi->master = master;

	master->bus_num = -1;
@@ -1345,7 +1408,6 @@ int bcm_qspi_remove(struct platform_device *pdev)
{
	struct bcm_qspi *qspi = platform_get_drvdata(pdev);

	platform_set_drvdata(pdev, NULL);
	bcm_qspi_hw_uninit(qspi);
	clk_disable_unprepare(qspi->clk);
	kfree(qspi->dev_ids);
+10 −8
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014-2016 Rafał Miłecki <rafal@milecki.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
@@ -275,10 +283,6 @@ static int bcm53xxspi_flash_read(struct spi_device *spi,
 * BCMA
 **************************************************/

static struct spi_board_info bcm53xx_info = {
	.modalias	= "bcm53xxspiflash",
};

static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = {
	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS),
	{},
@@ -311,6 +315,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
	b53spi->bspi = true;
	bcm53xxspi_disable_bspi(b53spi);

	master->dev.of_node = dev->of_node;
	master->transfer_one = bcm53xxspi_transfer_one;
	if (b53spi->mmio_base)
		master->spi_flash_read = bcm53xxspi_flash_read;
@@ -324,9 +329,6 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
		return err;
	}

	/* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
	spi_new_device(master, &bcm53xx_info);

	return 0;
}

@@ -361,4 +363,4 @@ module_exit(bcm53xxspi_module_exit);

MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver");
MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");