mirror of
https://github.com/torvalds/linux
synced 2024-09-19 18:46:35 +00:00
Merge remote-tracking branches 'spi/topic/altera', 'spi/topic/at79', 'spi/topic/bcm-qspi', 'spi/topic/bcm63xx' and 'spi/topic/bcm63xx-hspi' into spi-next
This commit is contained in:
commit
45cfc32ba4
|
@ -55,7 +55,6 @@ comment "SPI Master Controller Drivers"
|
||||||
|
|
||||||
config SPI_ALTERA
|
config SPI_ALTERA
|
||||||
tristate "Altera SPI Controller"
|
tristate "Altera SPI Controller"
|
||||||
select SPI_BITBANG
|
|
||||||
help
|
help
|
||||||
This is the driver for the Altera SPI Controller.
|
This is the driver for the Altera SPI Controller.
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/spi/spi_bitbang.h>
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
|
||||||
|
@ -45,10 +44,6 @@
|
||||||
#define ALTERA_SPI_CONTROL_SSO_MSK 0x400
|
#define ALTERA_SPI_CONTROL_SSO_MSK 0x400
|
||||||
|
|
||||||
struct altera_spi {
|
struct altera_spi {
|
||||||
/* bitbang has to be first */
|
|
||||||
struct spi_bitbang bitbang;
|
|
||||||
struct completion done;
|
|
||||||
|
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int irq;
|
int irq;
|
||||||
int len;
|
int len;
|
||||||
|
@ -66,112 +61,42 @@ static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
|
||||||
return spi_master_get_devdata(sdev->master);
|
return spi_master_get_devdata(sdev->master);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void altera_spi_chipsel(struct spi_device *spi, int value)
|
static void altera_spi_set_cs(struct spi_device *spi, bool is_high)
|
||||||
{
|
{
|
||||||
struct altera_spi *hw = altera_spi_to_hw(spi);
|
struct altera_spi *hw = altera_spi_to_hw(spi);
|
||||||
|
|
||||||
if (spi->mode & SPI_CS_HIGH) {
|
if (is_high) {
|
||||||
switch (value) {
|
hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
|
||||||
case BITBANG_CS_INACTIVE:
|
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
||||||
writel(1 << spi->chip_select,
|
writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
|
||||||
hw->base + ALTERA_SPI_SLAVE_SEL);
|
|
||||||
hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
|
|
||||||
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BITBANG_CS_ACTIVE:
|
|
||||||
hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
|
|
||||||
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
|
||||||
writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
switch (value) {
|
writel(BIT(spi->chip_select), hw->base + ALTERA_SPI_SLAVE_SEL);
|
||||||
case BITBANG_CS_INACTIVE:
|
hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
|
||||||
hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
|
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
||||||
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BITBANG_CS_ACTIVE:
|
|
||||||
writel(1 << spi->chip_select,
|
|
||||||
hw->base + ALTERA_SPI_SLAVE_SEL);
|
|
||||||
hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
|
|
||||||
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
|
static void altera_spi_tx_word(struct altera_spi *hw)
|
||||||
{
|
{
|
||||||
|
unsigned int txd = 0;
|
||||||
|
|
||||||
if (hw->tx) {
|
if (hw->tx) {
|
||||||
switch (hw->bytes_per_word) {
|
switch (hw->bytes_per_word) {
|
||||||
case 1:
|
case 1:
|
||||||
return hw->tx[count];
|
txd = hw->tx[hw->count];
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
return (hw->tx[count * 2]
|
txd = (hw->tx[hw->count * 2]
|
||||||
| (hw->tx[count * 2 + 1] << 8));
|
| (hw->tx[hw->count * 2 + 1] << 8));
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
|
|
||||||
{
|
|
||||||
struct altera_spi *hw = altera_spi_to_hw(spi);
|
|
||||||
|
|
||||||
hw->tx = t->tx_buf;
|
|
||||||
hw->rx = t->rx_buf;
|
|
||||||
hw->count = 0;
|
|
||||||
hw->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
|
|
||||||
hw->len = t->len / hw->bytes_per_word;
|
|
||||||
|
|
||||||
if (hw->irq >= 0) {
|
|
||||||
/* enable receive interrupt */
|
|
||||||
hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
|
|
||||||
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
|
||||||
|
|
||||||
/* send the first byte */
|
|
||||||
writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
|
|
||||||
|
|
||||||
wait_for_completion(&hw->done);
|
|
||||||
/* disable receive interrupt */
|
|
||||||
hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
|
|
||||||
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
|
||||||
} else {
|
|
||||||
while (hw->count < hw->len) {
|
|
||||||
unsigned int rxd;
|
|
||||||
|
|
||||||
writel(hw_txbyte(hw, hw->count),
|
|
||||||
hw->base + ALTERA_SPI_TXDATA);
|
|
||||||
|
|
||||||
while (!(readl(hw->base + ALTERA_SPI_STATUS) &
|
|
||||||
ALTERA_SPI_STATUS_RRDY_MSK))
|
|
||||||
cpu_relax();
|
|
||||||
|
|
||||||
rxd = readl(hw->base + ALTERA_SPI_RXDATA);
|
|
||||||
if (hw->rx) {
|
|
||||||
switch (hw->bytes_per_word) {
|
|
||||||
case 1:
|
|
||||||
hw->rx[hw->count] = rxd;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
hw->rx[hw->count * 2] = rxd;
|
|
||||||
hw->rx[hw->count * 2 + 1] = rxd >> 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hw->count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hw->count * hw->bytes_per_word;
|
writel(txd, hw->base + ALTERA_SPI_TXDATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t altera_spi_irq(int irq, void *dev)
|
static void altera_spi_rx_word(struct altera_spi *hw)
|
||||||
{
|
{
|
||||||
struct altera_spi *hw = dev;
|
|
||||||
unsigned int rxd;
|
unsigned int rxd;
|
||||||
|
|
||||||
rxd = readl(hw->base + ALTERA_SPI_RXDATA);
|
rxd = readl(hw->base + ALTERA_SPI_RXDATA);
|
||||||
|
@ -188,11 +113,58 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
hw->count++;
|
hw->count++;
|
||||||
|
}
|
||||||
|
|
||||||
if (hw->count < hw->len)
|
static int altera_spi_txrx(struct spi_master *master,
|
||||||
writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
|
struct spi_device *spi, struct spi_transfer *t)
|
||||||
else
|
{
|
||||||
complete(&hw->done);
|
struct altera_spi *hw = spi_master_get_devdata(master);
|
||||||
|
|
||||||
|
hw->tx = t->tx_buf;
|
||||||
|
hw->rx = t->rx_buf;
|
||||||
|
hw->count = 0;
|
||||||
|
hw->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
|
||||||
|
hw->len = t->len / hw->bytes_per_word;
|
||||||
|
|
||||||
|
if (hw->irq >= 0) {
|
||||||
|
/* enable receive interrupt */
|
||||||
|
hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
|
||||||
|
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
||||||
|
|
||||||
|
/* send the first byte */
|
||||||
|
altera_spi_tx_word(hw);
|
||||||
|
} else {
|
||||||
|
while (hw->count < hw->len) {
|
||||||
|
altera_spi_tx_word(hw);
|
||||||
|
|
||||||
|
while (!(readl(hw->base + ALTERA_SPI_STATUS) &
|
||||||
|
ALTERA_SPI_STATUS_RRDY_MSK))
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
altera_spi_rx_word(hw);
|
||||||
|
}
|
||||||
|
spi_finalize_current_transfer(master);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t altera_spi_irq(int irq, void *dev)
|
||||||
|
{
|
||||||
|
struct spi_master *master = dev;
|
||||||
|
struct altera_spi *hw = spi_master_get_devdata(master);
|
||||||
|
|
||||||
|
altera_spi_rx_word(hw);
|
||||||
|
|
||||||
|
if (hw->count < hw->len) {
|
||||||
|
altera_spi_tx_word(hw);
|
||||||
|
} else {
|
||||||
|
/* disable receive interrupt */
|
||||||
|
hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
|
||||||
|
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
|
||||||
|
|
||||||
|
spi_finalize_current_transfer(master);
|
||||||
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -214,14 +186,10 @@ static int altera_spi_probe(struct platform_device *pdev)
|
||||||
master->mode_bits = SPI_CS_HIGH;
|
master->mode_bits = SPI_CS_HIGH;
|
||||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
|
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
|
||||||
master->dev.of_node = pdev->dev.of_node;
|
master->dev.of_node = pdev->dev.of_node;
|
||||||
|
master->transfer_one = altera_spi_txrx;
|
||||||
|
master->set_cs = altera_spi_set_cs;
|
||||||
|
|
||||||
hw = spi_master_get_devdata(master);
|
hw = spi_master_get_devdata(master);
|
||||||
platform_set_drvdata(pdev, hw);
|
|
||||||
|
|
||||||
/* setup the state for the bitbang driver */
|
|
||||||
hw->bitbang.master = master;
|
|
||||||
hw->bitbang.chipselect = altera_spi_chipsel;
|
|
||||||
hw->bitbang.txrx_bufs = altera_spi_txrx;
|
|
||||||
|
|
||||||
/* find and map our resources */
|
/* find and map our resources */
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
@ -239,15 +207,13 @@ static int altera_spi_probe(struct platform_device *pdev)
|
||||||
/* irq is optional */
|
/* irq is optional */
|
||||||
hw->irq = platform_get_irq(pdev, 0);
|
hw->irq = platform_get_irq(pdev, 0);
|
||||||
if (hw->irq >= 0) {
|
if (hw->irq >= 0) {
|
||||||
init_completion(&hw->done);
|
|
||||||
err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
|
err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
|
||||||
pdev->name, hw);
|
pdev->name, master);
|
||||||
if (err)
|
if (err)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register our spi controller */
|
err = devm_spi_register_master(&pdev->dev, master);
|
||||||
err = spi_bitbang_start(&hw->bitbang);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto exit;
|
goto exit;
|
||||||
dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
|
dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
|
||||||
|
@ -258,16 +224,6 @@ static int altera_spi_probe(struct platform_device *pdev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int altera_spi_remove(struct platform_device *dev)
|
|
||||||
{
|
|
||||||
struct altera_spi *hw = platform_get_drvdata(dev);
|
|
||||||
struct spi_master *master = hw->bitbang.master;
|
|
||||||
|
|
||||||
spi_bitbang_stop(&hw->bitbang);
|
|
||||||
spi_master_put(master);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
static const struct of_device_id altera_spi_match[] = {
|
static const struct of_device_id altera_spi_match[] = {
|
||||||
{ .compatible = "ALTR,spi-1.0", },
|
{ .compatible = "ALTR,spi-1.0", },
|
||||||
|
@ -279,7 +235,6 @@ MODULE_DEVICE_TABLE(of, altera_spi_match);
|
||||||
|
|
||||||
static struct platform_driver altera_spi_driver = {
|
static struct platform_driver altera_spi_driver = {
|
||||||
.probe = altera_spi_probe,
|
.probe = altera_spi_probe,
|
||||||
.remove = altera_spi_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.pm = NULL,
|
.pm = NULL,
|
||||||
|
|
|
@ -39,15 +39,15 @@ struct ath79_spi {
|
||||||
u32 reg_ctrl;
|
u32 reg_ctrl;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
unsigned rrw_delay;
|
unsigned int rrw_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
|
static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned int reg)
|
||||||
{
|
{
|
||||||
return ioread32(sp->base + reg);
|
return ioread32(sp->base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
|
static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned int reg, u32 val)
|
||||||
{
|
{
|
||||||
iowrite32(val, sp->base + reg);
|
iowrite32(val, sp->base + reg);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
|
||||||
return spi_master_get_devdata(spi->master);
|
return spi_master_get_devdata(spi->master);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
|
static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned int nsecs)
|
||||||
{
|
{
|
||||||
if (nsecs > sp->rrw_delay)
|
if (nsecs > sp->rrw_delay)
|
||||||
ndelay(nsecs - sp->rrw_delay);
|
ndelay(nsecs - sp->rrw_delay);
|
||||||
|
@ -148,9 +148,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
|
||||||
|
|
||||||
static void ath79_spi_cleanup_cs(struct spi_device *spi)
|
static void ath79_spi_cleanup_cs(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
if (gpio_is_valid(spi->cs_gpio)) {
|
if (gpio_is_valid(spi->cs_gpio))
|
||||||
gpio_free(spi->cs_gpio);
|
gpio_free(spi->cs_gpio);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath79_spi_setup(struct spi_device *spi)
|
static int ath79_spi_setup(struct spi_device *spi)
|
||||||
|
@ -176,7 +175,7 @@ static void ath79_spi_cleanup(struct spi_device *spi)
|
||||||
spi_bitbang_cleanup(spi);
|
spi_bitbang_cleanup(spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
|
static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
|
||||||
u32 word, u8 bits)
|
u32 word, u8 bits)
|
||||||
{
|
{
|
||||||
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
|
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mtd/spi-nor.h>
|
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -349,76 +348,60 @@ static void bcm_qspi_bspi_set_xfer_params(struct bcm_qspi *qspi, u8 cmd_byte,
|
||||||
bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, flex_mode);
|
bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, flex_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, int width,
|
static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,
|
||||||
int addrlen, int hp)
|
struct spi_flash_read_message *msg,
|
||||||
|
int hp)
|
||||||
{
|
{
|
||||||
int bpc = 0, bpp = 0;
|
int bpc = 0, bpp = 0;
|
||||||
u8 command = SPINOR_OP_READ_FAST;
|
u8 command = msg->read_opcode;
|
||||||
int flex_mode = 1, rv = 0;
|
int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
|
||||||
bool spans_4byte = false;
|
int addrlen = msg->addr_width;
|
||||||
|
int addr_nbits = msg->addr_nbits ? msg->addr_nbits : SPI_NBITS_SINGLE;
|
||||||
|
int flex_mode = 1;
|
||||||
|
|
||||||
dev_dbg(&qspi->pdev->dev, "set flex mode w %x addrlen %x hp %d\n",
|
dev_dbg(&qspi->pdev->dev, "set flex mode w %x addrlen %x hp %d\n",
|
||||||
width, addrlen, hp);
|
width, addrlen, hp);
|
||||||
|
|
||||||
if (addrlen == BSPI_ADDRLEN_4BYTES) {
|
if (addrlen == BSPI_ADDRLEN_4BYTES)
|
||||||
bpp = BSPI_BPP_ADDR_SELECT_MASK;
|
bpp = BSPI_BPP_ADDR_SELECT_MASK;
|
||||||
spans_4byte = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpp |= 8;
|
bpp |= msg->dummy_bytes * (8/addr_nbits);
|
||||||
|
|
||||||
switch (width) {
|
switch (width) {
|
||||||
case SPI_NBITS_SINGLE:
|
case SPI_NBITS_SINGLE:
|
||||||
if (addrlen == BSPI_ADDRLEN_3BYTES)
|
if (addrlen == BSPI_ADDRLEN_3BYTES)
|
||||||
/* default mode, does not need flex_cmd */
|
/* default mode, does not need flex_cmd */
|
||||||
flex_mode = 0;
|
flex_mode = 0;
|
||||||
else
|
|
||||||
command = SPINOR_OP_READ_FAST_4B;
|
|
||||||
break;
|
break;
|
||||||
case SPI_NBITS_DUAL:
|
case SPI_NBITS_DUAL:
|
||||||
bpc = 0x00000001;
|
bpc = 0x00000001;
|
||||||
if (hp) {
|
if (hp) {
|
||||||
bpc |= 0x00010100; /* address and mode are 2-bit */
|
bpc |= 0x00010100; /* address and mode are 2-bit */
|
||||||
bpp = BSPI_BPP_MODE_SELECT_MASK;
|
bpp = BSPI_BPP_MODE_SELECT_MASK;
|
||||||
command = OPCODE_DIOR;
|
|
||||||
if (spans_4byte)
|
|
||||||
command = OPCODE_DIOR_4B;
|
|
||||||
} else {
|
|
||||||
command = SPINOR_OP_READ_1_1_2;
|
|
||||||
if (spans_4byte)
|
|
||||||
command = SPINOR_OP_READ_1_1_2_4B;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPI_NBITS_QUAD:
|
case SPI_NBITS_QUAD:
|
||||||
bpc = 0x00000002;
|
bpc = 0x00000002;
|
||||||
if (hp) {
|
if (hp) {
|
||||||
bpc |= 0x00020200; /* address and mode are 4-bit */
|
bpc |= 0x00020200; /* address and mode are 4-bit */
|
||||||
bpp = 4; /* dummy cycles */
|
bpp |= BSPI_BPP_MODE_SELECT_MASK;
|
||||||
bpp |= BSPI_BPP_ADDR_SELECT_MASK;
|
|
||||||
command = OPCODE_QIOR;
|
|
||||||
if (spans_4byte)
|
|
||||||
command = OPCODE_QIOR_4B;
|
|
||||||
} else {
|
|
||||||
command = SPINOR_OP_READ_1_1_4;
|
|
||||||
if (spans_4byte)
|
|
||||||
command = SPINOR_OP_READ_1_1_4_4B;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rv = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv == 0)
|
bcm_qspi_bspi_set_xfer_params(qspi, command, bpp, bpc, flex_mode);
|
||||||
bcm_qspi_bspi_set_xfer_params(qspi, command, bpp, bpc,
|
|
||||||
flex_mode);
|
|
||||||
|
|
||||||
return rv;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
|
static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi,
|
||||||
int addrlen, int hp)
|
struct spi_flash_read_message *msg,
|
||||||
|
int hp)
|
||||||
{
|
{
|
||||||
|
int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
|
||||||
|
int addrlen = msg->addr_width;
|
||||||
u32 data = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
|
u32 data = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
|
||||||
|
|
||||||
dev_dbg(&qspi->pdev->dev, "set override mode w %x addrlen %x hp %d\n",
|
dev_dbg(&qspi->pdev->dev, "set override mode w %x addrlen %x hp %d\n",
|
||||||
|
@ -430,7 +413,6 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
|
||||||
data &= ~(BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD |
|
data &= ~(BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD |
|
||||||
BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL);
|
BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPI_NBITS_QUAD:
|
case SPI_NBITS_QUAD:
|
||||||
/* clear dual mode and set quad mode */
|
/* clear dual mode and set quad mode */
|
||||||
data &= ~BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL;
|
data &= ~BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL;
|
||||||
|
@ -455,15 +437,17 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
|
||||||
/* set the override mode */
|
/* set the override mode */
|
||||||
data |= BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
|
data |= BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
|
||||||
bcm_qspi_write(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL, data);
|
bcm_qspi_write(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL, data);
|
||||||
bcm_qspi_bspi_set_xfer_params(qspi, SPINOR_OP_READ_FAST, 0, 0, 0);
|
bcm_qspi_bspi_set_xfer_params(qspi, msg->read_opcode, 0, 0, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
|
static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
|
||||||
int width, int addrlen, int hp)
|
struct spi_flash_read_message *msg, int hp)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
|
||||||
|
int addrlen = msg->addr_width;
|
||||||
|
|
||||||
/* default mode */
|
/* default mode */
|
||||||
qspi->xfer_mode.flex_mode = true;
|
qspi->xfer_mode.flex_mode = true;
|
||||||
|
@ -475,23 +459,13 @@ static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
|
||||||
mask = BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
|
mask = BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
|
||||||
if (val & mask || qspi->s3_strap_override_ctrl & mask) {
|
if (val & mask || qspi->s3_strap_override_ctrl & mask) {
|
||||||
qspi->xfer_mode.flex_mode = false;
|
qspi->xfer_mode.flex_mode = false;
|
||||||
bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE,
|
bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, 0);
|
||||||
0);
|
error = bcm_qspi_bspi_set_override(qspi, msg, hp);
|
||||||
|
|
||||||
if ((val | qspi->s3_strap_override_ctrl) &
|
|
||||||
BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL)
|
|
||||||
width = SPI_NBITS_DUAL;
|
|
||||||
else if ((val | qspi->s3_strap_override_ctrl) &
|
|
||||||
BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD)
|
|
||||||
width = SPI_NBITS_QUAD;
|
|
||||||
|
|
||||||
error = bcm_qspi_bspi_set_override(qspi, width, addrlen,
|
|
||||||
hp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qspi->xfer_mode.flex_mode)
|
if (qspi->xfer_mode.flex_mode)
|
||||||
error = bcm_qspi_bspi_set_flex_mode(qspi, width, addrlen, hp);
|
error = bcm_qspi_bspi_set_flex_mode(qspi, msg, hp);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dev_warn(&qspi->pdev->dev,
|
dev_warn(&qspi->pdev->dev,
|
||||||
|
@ -981,7 +955,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
|
||||||
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
|
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
bool mspi_read = false;
|
bool mspi_read = false;
|
||||||
u32 io_width, addrlen, addr, len;
|
u32 addr, len;
|
||||||
u_char *buf;
|
u_char *buf;
|
||||||
|
|
||||||
buf = msg->buf;
|
buf = msg->buf;
|
||||||
|
@ -1010,9 +984,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
|
||||||
if (mspi_read)
|
if (mspi_read)
|
||||||
return bcm_qspi_mspi_flash_read(spi, msg);
|
return bcm_qspi_mspi_flash_read(spi, msg);
|
||||||
|
|
||||||
io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
|
ret = bcm_qspi_bspi_set_mode(qspi, msg, -1);
|
||||||
addrlen = msg->addr_width;
|
|
||||||
ret = bcm_qspi_bspi_set_mode(qspi, io_width, addrlen, -1);
|
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = bcm_qspi_bspi_flash_read(spi, msg);
|
ret = bcm_qspi_bspi_flash_read(spi, msg);
|
||||||
|
@ -1422,6 +1394,11 @@ static int __maybe_unused bcm_qspi_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct bcm_qspi *qspi = dev_get_drvdata(dev);
|
struct bcm_qspi *qspi = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
/* store the override strap value */
|
||||||
|
if (!bcm_qspi_bspi_ver_three(qspi))
|
||||||
|
qspi->s3_strap_override_ctrl =
|
||||||
|
bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
|
||||||
|
|
||||||
spi_master_suspend(qspi->master);
|
spi_master_suspend(qspi->master);
|
||||||
clk_disable(qspi->clk);
|
clk_disable(qspi->clk);
|
||||||
bcm_qspi_hw_uninit(qspi);
|
bcm_qspi_hw_uninit(qspi);
|
||||||
|
|
|
@ -108,7 +108,7 @@ struct bcm63xx_hsspi {
|
||||||
u8 cs_polarity;
|
u8 cs_polarity;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
|
static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned int cs,
|
||||||
bool active)
|
bool active)
|
||||||
{
|
{
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
@ -127,7 +127,7 @@ static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
|
||||||
static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
|
static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
|
||||||
struct spi_device *spi, int hz)
|
struct spi_device *spi, int hz)
|
||||||
{
|
{
|
||||||
unsigned profile = spi->chip_select;
|
unsigned int profile = spi->chip_select;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
|
reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
|
||||||
|
@ -154,7 +154,7 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
|
||||||
static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
|
static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
|
||||||
{
|
{
|
||||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
|
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
|
||||||
unsigned chip_select = spi->chip_select;
|
unsigned int chip_select = spi->chip_select;
|
||||||
u16 opcode = 0;
|
u16 opcode = 0;
|
||||||
int pending = t->len;
|
int pending = t->len;
|
||||||
int step_size = HSSPI_BUFFER_LEN;
|
int step_size = HSSPI_BUFFER_LEN;
|
||||||
|
@ -338,8 +338,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0) {
|
||||||
dev_err(dev, "no irq\n");
|
dev_err(dev, "no irq: %d\n", irq);
|
||||||
return -ENXIO;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
|
|
@ -530,8 +530,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0) {
|
||||||
dev_err(dev, "no irq\n");
|
dev_err(dev, "no irq: %d\n", irq);
|
||||||
return -ENXIO;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
clk = devm_clk_get(dev, "spi");
|
clk = devm_clk_get(dev, "spi");
|
||||||
|
|
Loading…
Reference in a new issue