ar71xx: wpj588: add missing usb support
[openwrt.git] / target / linux / ar71xx / patches-3.18 / 463-spi-ath79-add-fast-flash-read.patch
1 --- a/drivers/spi/spi-ath79.c
2 +++ b/drivers/spi/spi-ath79.c
3 @@ -35,6 +35,11 @@
4  
5  #define ATH79_SPI_CS_LINE_MAX          2
6  
7 +enum ath79_spi_state {
8 +       ATH79_SPI_STATE_WAIT_CMD = 0,
9 +       ATH79_SPI_STATE_WAIT_READ,
10 +};
11 +
12  struct ath79_spi {
13         struct spi_bitbang      bitbang;
14         u32                     ioc_base;
15 @@ -42,6 +47,11 @@ struct ath79_spi {
16         void __iomem            *base;
17         struct clk              *clk;
18         unsigned                rrw_delay;
19 +
20 +       enum ath79_spi_state    state;
21 +       u32                     clk_div;
22 +       unsigned long           read_addr;
23 +       unsigned long           ahb_rate;
24  };
25  
26  static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
27 @@ -109,9 +119,6 @@ static void ath79_spi_enable(struct ath7
28         /* save CTRL register */
29         sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
30         sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
31 -
32 -       /* TODO: setup speed? */
33 -       ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
34  }
35  
36  static void ath79_spi_disable(struct ath79_spi *sp)
37 @@ -224,6 +231,110 @@ static u32 ath79_spi_txrx_mode0(struct s
38         return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
39  }
40  
41 +static int ath79_spi_do_read_flash_data(struct spi_device *spi,
42 +                                       struct spi_transfer *t)
43 +{
44 +       struct ath79_spi *sp = ath79_spidev_to_sp(spi);
45 +
46 +       /* disable GPIO mode */
47 +       ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
48 +
49 +       memcpy_fromio(t->rx_buf, sp->base + sp->read_addr, t->len);
50 +
51 +       /* enable GPIO mode */
52 +       ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
53 +
54 +       /* restore IOC register */
55 +       ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
56 +
57 +       return t->len;
58 +}
59 +
60 +static int ath79_spi_do_read_flash_cmd(struct spi_device *spi,
61 +                                      struct spi_transfer *t)
62 +{
63 +       struct ath79_spi *sp = ath79_spidev_to_sp(spi);
64 +       int len;
65 +       const u8 *p;
66 +
67 +       sp->read_addr = 0;
68 +
69 +       len = t->len - 1;
70 +       p = t->tx_buf;
71 +
72 +       while (len--) {
73 +               p++;
74 +               sp->read_addr <<= 8;
75 +               sp->read_addr |= *p;
76 +       }
77 +
78 +       return t->len;
79 +}
80 +
81 +static bool ath79_spi_is_read_cmd(struct spi_device *spi,
82 +                                struct spi_transfer *t)
83 +{
84 +       return t->type == SPI_TRANSFER_FLASH_READ_CMD;
85 +}
86 +
87 +static bool ath79_spi_is_data_read(struct spi_device *spi,
88 +                                 struct spi_transfer *t)
89 +{
90 +       return t->type == SPI_TRANSFER_FLASH_READ_DATA;
91 +}
92 +
93 +static int ath79_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
94 +{
95 +       struct ath79_spi *sp = ath79_spidev_to_sp(spi);
96 +       int ret;
97 +
98 +       switch (sp->state) {
99 +       case ATH79_SPI_STATE_WAIT_CMD:
100 +               if (ath79_spi_is_read_cmd(spi, t)) {
101 +                       ret = ath79_spi_do_read_flash_cmd(spi, t);
102 +                       sp->state = ATH79_SPI_STATE_WAIT_READ;
103 +               } else {
104 +                       ret = spi_bitbang_bufs(spi, t);
105 +               }
106 +               break;
107 +
108 +       case ATH79_SPI_STATE_WAIT_READ:
109 +               if (ath79_spi_is_data_read(spi, t)) {
110 +                       ret = ath79_spi_do_read_flash_data(spi, t);
111 +               } else {
112 +                       dev_warn(&spi->dev, "flash data read expected\n");
113 +                       ret = -EIO;
114 +               }
115 +               sp->state = ATH79_SPI_STATE_WAIT_CMD;
116 +               break;
117 +
118 +       default:
119 +               BUG();
120 +       }
121 +
122 +       return ret;
123 +}
124 +
125 +static int ath79_spi_setup_transfer(struct spi_device *spi,
126 +                                   struct spi_transfer *t)
127 +{
128 +       struct ath79_spi *sp = ath79_spidev_to_sp(spi);
129 +       struct ath79_spi_controller_data *cdata;
130 +       int ret;
131 +
132 +       ret = spi_bitbang_setup_transfer(spi, t);
133 +       if (ret)
134 +               return ret;
135 +
136 +       cdata = spi->controller_data;
137 +       if (cdata->is_flash)
138 +               sp->bitbang.txrx_bufs = ath79_spi_txrx_bufs;
139 +       else
140 +               sp->bitbang.txrx_bufs = spi_bitbang_bufs;
141 +
142 +       return ret;
143 +}
144 +
145  static int ath79_spi_probe(struct platform_device *pdev)
146  {
147         struct spi_master *master;
148 @@ -246,6 +357,8 @@ static int ath79_spi_probe(struct platfo
149         sp = spi_master_get_devdata(master);
150         platform_set_drvdata(pdev, sp);
151  
152 +       sp->state = ATH79_SPI_STATE_WAIT_CMD;
153 +
154         master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
155         master->setup = ath79_spi_setup;
156         master->cleanup = ath79_spi_cleanup;
157 @@ -255,7 +368,7 @@ static int ath79_spi_probe(struct platfo
158         sp->bitbang.master = master;
159         sp->bitbang.chipselect = ath79_spi_chipselect;
160         sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
161 -       sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
162 +       sp->bitbang.setup_transfer = ath79_spi_setup_transfer;
163         sp->bitbang.flags = SPI_CS_HIGH;
164  
165         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
166 @@ -280,7 +393,8 @@ static int ath79_spi_probe(struct platfo
167         if (ret)
168                 goto err_put_master;
169  
170 -       rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
171 +       sp->ahb_rate = clk_get_rate(sp->clk);
172 +       rate = DIV_ROUND_UP(sp->ahb_rate, MHZ);
173         if (!rate) {
174                 ret = -EINVAL;
175                 goto err_clk_disable;
176 --- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
177 +++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
178 @@ -24,6 +24,7 @@ enum ath79_spi_cs_type {
179  struct ath79_spi_controller_data {
180         enum ath79_spi_cs_type cs_type;
181         unsigned cs_line;
182 +       bool is_flash;
183  };
184  
185  #endif /* _ATH79_SPI_PLATFORM_H */