kernel: fix ip6_tunnel compilation
[openwrt.git] / target / linux / generic / patches-4.4 / 081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch
1 From a7b221d8f0d75511c5f959584712a5dd35f88a86 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
3 Date: Mon, 18 Apr 2016 14:39:30 +0200
4 Subject: [PATCH] spi: bcm53xx: add spi_flash_read callback for MMIO-based
5  reads
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 This implements more efficient reads of SPI-attached flash content.
11
12 Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
13 Signed-off-by: Mark Brown <broonie@kernel.org>
14 ---
15
16 --- a/drivers/spi/spi-bcm53xx.c
17 +++ b/drivers/spi/spi-bcm53xx.c
18 @@ -10,6 +10,7 @@
19  #include "spi-bcm53xx.h"
20  
21  #define BCM53XXSPI_MAX_SPI_BAUD        13500000        /* 216 MHz? */
22 +#define BCM53XXSPI_FLASH_WINDOW        SZ_32M
23  
24  /* The longest observed required wait was 19 ms */
25  #define BCM53XXSPI_SPE_TIMEOUT_MS      80
26 @@ -17,8 +18,10 @@
27  struct bcm53xxspi {
28         struct bcma_device *core;
29         struct spi_master *master;
30 +       void __iomem *mmio_base;
31  
32         size_t read_offset;
33 +       bool bspi;                              /* Boot SPI mode with memory mapping */
34  };
35  
36  static inline u32 bcm53xxspi_read(struct bcm53xxspi *b53spi, u16 offset)
37 @@ -32,6 +35,50 @@ static inline void bcm53xxspi_write(struct bcm53xxspi *b53spi, u16 offset,
38         bcma_write32(b53spi->core, offset, value);
39  }
40  
41 +static void bcm53xxspi_disable_bspi(struct bcm53xxspi *b53spi)
42 +{
43 +       struct device *dev = &b53spi->core->dev;
44 +       unsigned long deadline;
45 +       u32 tmp;
46 +
47 +       if (!b53spi->bspi)
48 +               return;
49 +
50 +       tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL);
51 +       if (tmp & 0x1)
52 +               return;
53 +
54 +       deadline = jiffies + usecs_to_jiffies(200);
55 +       do {
56 +               tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_BUSY_STATUS);
57 +               if (!(tmp & 0x1)) {
58 +                       bcm53xxspi_write(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL,
59 +                                        0x1);
60 +                       ndelay(200);
61 +                       b53spi->bspi = false;
62 +                       return;
63 +               }
64 +               udelay(1);
65 +       } while (!time_after_eq(jiffies, deadline));
66 +
67 +       dev_warn(dev, "Timeout disabling BSPI\n");
68 +}
69 +
70 +static void bcm53xxspi_enable_bspi(struct bcm53xxspi *b53spi)
71 +{
72 +       u32 tmp;
73 +
74 +       if (b53spi->bspi)
75 +               return;
76 +
77 +       tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL);
78 +       if (!(tmp & 0x1))
79 +               return;
80 +
81 +       bcm53xxspi_write(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL, 0x0);
82 +       b53spi->bspi = true;
83 +}
84 +
85  static inline unsigned int bcm53xxspi_calc_timeout(size_t len)
86  {
87         /* Do some magic calculation based on length and buad. Add 10% and 1. */
88 @@ -176,6 +223,8 @@ static int bcm53xxspi_transfer_one(struct spi_master *master,
89         u8 *buf;
90         size_t left;
91  
92 +       bcm53xxspi_disable_bspi(b53spi);
93 +
94         if (t->tx_buf) {
95                 buf = (u8 *)t->tx_buf;
96                 left = t->len;
97 @@ -206,6 +255,22 @@ static int bcm53xxspi_transfer_one(struct spi_master *master,
98         return 0;
99  }
100  
101 +static int bcm53xxspi_flash_read(struct spi_device *spi,
102 +                                struct spi_flash_read_message *msg)
103 +{
104 +       struct bcm53xxspi *b53spi = spi_master_get_devdata(spi->master);
105 +       int ret = 0;
106 +
107 +       if (msg->from + msg->len > BCM53XXSPI_FLASH_WINDOW)
108 +               return -EINVAL;
109 +
110 +       bcm53xxspi_enable_bspi(b53spi);
111 +       memcpy_fromio(msg->buf, b53spi->mmio_base + msg->from, msg->len);
112 +       msg->retlen = msg->len;
113 +
114 +       return ret;
115 +}
116 +
117  /**************************************************
118   * BCMA
119   **************************************************/
120 @@ -222,6 +287,7 @@ MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl);
121  
122  static int bcm53xxspi_bcma_probe(struct bcma_device *core)
123  {
124 +       struct device *dev = &core->dev;
125         struct bcm53xxspi *b53spi;
126         struct spi_master *master;
127         int err;
128 @@ -231,7 +297,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
129                 return -ENOTSUPP;
130         }
131  
132 -       master = spi_alloc_master(&core->dev, sizeof(*b53spi));
133 +       master = spi_alloc_master(dev, sizeof(*b53spi));
134         if (!master)
135                 return -ENOMEM;
136  
137 @@ -239,11 +305,19 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
138         b53spi->master = master;
139         b53spi->core = core;
140  
141 +       if (core->addr_s[0])
142 +               b53spi->mmio_base = devm_ioremap(dev, core->addr_s[0],
143 +                                                BCM53XXSPI_FLASH_WINDOW);
144 +       b53spi->bspi = true;
145 +       bcm53xxspi_disable_bspi(b53spi);
146 +
147         master->transfer_one = bcm53xxspi_transfer_one;
148 +       if (b53spi->mmio_base)
149 +               master->spi_flash_read = bcm53xxspi_flash_read;
150  
151         bcma_set_drvdata(core, b53spi);
152  
153 -       err = devm_spi_register_master(&core->dev, master);
154 +       err = devm_spi_register_master(dev, master);
155         if (err) {
156                 spi_master_put(master);
157                 bcma_set_drvdata(core, NULL);