diff --git a/target/linux/bcm53xx/patches-4.4/182-spi-bcm53xx-simplify-reading-SPI-data.patch b/target/linux/bcm53xx/patches-4.4/182-spi-bcm53xx-simplify-reading-SPI-data.patch new file mode 100644 index 0000000000..ee377c491f --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/182-spi-bcm53xx-simplify-reading-SPI-data.patch @@ -0,0 +1,107 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 29 Dec 2017 14:44:09 +0100 +Subject: [PATCH] spi: bcm53xx: simplify reading SPI data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit makes transfer function use spi_transfer_is_last to +determine if currently processed transfer is the last one. Thanks to +that we finally set hardware registers properly and it makes controller +behave the way it's expected to. + +This allows simplifying read function which can now simply start reading +from the slot 0 instead of the last saved offset. It has been +successfully tested using spi_write_then_read. + +Moreover this change fixes handling messages with two writing transfers. +It's important for SPI flash devices as their drivers commonly use one +transfer for a command and another one for data. + +Signed-off-by: Rafał Miłecki +--- + drivers/spi/spi-bcm53xx.c | 26 ++++++++++---------------- + 1 file changed, 10 insertions(+), 16 deletions(-) + +--- a/drivers/spi/spi-bcm53xx.c ++++ b/drivers/spi/spi-bcm53xx.c +@@ -27,8 +27,6 @@ struct bcm53xxspi { + struct bcma_device *core; + struct spi_master *master; + void __iomem *mmio_base; +- +- size_t read_offset; + bool bspi; /* Boot SPI mode with memory mapping */ + }; + +@@ -172,8 +170,6 @@ static void bcm53xxspi_buf_write(struct + + if (!cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); +- +- b53spi->read_offset = len; + } + + static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, +@@ -182,10 +178,10 @@ static void bcm53xxspi_buf_read(struct b + u32 tmp; + int i; + +- for (i = 0; i < b53spi->read_offset + len; i++) { ++ for (i = 0; i < len; i++) { + tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | + B53SPI_CDRAM_PCS_DSCK; +- if (!cont && i == b53spi->read_offset + len - 1) ++ if (!cont && i == len - 1) + tmp &= ~B53SPI_CDRAM_CONT; + tmp &= ~0x1; + /* Command Register File */ +@@ -194,8 +190,7 @@ static void bcm53xxspi_buf_read(struct b + + /* Set queue pointers */ + bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); +- bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, +- b53spi->read_offset + len - 1); ++ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); + + if (cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); +@@ -214,13 +209,11 @@ static void bcm53xxspi_buf_read(struct b + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); + + for (i = 0; i < len; ++i) { +- int offset = b53spi->read_offset + i; ++ u16 reg = B53SPI_MSPI_RXRAM + 4 * (1 + i * 2); + + /* Data stored in the transmit register file LSB */ +- r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); ++ r_buf[i] = (u8)bcm53xxspi_read(b53spi, reg); + } +- +- b53spi->read_offset = 0; + } + + static int bcm53xxspi_transfer_one(struct spi_master *master, +@@ -238,7 +231,8 @@ static int bcm53xxspi_transfer_one(struc + left = t->len; + while (left) { + size_t to_write = min_t(size_t, 16, left); +- bool cont = left - to_write > 0; ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_write > 0; + + bcm53xxspi_buf_write(b53spi, buf, to_write, cont); + left -= to_write; +@@ -250,9 +244,9 @@ static int bcm53xxspi_transfer_one(struc + buf = (u8 *)t->rx_buf; + left = t->len; + while (left) { +- size_t to_read = min_t(size_t, 16 - b53spi->read_offset, +- left); +- bool cont = left - to_read > 0; ++ size_t to_read = min_t(size_t, 16, left); ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_read > 0; + + bcm53xxspi_buf_read(b53spi, buf, to_read, cont); + left -= to_read; diff --git a/target/linux/bcm53xx/patches-4.4/406-mtd-m25p80-use-single-SPI-message-for-writing-data.patch b/target/linux/bcm53xx/patches-4.4/406-mtd-m25p80-use-single-SPI-message-for-writing-data.patch deleted file mode 100644 index d5525f6223..0000000000 --- a/target/linux/bcm53xx/patches-4.4/406-mtd-m25p80-use-single-SPI-message-for-writing-data.patch +++ /dev/null @@ -1,59 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Subject: [PATCH] mtd: m25p80: use single SPI message for writing data -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -On all 3 tested Northstar devices with following flash memories: -mx25l6405d (8192 Kbytes) -mx25l12805d (16384 Kbytes) -mx25l25635e (32768 Kbytes) -I noticed writing to be broken. Not a single bit was changed leaving all -bytes set to 0xff. - -This is most likely some problem related to the SPI controller or its -driver. Using a single SPI message seems to workaround this. Of course -it's not perfect solution as copying whole data into a new buffer makes -writing slower. - -Signed-off-by: Rafał Miłecki ---- - ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -78,6 +78,7 @@ static void m25p80_write(struct spi_nor - { - struct m25p *flash = nor->priv; - struct spi_device *spi = flash->spi; -+ u8 *command = kzalloc(MAX_CMD_SIZE + len, GFP_KERNEL); - struct spi_transfer t[2] = {}; - struct spi_message m; - int cmd_sz = m25p_cmdsz(nor); -@@ -87,20 +88,19 @@ static void m25p80_write(struct spi_nor - if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) - cmd_sz = 1; - -- flash->command[0] = nor->program_opcode; -- m25p_addr2cmd(nor, to, flash->command); -+ command[0] = nor->program_opcode; -+ m25p_addr2cmd(nor, to, command); -+ memcpy(&command[cmd_sz], buf, len); - -- t[0].tx_buf = flash->command; -- t[0].len = cmd_sz; -+ t[0].tx_buf = command; -+ t[0].len = cmd_sz + len; - spi_message_add_tail(&t[0], &m); - -- t[1].tx_buf = buf; -- t[1].len = len; -- spi_message_add_tail(&t[1], &m); -- - spi_sync(spi, &m); - - *retlen += m.actual_length - cmd_sz; -+ -+ kfree(command); - } - - static inline unsigned int m25p80_rx_nbits(struct spi_nor *nor) diff --git a/target/linux/bcm53xx/patches-4.9/182-spi-bcm53xx-simplify-reading-SPI-data.patch b/target/linux/bcm53xx/patches-4.9/182-spi-bcm53xx-simplify-reading-SPI-data.patch new file mode 100644 index 0000000000..ee377c491f --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/182-spi-bcm53xx-simplify-reading-SPI-data.patch @@ -0,0 +1,107 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 29 Dec 2017 14:44:09 +0100 +Subject: [PATCH] spi: bcm53xx: simplify reading SPI data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit makes transfer function use spi_transfer_is_last to +determine if currently processed transfer is the last one. Thanks to +that we finally set hardware registers properly and it makes controller +behave the way it's expected to. + +This allows simplifying read function which can now simply start reading +from the slot 0 instead of the last saved offset. It has been +successfully tested using spi_write_then_read. + +Moreover this change fixes handling messages with two writing transfers. +It's important for SPI flash devices as their drivers commonly use one +transfer for a command and another one for data. + +Signed-off-by: Rafał Miłecki +--- + drivers/spi/spi-bcm53xx.c | 26 ++++++++++---------------- + 1 file changed, 10 insertions(+), 16 deletions(-) + +--- a/drivers/spi/spi-bcm53xx.c ++++ b/drivers/spi/spi-bcm53xx.c +@@ -27,8 +27,6 @@ struct bcm53xxspi { + struct bcma_device *core; + struct spi_master *master; + void __iomem *mmio_base; +- +- size_t read_offset; + bool bspi; /* Boot SPI mode with memory mapping */ + }; + +@@ -172,8 +170,6 @@ static void bcm53xxspi_buf_write(struct + + if (!cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); +- +- b53spi->read_offset = len; + } + + static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, +@@ -182,10 +178,10 @@ static void bcm53xxspi_buf_read(struct b + u32 tmp; + int i; + +- for (i = 0; i < b53spi->read_offset + len; i++) { ++ for (i = 0; i < len; i++) { + tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | + B53SPI_CDRAM_PCS_DSCK; +- if (!cont && i == b53spi->read_offset + len - 1) ++ if (!cont && i == len - 1) + tmp &= ~B53SPI_CDRAM_CONT; + tmp &= ~0x1; + /* Command Register File */ +@@ -194,8 +190,7 @@ static void bcm53xxspi_buf_read(struct b + + /* Set queue pointers */ + bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); +- bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, +- b53spi->read_offset + len - 1); ++ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); + + if (cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); +@@ -214,13 +209,11 @@ static void bcm53xxspi_buf_read(struct b + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); + + for (i = 0; i < len; ++i) { +- int offset = b53spi->read_offset + i; ++ u16 reg = B53SPI_MSPI_RXRAM + 4 * (1 + i * 2); + + /* Data stored in the transmit register file LSB */ +- r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); ++ r_buf[i] = (u8)bcm53xxspi_read(b53spi, reg); + } +- +- b53spi->read_offset = 0; + } + + static int bcm53xxspi_transfer_one(struct spi_master *master, +@@ -238,7 +231,8 @@ static int bcm53xxspi_transfer_one(struc + left = t->len; + while (left) { + size_t to_write = min_t(size_t, 16, left); +- bool cont = left - to_write > 0; ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_write > 0; + + bcm53xxspi_buf_write(b53spi, buf, to_write, cont); + left -= to_write; +@@ -250,9 +244,9 @@ static int bcm53xxspi_transfer_one(struc + buf = (u8 *)t->rx_buf; + left = t->len; + while (left) { +- size_t to_read = min_t(size_t, 16 - b53spi->read_offset, +- left); +- bool cont = left - to_read > 0; ++ size_t to_read = min_t(size_t, 16, left); ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_read > 0; + + bcm53xxspi_buf_read(b53spi, buf, to_read, cont); + left -= to_read; diff --git a/target/linux/bcm53xx/patches-4.9/401-mtd-m25p80-use-single-SPI-message-for-writing-data.patch b/target/linux/bcm53xx/patches-4.9/401-mtd-m25p80-use-single-SPI-message-for-writing-data.patch deleted file mode 100644 index 80c0e7877e..0000000000 --- a/target/linux/bcm53xx/patches-4.9/401-mtd-m25p80-use-single-SPI-message-for-writing-data.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Subject: [PATCH] mtd: m25p80: use single SPI message for writing data -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -On all 3 tested Northstar devices with following flash memories: -mx25l6405d (8192 Kbytes) -mx25l12805d (16384 Kbytes) -mx25l25635e (32768 Kbytes) -I noticed writing to be broken. Not a single bit was changed leaving all -bytes set to 0xff. - -This is most likely some problem related to the SPI controller or its -driver. Using a single SPI message seems to workaround this. Of course -it's not perfect solution as copying whole data into a new buffer makes -writing slower. - -Signed-off-by: Rafał Miłecki ---- - ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -78,6 +78,7 @@ static ssize_t m25p80_write(struct spi_n - { - struct m25p *flash = nor->priv; - struct spi_device *spi = flash->spi; -+ u8 *command = kzalloc(MAX_CMD_SIZE + len, GFP_KERNEL); - struct spi_transfer t[2] = {}; - struct spi_message m; - int cmd_sz = m25p_cmdsz(nor); -@@ -88,24 +89,26 @@ static ssize_t m25p80_write(struct spi_n - if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) - cmd_sz = 1; - -- flash->command[0] = nor->program_opcode; -- m25p_addr2cmd(nor, to, flash->command); -+ command[0] = nor->program_opcode; -+ m25p_addr2cmd(nor, to, command); -+ memcpy(&command[cmd_sz], buf, len); - -- t[0].tx_buf = flash->command; -- t[0].len = cmd_sz; -+ t[0].tx_buf = command; -+ t[0].len = cmd_sz + len; - spi_message_add_tail(&t[0], &m); - -- t[1].tx_buf = buf; -- t[1].len = len; -- spi_message_add_tail(&t[1], &m); -- - ret = spi_sync(spi, &m); -- if (ret) -+ if (ret) { -+ kfree(command); - return ret; -+ } - - ret = m.actual_length - cmd_sz; -- if (ret < 0) -+ if (ret < 0) { -+ kfree(command); - return -EIO; -+ } -+ kfree(command); - return ret; - } -