Merge tag 'u-boot-amlogic-20181207' of git://git.denx.de/u-boot-amlogic
[platform/kernel/u-boot.git] / drivers / spi / meson_spifc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
4  * Copyright (C) 2018 BayLibre, SAS
5  * Author: Neil Armstrong <narmstrong@baylibre.com>
6  *
7  * Amlogic Meson SPI Flash Controller driver
8  */
9
10 #include <common.h>
11 #include <spi.h>
12 #include <clk.h>
13 #include <dm.h>
14 #include <regmap.h>
15 #include <errno.h>
16 #include <asm/io.h>
17 #include <linux/bitfield.h>
18
19 /* register map */
20 #define REG_CMD                 0x00
21 #define REG_ADDR                0x04
22 #define REG_CTRL                0x08
23 #define REG_CTRL1               0x0c
24 #define REG_STATUS              0x10
25 #define REG_CTRL2               0x14
26 #define REG_CLOCK               0x18
27 #define REG_USER                0x1c
28 #define REG_USER1               0x20
29 #define REG_USER2               0x24
30 #define REG_USER3               0x28
31 #define REG_USER4               0x2c
32 #define REG_SLAVE               0x30
33 #define REG_SLAVE1              0x34
34 #define REG_SLAVE2              0x38
35 #define REG_SLAVE3              0x3c
36 #define REG_C0                  0x40
37 #define REG_B8                  0x60
38 #define REG_MAX                 0x7c
39
40 /* register fields */
41 #define CMD_USER                BIT(18)
42 #define CTRL_ENABLE_AHB         BIT(17)
43 #define CLOCK_SOURCE            BIT(31)
44 #define CLOCK_DIV_SHIFT         12
45 #define CLOCK_DIV_MASK          (0x3f << CLOCK_DIV_SHIFT)
46 #define CLOCK_CNT_HIGH_SHIFT    6
47 #define CLOCK_CNT_HIGH_MASK     (0x3f << CLOCK_CNT_HIGH_SHIFT)
48 #define CLOCK_CNT_LOW_SHIFT     0
49 #define CLOCK_CNT_LOW_MASK      (0x3f << CLOCK_CNT_LOW_SHIFT)
50 #define USER_DIN_EN_MS          BIT(0)
51 #define USER_CMP_MODE           BIT(2)
52 #define USER_CLK_NOT_INV        BIT(7)
53 #define USER_UC_DOUT_SEL        BIT(27)
54 #define USER_UC_DIN_SEL         BIT(28)
55 #define USER_UC_MASK            ((BIT(5) - 1) << 27)
56 #define USER1_BN_UC_DOUT_SHIFT  17
57 #define USER1_BN_UC_DOUT_MASK   (0xff << 16)
58 #define USER1_BN_UC_DIN_SHIFT   8
59 #define USER1_BN_UC_DIN_MASK    (0xff << 8)
60 #define USER4_CS_POL_HIGH       BIT(23)
61 #define USER4_IDLE_CLK_HIGH     BIT(29)
62 #define USER4_CS_ACT            BIT(30)
63 #define SLAVE_TRST_DONE         BIT(4)
64 #define SLAVE_OP_MODE           BIT(30)
65 #define SLAVE_SW_RST            BIT(31)
66
67 #define SPIFC_BUFFER_SIZE       64
68
69 struct meson_spifc_priv {
70         struct regmap                   *regmap;
71         struct clk                      clk;
72 };
73
74 /**
75  * meson_spifc_drain_buffer() - copy data from device buffer to memory
76  * @spifc:      the Meson SPI device
77  * @buf:        the destination buffer
78  * @len:        number of bytes to copy
79  */
80 static void meson_spifc_drain_buffer(struct meson_spifc_priv *spifc,
81                                      u8 *buf, int len)
82 {
83         u32 data;
84         int i = 0;
85
86         while (i < len) {
87                 regmap_read(spifc->regmap, REG_C0 + i, &data);
88
89                 if (len - i >= 4) {
90                         *((u32 *)buf) = data;
91                         buf += 4;
92                 } else {
93                         memcpy(buf, &data, len - i);
94                         break;
95                 }
96                 i += 4;
97         }
98 }
99
100 /**
101  * meson_spifc_fill_buffer() - copy data from memory to device buffer
102  * @spifc:      the Meson SPI device
103  * @buf:        the source buffer
104  * @len:        number of bytes to copy
105  */
106 static void meson_spifc_fill_buffer(struct meson_spifc_priv *spifc,
107                                     const u8 *buf, int len)
108 {
109         u32 data = 0;
110         int i = 0;
111
112         while (i < len) {
113                 if (len - i >= 4)
114                         data = *(u32 *)buf;
115                 else
116                         memcpy(&data, buf, len - i);
117
118                 regmap_write(spifc->regmap, REG_C0 + i, data);
119
120                 buf += 4;
121                 i += 4;
122         }
123 }
124
125 /**
126  * meson_spifc_txrx() - transfer a chunk of data
127  * @spifc:      the Meson SPI device
128  * @dout:       data buffer for TX
129  * @din:        data buffer for RX
130  * @offset:     offset of the data to transfer
131  * @len:        length of the data to transfer
132  * @last_xfer:  whether this is the last transfer of the message
133  * @last_chunk: whether this is the last chunk of the transfer
134  * Return:      0 on success, a negative value on error
135  */
136 static int meson_spifc_txrx(struct meson_spifc_priv *spifc,
137                             const u8 *dout, u8 *din, int offset,
138                             int len, bool last_xfer, bool last_chunk)
139 {
140         bool keep_cs = true;
141         u32 data;
142         int ret;
143
144         if (dout)
145                 meson_spifc_fill_buffer(spifc, dout + offset, len);
146
147         /* enable DOUT stage */
148         regmap_update_bits(spifc->regmap, REG_USER, USER_UC_MASK,
149                            USER_UC_DOUT_SEL);
150         regmap_write(spifc->regmap, REG_USER1,
151                      (8 * len - 1) << USER1_BN_UC_DOUT_SHIFT);
152
153         /* enable data input during DOUT */
154         regmap_update_bits(spifc->regmap, REG_USER, USER_DIN_EN_MS,
155                            USER_DIN_EN_MS);
156
157         if (last_chunk && last_xfer)
158                 keep_cs = false;
159
160         regmap_update_bits(spifc->regmap, REG_USER4, USER4_CS_ACT,
161                            keep_cs ? USER4_CS_ACT : 0);
162
163         /* clear transition done bit */
164         regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_TRST_DONE, 0);
165         /* start transfer */
166         regmap_update_bits(spifc->regmap, REG_CMD, CMD_USER, CMD_USER);
167
168         /* wait for the current operation to terminate */
169         ret = regmap_read_poll_timeout(spifc->regmap, REG_SLAVE, data,
170                                        (data & SLAVE_TRST_DONE),
171                                        0, 5 * CONFIG_SYS_HZ);
172
173         if (!ret && din)
174                 meson_spifc_drain_buffer(spifc, din + offset, len);
175
176         return ret;
177 }
178
179 /**
180  * meson_spifc_xfer() - perform a single transfer
181  * @dev:        the SPI controller device
182  * @bitlen:     length of the transfer
183  * @dout:       data buffer for TX
184  * @din:        data buffer for RX
185  * @flags:      transfer flags
186  * Return:      0 on success, a negative value on error
187  */
188 static int meson_spifc_xfer(struct udevice *slave, unsigned int bitlen,
189                             const void *dout, void *din, unsigned long flags)
190 {
191         struct meson_spifc_priv *spifc = dev_get_priv(slave->parent);
192         int blen = bitlen / 8;
193         int len, done = 0, ret = 0;
194
195         if (bitlen % 8)
196                 return -EINVAL;
197
198         debug("xfer len %d (%d) dout %p din %p\n", bitlen, blen, dout, din);
199
200         regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB, 0);
201
202         while (done < blen && !ret) {
203                 len = min_t(int, blen - done, SPIFC_BUFFER_SIZE);
204                 ret = meson_spifc_txrx(spifc, dout, din, done, len,
205                                        flags & SPI_XFER_END,
206                                        done + len >= blen);
207                 done += len;
208         }
209
210         regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB,
211                            CTRL_ENABLE_AHB);
212
213         return ret;
214 }
215
216 /**
217  * meson_spifc_set_speed() - program the clock divider
218  * @dev:        the SPI controller device
219  * @speed:      desired speed in Hz
220  */
221 static int meson_spifc_set_speed(struct udevice *dev, uint speed)
222 {
223         struct meson_spifc_priv *spifc = dev_get_priv(dev);
224         unsigned long parent, value;
225         int n;
226
227         parent = clk_get_rate(&spifc->clk);
228         n = max_t(int, parent / speed - 1, 1);
229
230         debug("parent %lu, speed %u, n %d\n", parent, speed, n);
231
232         value = (n << CLOCK_DIV_SHIFT) & CLOCK_DIV_MASK;
233         value |= (n << CLOCK_CNT_LOW_SHIFT) & CLOCK_CNT_LOW_MASK;
234         value |= (((n + 1) / 2 - 1) << CLOCK_CNT_HIGH_SHIFT) &
235                 CLOCK_CNT_HIGH_MASK;
236
237         regmap_write(spifc->regmap, REG_CLOCK, value);
238
239         return 0;
240 }
241
242 /**
243  * meson_spifc_set_mode() - setups the SPI bus mode
244  * @dev:        the SPI controller device
245  * @mode:       desired mode bitfield
246  * Return:      0 on success, -ENODEV on error
247  */
248 static int meson_spifc_set_mode(struct udevice *dev, uint mode)
249 {
250         struct meson_spifc_priv *spifc = dev_get_priv(dev);
251
252         if (mode & (SPI_CPHA | SPI_RX_QUAD | SPI_RX_DUAL |
253                     SPI_TX_QUAD | SPI_TX_DUAL))
254                 return -ENODEV;
255
256         regmap_update_bits(spifc->regmap, REG_USER, USER_CLK_NOT_INV,
257                            mode & SPI_CPOL ? USER_CLK_NOT_INV : 0);
258
259         regmap_update_bits(spifc->regmap, REG_USER4, USER4_CS_POL_HIGH,
260                            mode & SPI_CS_HIGH ? USER4_CS_POL_HIGH : 0);
261
262         return 0;
263 }
264
265 /**
266  * meson_spifc_hw_init() - reset and initialize the SPI controller
267  * @spifc:      the Meson SPI device
268  */
269 static void meson_spifc_hw_init(struct meson_spifc_priv *spifc)
270 {
271         /* reset device */
272         regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_SW_RST,
273                            SLAVE_SW_RST);
274         /* disable compatible mode */
275         regmap_update_bits(spifc->regmap, REG_USER, USER_CMP_MODE, 0);
276         /* set master mode */
277         regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_OP_MODE, 0);
278 }
279
280 static const struct dm_spi_ops meson_spifc_ops = {
281         .xfer           = meson_spifc_xfer,
282         .set_speed      = meson_spifc_set_speed,
283         .set_mode       = meson_spifc_set_mode,
284 };
285
286 static int meson_spifc_probe(struct udevice *dev)
287 {
288         struct meson_spifc_priv *priv = dev_get_priv(dev);
289         int ret;
290
291         ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
292         if (ret)
293                 return ret;
294
295         ret = clk_get_by_index(dev, 0, &priv->clk);
296         if (ret)
297                 return ret;
298
299         ret = clk_enable(&priv->clk);
300         if (ret)
301                 return ret;
302
303         meson_spifc_hw_init(priv);
304
305         return 0;
306 }
307
308 static const struct udevice_id meson_spifc_ids[] = {
309         { .compatible = "amlogic,meson-gxbb-spifc", },
310         { }
311 };
312
313 U_BOOT_DRIVER(meson_spifc) = {
314         .name           = "meson_spifc",
315         .id             = UCLASS_SPI,
316         .of_match       = meson_spifc_ids,
317         .ops            = &meson_spifc_ops,
318         .probe          = meson_spifc_probe,
319         .priv_auto_alloc_size = sizeof(struct meson_spifc_priv),
320 };