mirror of https://gitee.com/openkylin/linux.git
Merge remote-tracking branches 'spi/topic/armada', 'spi/topic/ath79', 'spi/topic/bcm-qspi' and 'spi/topic/bcm53xx' into spi-next
This commit is contained in:
commit
244a60c28d
|
@ -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.
|
||||
|
|
|
@ -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,8 +340,7 @@ 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);
|
||||
complete(&a3700_spi->done);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -421,7 +420,7 @@ static void a3700_spi_fifo_thres_set(struct a3700_spi *a3700_spi,
|
|||
}
|
||||
|
||||
static void a3700_spi_transfer_setup(struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct a3700_spi *a3700_spi;
|
||||
unsigned int byte_len;
|
||||
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,48 +851,127 @@ 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;
|
||||
|
||||
reinit_completion(&qspi->bspi_done);
|
||||
bcm_qspi_enable_bspi(qspi);
|
||||
len_words = (len + 3) >> 2;
|
||||
qspi->bspi_rf_msg = msg;
|
||||
qspi->bspi_rf_msg_status = 0;
|
||||
/*
|
||||
* read into the entire buffer by breaking the reads
|
||||
* into RAF buffer read lengths
|
||||
*/
|
||||
len = msg->len;
|
||||
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);
|
||||
|
||||
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);
|
||||
do {
|
||||
if (len > BSPI_READ_LENGTH)
|
||||
rdlen = BSPI_READ_LENGTH;
|
||||
else
|
||||
rdlen = len;
|
||||
|
||||
if (qspi->soc_intc) {
|
||||
/*
|
||||
* clear soc MSPI and BSPI interrupts and enable
|
||||
* BSPI interrupts.
|
||||
*/
|
||||
soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
|
||||
soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true);
|
||||
reinit_completion(&qspi->bspi_done);
|
||||
bcm_qspi_enable_bspi(qspi);
|
||||
len_words = (rdlen + 3) >> 2;
|
||||
qspi->bspi_rf_msg = msg;
|
||||
qspi->bspi_rf_msg_status = 0;
|
||||
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
|
||||
* BSPI interrupts.
|
||||
*/
|
||||
soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
|
||||
soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
}
|
||||
|
||||
/* Must flush previous writes before starting BSPI operation */
|
||||
mb();
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* 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");
|
||||
|
|
Loading…
Reference in New Issue