123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- From c4388a57860440e23c9654f4de2f515433e685a1 Mon Sep 17 00:00:00 2001
- From: Phil Sutter <phil@nwl.cc>
- 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
|