From dc567bd4daacc2c576333e71bab73e817a7bc7e1 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sat, 7 Mar 2015 15:54:04 -0600 Subject: update all kernel versions --- ...020-spi-ath79-add-fast-flash-read-support.patch | 202 +++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 target/mips/dragino-ms14s/patches/3.14.35/0020-spi-ath79-add-fast-flash-read-support.patch (limited to 'target/mips/dragino-ms14s/patches/3.14.35/0020-spi-ath79-add-fast-flash-read-support.patch') diff --git a/target/mips/dragino-ms14s/patches/3.14.35/0020-spi-ath79-add-fast-flash-read-support.patch b/target/mips/dragino-ms14s/patches/3.14.35/0020-spi-ath79-add-fast-flash-read-support.patch new file mode 100644 index 000000000..8fd174448 --- /dev/null +++ b/target/mips/dragino-ms14s/patches/3.14.35/0020-spi-ath79-add-fast-flash-read-support.patch @@ -0,0 +1,202 @@ +From c4388a57860440e23c9654f4de2f515433e685a1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 13 May 2014 04:12:35 +0200 +Subject: [PATCH] spi-ath79: add fast flash read support + +--- + .../include/asm/mach-ath79/ath79_spi_platform.h | 1 + + drivers/spi/spi-ath79.c | 124 ++++++++++++++++++++- + 2 files changed, 120 insertions(+), 5 deletions(-) + +diff --git a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h +index aa2283e..65369fe 100644 +--- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h ++++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h +@@ -18,6 +18,7 @@ struct ath79_spi_platform_data { + + struct ath79_spi_controller_data { + unsigned gpio; ++ bool is_flash; + }; + + #endif /* _ATH79_SPI_PLATFORM_H */ +diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c +index c3b2fb9..a26a6a4 100644 +--- a/drivers/spi/spi-ath79.c ++++ b/drivers/spi/spi-ath79.c +@@ -35,6 +35,11 @@ + #define ATH79_SPI_RRW_DELAY_FACTOR 12000 + #define MHZ (1000 * 1000) + ++enum ath79_spi_state { ++ ATH79_SPI_STATE_WAIT_CMD = 0, ++ ATH79_SPI_STATE_WAIT_READ, ++}; ++ + struct ath79_spi { + struct spi_bitbang bitbang; + u32 ioc_base; +@@ -42,6 +47,11 @@ struct ath79_spi { + void __iomem *base; + struct clk *clk; + unsigned rrw_delay; ++ ++ enum ath79_spi_state state; ++ u32 clk_div; ++ unsigned long read_addr; ++ unsigned long ahb_rate; + }; + + static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) +@@ -104,9 +114,6 @@ static void ath79_spi_enable(struct ath79_spi *sp) + /* save CTRL register */ + sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); + sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); +- +- /* TODO: setup speed? */ +- ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); + } + + static void ath79_spi_disable(struct ath79_spi *sp) +@@ -203,6 +210,110 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, + return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); + } + ++static int ath79_spi_do_read_flash_data(struct spi_device *spi, ++ struct spi_transfer *t) ++{ ++ struct ath79_spi *sp = ath79_spidev_to_sp(spi); ++ ++ /* disable GPIO mode */ ++ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); ++ ++ memcpy_fromio(t->rx_buf, sp->base + sp->read_addr, t->len); ++ ++ /* enable GPIO mode */ ++ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); ++ ++ /* restore IOC register */ ++ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); ++ ++ return t->len; ++} ++ ++static int ath79_spi_do_read_flash_cmd(struct spi_device *spi, ++ struct spi_transfer *t) ++{ ++ struct ath79_spi *sp = ath79_spidev_to_sp(spi); ++ int len; ++ const u8 *p; ++ ++ sp->read_addr = 0; ++ ++ len = t->len - 1; ++ p = t->tx_buf; ++ ++ while (len--) { ++ p++; ++ sp->read_addr <<= 8; ++ sp->read_addr |= *p; ++ } ++ ++ return t->len; ++} ++ ++static bool ath79_spi_is_read_cmd(struct spi_device *spi, ++ struct spi_transfer *t) ++{ ++ return t->type == SPI_TRANSFER_FLASH_READ_CMD; ++} ++ ++static bool ath79_spi_is_data_read(struct spi_device *spi, ++ struct spi_transfer *t) ++{ ++ return t->type == SPI_TRANSFER_FLASH_READ_DATA; ++} ++ ++static int ath79_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ++{ ++ struct ath79_spi *sp = ath79_spidev_to_sp(spi); ++ int ret; ++ ++ switch (sp->state) { ++ case ATH79_SPI_STATE_WAIT_CMD: ++ if (ath79_spi_is_read_cmd(spi, t)) { ++ ret = ath79_spi_do_read_flash_cmd(spi, t); ++ sp->state = ATH79_SPI_STATE_WAIT_READ; ++ } else { ++ ret = spi_bitbang_bufs(spi, t); ++ } ++ break; ++ ++ case ATH79_SPI_STATE_WAIT_READ: ++ if (ath79_spi_is_data_read(spi, t)) { ++ ret = ath79_spi_do_read_flash_data(spi, t); ++ } else { ++ dev_warn(&spi->dev, "flash data read expected\n"); ++ ret = -EIO; ++ } ++ sp->state = ATH79_SPI_STATE_WAIT_CMD; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ return ret; ++} ++ ++static int ath79_spi_setup_transfer(struct spi_device *spi, ++ struct spi_transfer *t) ++{ ++ struct ath79_spi *sp = ath79_spidev_to_sp(spi); ++ struct ath79_spi_controller_data *cdata; ++ int ret; ++ ++ ret = spi_bitbang_setup_transfer(spi, t); ++ if (ret) ++ return ret; ++ ++ cdata = spi->controller_data; ++ if (cdata->is_flash) ++ sp->bitbang.txrx_bufs = ath79_spi_txrx_bufs; ++ else ++ sp->bitbang.txrx_bufs = spi_bitbang_bufs; ++ ++ return ret; ++} ++ + static int ath79_spi_probe(struct platform_device *pdev) + { + struct spi_master *master; +@@ -223,6 +334,8 @@ static int ath79_spi_probe(struct platform_device *pdev) + + pdata = dev_get_platdata(&pdev->dev); + ++ sp->state = ATH79_SPI_STATE_WAIT_CMD; ++ + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); + master->setup = ath79_spi_setup; + master->cleanup = ath79_spi_cleanup; +@@ -234,7 +347,7 @@ static int ath79_spi_probe(struct platform_device *pdev) + sp->bitbang.master = master; + sp->bitbang.chipselect = ath79_spi_chipselect; + sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; +- sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; ++ sp->bitbang.setup_transfer = ath79_spi_setup_transfer; + sp->bitbang.flags = SPI_CS_HIGH; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -259,7 +372,8 @@ static int ath79_spi_probe(struct platform_device *pdev) + if (ret) + goto err_put_master; + +- rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ); ++ sp->ahb_rate = clk_get_rate(sp->clk); ++ rate = DIV_ROUND_UP(sp->ahb_rate, MHZ); + if (!rate) { + ret = -EINVAL; + goto err_clk_disable; +-- +1.8.5.3 + -- cgit v1.2.3