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