1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for Amlogic A1 SPI flash controller (SPIFC)
5 * Copyright (c) 2023, SberDevices. All Rights Reserved.
7 * Author: Martin Kurbanov <mmkurbanov@sberdevices.ru>
10 * Author: Igor Prusov <ivprusov@sberdevices.ru>
18 #include <linux/log2.h>
19 #include <linux/iopoll.h>
20 #include <linux/bitfield.h>
22 #define SPIFC_A1_AHB_CTRL_REG 0x0
23 #define SPIFC_A1_AHB_BUS_EN BIT(31)
25 #define SPIFC_A1_USER_CTRL0_REG 0x200
26 #define SPIFC_A1_USER_REQUEST_ENABLE BIT(31)
27 #define SPIFC_A1_USER_REQUEST_FINISH BIT(30)
28 #define SPIFC_A1_USER_DATA_UPDATED BIT(0)
30 #define SPIFC_A1_USER_CTRL1_REG 0x204
31 #define SPIFC_A1_USER_CMD_ENABLE BIT(30)
32 #define SPIFC_A1_USER_CMD_MODE GENMASK(29, 28)
33 #define SPIFC_A1_USER_CMD_CODE GENMASK(27, 20)
34 #define SPIFC_A1_USER_ADDR_ENABLE BIT(19)
35 #define SPIFC_A1_USER_ADDR_MODE GENMASK(18, 17)
36 #define SPIFC_A1_USER_ADDR_BYTES GENMASK(16, 15)
37 #define SPIFC_A1_USER_DOUT_ENABLE BIT(14)
38 #define SPIFC_A1_USER_DOUT_MODE GENMASK(11, 10)
39 #define SPIFC_A1_USER_DOUT_BYTES GENMASK(9, 0)
41 #define SPIFC_A1_USER_CTRL2_REG 0x208
42 #define SPIFC_A1_USER_DUMMY_ENABLE BIT(31)
43 #define SPIFC_A1_USER_DUMMY_MODE GENMASK(30, 29)
44 #define SPIFC_A1_USER_DUMMY_CLK_SYCLES GENMASK(28, 23)
46 #define SPIFC_A1_USER_CTRL3_REG 0x20c
47 #define SPIFC_A1_USER_DIN_ENABLE BIT(31)
48 #define SPIFC_A1_USER_DIN_MODE GENMASK(28, 27)
49 #define SPIFC_A1_USER_DIN_BYTES GENMASK(25, 16)
51 #define SPIFC_A1_USER_ADDR_REG 0x210
53 #define SPIFC_A1_AHB_REQ_CTRL_REG 0x214
54 #define SPIFC_A1_AHB_REQ_ENABLE BIT(31)
56 #define SPIFC_A1_ACTIMING0_REG (0x0088 << 2)
57 #define SPIFC_A1_TSLCH GENMASK(31, 30)
58 #define SPIFC_A1_TCLSH GENMASK(29, 28)
59 #define SPIFC_A1_TSHWL GENMASK(20, 16)
60 #define SPIFC_A1_TSHSL2 GENMASK(15, 12)
61 #define SPIFC_A1_TSHSL1 GENMASK(11, 8)
62 #define SPIFC_A1_TWHSL GENMASK(7, 0)
64 #define SPIFC_A1_DBUF_CTRL_REG 0x240
65 #define SPIFC_A1_DBUF_DIR BIT(31)
66 #define SPIFC_A1_DBUF_AUTO_UPDATE_ADDR BIT(30)
67 #define SPIFC_A1_DBUF_ADDR GENMASK(7, 0)
69 #define SPIFC_A1_DBUF_DATA_REG 0x244
71 #define SPIFC_A1_USER_DBUF_ADDR_REG 0x248
73 #define SPIFC_A1_BUFFER_SIZE 512U
75 #define SPIFC_A1_MAX_HZ 200000000
76 #define SPIFC_A1_MIN_HZ 1000000
78 #define SPIFC_A1_USER_CMD(op) ( \
79 SPIFC_A1_USER_CMD_ENABLE | \
80 FIELD_PREP(SPIFC_A1_USER_CMD_CODE, (op)->cmd.opcode) | \
81 FIELD_PREP(SPIFC_A1_USER_CMD_MODE, ilog2((op)->cmd.buswidth)))
83 #define SPIFC_A1_USER_ADDR(op) ( \
84 SPIFC_A1_USER_ADDR_ENABLE | \
85 FIELD_PREP(SPIFC_A1_USER_ADDR_MODE, ilog2((op)->addr.buswidth)) | \
86 FIELD_PREP(SPIFC_A1_USER_ADDR_BYTES, (op)->addr.nbytes - 1))
88 #define SPIFC_A1_USER_DUMMY(op) ( \
89 SPIFC_A1_USER_DUMMY_ENABLE | \
90 FIELD_PREP(SPIFC_A1_USER_DUMMY_MODE, ilog2((op)->dummy.buswidth)) | \
91 FIELD_PREP(SPIFC_A1_USER_DUMMY_CLK_SYCLES, (op)->dummy.nbytes << 3))
93 #define SPIFC_A1_TSLCH_VAL FIELD_PREP(SPIFC_A1_TSLCH, 1)
94 #define SPIFC_A1_TCLSH_VAL FIELD_PREP(SPIFC_A1_TCLSH, 1)
95 #define SPIFC_A1_TSHWL_VAL FIELD_PREP(SPIFC_A1_TSHWL, 7)
96 #define SPIFC_A1_TSHSL2_VAL FIELD_PREP(SPIFC_A1_TSHSL2, 7)
97 #define SPIFC_A1_TSHSL1_VAL FIELD_PREP(SPIFC_A1_TSHSL1, 7)
98 #define SPIFC_A1_TWHSL_VAL FIELD_PREP(SPIFC_A1_TWHSL, 2)
99 #define SPIFC_A1_ACTIMING0_VAL (SPIFC_A1_TSLCH_VAL | SPIFC_A1_TCLSH_VAL | \
100 SPIFC_A1_TSHWL_VAL | SPIFC_A1_TSHSL2_VAL | \
101 SPIFC_A1_TSHSL1_VAL | SPIFC_A1_TWHSL_VAL)
103 struct amlogic_spifc_a1
{
109 static int amlogic_spifc_a1_request(struct amlogic_spifc_a1
*spifc
, bool read
)
111 u32 mask
= SPIFC_A1_USER_REQUEST_FINISH
|
112 (read
? SPIFC_A1_USER_DATA_UPDATED
: 0);
115 writel(SPIFC_A1_USER_REQUEST_ENABLE
,
116 spifc
->base
+ SPIFC_A1_USER_CTRL0_REG
);
118 return readl_poll_timeout(spifc
->base
+ SPIFC_A1_USER_CTRL0_REG
,
119 val
, (val
& mask
) == mask
,
123 static void amlogic_spifc_a1_drain_buffer(struct amlogic_spifc_a1
*spifc
,
127 const u32 count
= len
/ sizeof(data
);
128 const u32 pad
= len
% sizeof(data
);
130 writel(SPIFC_A1_DBUF_AUTO_UPDATE_ADDR
,
131 spifc
->base
+ SPIFC_A1_DBUF_CTRL_REG
);
132 ioread32_rep(spifc
->base
+ SPIFC_A1_DBUF_DATA_REG
, buf
, count
);
135 data
= readl(spifc
->base
+ SPIFC_A1_DBUF_DATA_REG
);
136 memcpy(buf
+ len
- pad
, &data
, pad
);
140 static void amlogic_spifc_a1_fill_buffer(struct amlogic_spifc_a1
*spifc
,
141 const char *buf
, u32 len
)
144 const u32 count
= len
/ sizeof(data
);
145 const u32 pad
= len
% sizeof(data
);
147 writel(SPIFC_A1_DBUF_DIR
| SPIFC_A1_DBUF_AUTO_UPDATE_ADDR
,
148 spifc
->base
+ SPIFC_A1_DBUF_CTRL_REG
);
149 iowrite32_rep(spifc
->base
+ SPIFC_A1_DBUF_DATA_REG
, buf
, count
);
152 memcpy(&data
, buf
+ len
- pad
, pad
);
153 writel(data
, spifc
->base
+ SPIFC_A1_DBUF_DATA_REG
);
157 static void amlogic_spifc_a1_user_init(struct amlogic_spifc_a1
*spifc
)
159 writel(0, spifc
->base
+ SPIFC_A1_USER_CTRL0_REG
);
160 writel(0, spifc
->base
+ SPIFC_A1_USER_CTRL1_REG
);
161 writel(0, spifc
->base
+ SPIFC_A1_USER_CTRL2_REG
);
162 writel(0, spifc
->base
+ SPIFC_A1_USER_CTRL3_REG
);
165 static void amlogic_spifc_a1_set_cmd(struct amlogic_spifc_a1
*spifc
,
170 val
= readl(spifc
->base
+ SPIFC_A1_USER_CTRL1_REG
);
171 val
&= ~(SPIFC_A1_USER_CMD_MODE
| SPIFC_A1_USER_CMD_CODE
);
173 writel(val
, spifc
->base
+ SPIFC_A1_USER_CTRL1_REG
);
176 static void amlogic_spifc_a1_set_addr(struct amlogic_spifc_a1
*spifc
, u32 addr
,
181 writel(addr
, spifc
->base
+ SPIFC_A1_USER_ADDR_REG
);
183 val
= readl(spifc
->base
+ SPIFC_A1_USER_CTRL1_REG
);
184 val
&= ~(SPIFC_A1_USER_ADDR_MODE
| SPIFC_A1_USER_ADDR_BYTES
);
186 writel(val
, spifc
->base
+ SPIFC_A1_USER_CTRL1_REG
);
189 static void amlogic_spifc_a1_set_dummy(struct amlogic_spifc_a1
*spifc
,
192 u32 val
= readl(spifc
->base
+ SPIFC_A1_USER_CTRL2_REG
);
194 val
&= ~(SPIFC_A1_USER_DUMMY_MODE
| SPIFC_A1_USER_DUMMY_CLK_SYCLES
);
196 writel(val
, spifc
->base
+ SPIFC_A1_USER_CTRL2_REG
);
199 static int amlogic_spifc_a1_read(struct amlogic_spifc_a1
*spifc
, void *buf
,
202 u32 val
= readl(spifc
->base
+ SPIFC_A1_USER_CTRL3_REG
);
205 val
&= ~(SPIFC_A1_USER_DIN_MODE
| SPIFC_A1_USER_DIN_BYTES
);
206 val
|= SPIFC_A1_USER_DIN_ENABLE
;
207 val
|= FIELD_PREP(SPIFC_A1_USER_DIN_MODE
, mode
);
208 val
|= FIELD_PREP(SPIFC_A1_USER_DIN_BYTES
, size
);
209 writel(val
, spifc
->base
+ SPIFC_A1_USER_CTRL3_REG
);
211 ret
= amlogic_spifc_a1_request(spifc
, true);
213 amlogic_spifc_a1_drain_buffer(spifc
, buf
, size
);
218 static int amlogic_spifc_a1_write(struct amlogic_spifc_a1
*spifc
,
219 const void *buf
, u32 size
, u32 mode
)
223 amlogic_spifc_a1_fill_buffer(spifc
, buf
, size
);
225 val
= readl(spifc
->base
+ SPIFC_A1_USER_CTRL1_REG
);
226 val
&= ~(SPIFC_A1_USER_DOUT_MODE
| SPIFC_A1_USER_DOUT_BYTES
);
227 val
|= FIELD_PREP(SPIFC_A1_USER_DOUT_MODE
, mode
);
228 val
|= FIELD_PREP(SPIFC_A1_USER_DOUT_BYTES
, size
);
229 val
|= SPIFC_A1_USER_DOUT_ENABLE
;
230 writel(val
, spifc
->base
+ SPIFC_A1_USER_CTRL1_REG
);
232 return amlogic_spifc_a1_request(spifc
, false);
235 static int amlogic_spifc_a1_set_freq(struct amlogic_spifc_a1
*spifc
, u32 freq
)
239 if (freq
== spifc
->curr_speed_hz
)
242 ret
= clk_set_rate(&spifc
->clk
, freq
);
246 spifc
->curr_speed_hz
= freq
;
250 static int amlogic_spifc_a1_exec_op(struct spi_slave
*slave
,
251 const struct spi_mem_op
*op
)
253 struct amlogic_spifc_a1
*spifc
= dev_get_priv(slave
->dev
->parent
);
254 size_t data_size
= op
->data
.nbytes
;
257 ret
= amlogic_spifc_a1_set_freq(spifc
, slave
->max_hz
);
261 amlogic_spifc_a1_user_init(spifc
);
262 amlogic_spifc_a1_set_cmd(spifc
, SPIFC_A1_USER_CMD(op
));
265 amlogic_spifc_a1_set_addr(spifc
, op
->addr
.val
,
266 SPIFC_A1_USER_ADDR(op
));
268 if (op
->dummy
.nbytes
)
269 amlogic_spifc_a1_set_dummy(spifc
, SPIFC_A1_USER_DUMMY(op
));
272 u32 mode
= ilog2(op
->data
.buswidth
);
274 writel(0, spifc
->base
+ SPIFC_A1_USER_DBUF_ADDR_REG
);
276 if (op
->data
.dir
== SPI_MEM_DATA_IN
)
277 ret
= amlogic_spifc_a1_read(spifc
, op
->data
.buf
.in
,
280 ret
= amlogic_spifc_a1_write(spifc
, op
->data
.buf
.out
,
283 ret
= amlogic_spifc_a1_request(spifc
, false);
289 static int amlogic_spifc_a1_adjust_op_size(struct spi_slave
*slave
,
290 struct spi_mem_op
*op
)
292 op
->data
.nbytes
= min(op
->data
.nbytes
, SPIFC_A1_BUFFER_SIZE
);
296 static void amlogic_spifc_a1_hw_init(struct amlogic_spifc_a1
*spifc
)
300 regv
= readl(spifc
->base
+ SPIFC_A1_AHB_REQ_CTRL_REG
);
301 regv
&= ~(SPIFC_A1_AHB_REQ_ENABLE
);
302 writel(regv
, spifc
->base
+ SPIFC_A1_AHB_REQ_CTRL_REG
);
304 regv
= readl(spifc
->base
+ SPIFC_A1_AHB_CTRL_REG
);
305 regv
&= ~(SPIFC_A1_AHB_BUS_EN
);
306 writel(regv
, spifc
->base
+ SPIFC_A1_AHB_CTRL_REG
);
308 writel(SPIFC_A1_ACTIMING0_VAL
, spifc
->base
+ SPIFC_A1_ACTIMING0_REG
);
310 writel(0, spifc
->base
+ SPIFC_A1_USER_DBUF_ADDR_REG
);
313 static const struct spi_controller_mem_ops amlogic_spifc_a1_mem_ops
= {
314 .exec_op
= amlogic_spifc_a1_exec_op
,
315 .adjust_op_size
= amlogic_spifc_a1_adjust_op_size
,
318 static int amlogic_spifc_a1_probe(struct udevice
*dev
)
320 struct amlogic_spifc_a1
*spifc
= dev_get_priv(dev
);
322 struct udevice
*bus
= dev
;
324 spifc
->base
= dev_read_addr_ptr(dev
);
328 ret
= clk_get_by_index(bus
, 0, &spifc
->clk
);
330 pr_err("can't get clk spifc_gate!\n");
334 ret
= clk_enable(&spifc
->clk
);
336 pr_err("enable clk fail\n");
340 amlogic_spifc_a1_hw_init(spifc
);
345 static int amlogic_spifc_a1_remove(struct udevice
*dev
)
347 struct amlogic_spifc_a1
*spifc
= dev_get_priv(dev
);
349 clk_free(&spifc
->clk
);
354 static const struct udevice_id meson_spifc_ids
[] = {
355 { .compatible
= "amlogic,a1-spifc", },
359 int amlogic_spifc_a1_set_speed(struct udevice
*bus
, uint hz
)
364 int amlogic_spifc_a1_set_mode(struct udevice
*bus
, uint mode
)
369 static const struct dm_spi_ops amlogic_spifc_a1_ops
= {
370 .mem_ops
= &amlogic_spifc_a1_mem_ops
,
371 .set_speed
= amlogic_spifc_a1_set_speed
,
372 .set_mode
= amlogic_spifc_a1_set_mode
,
375 U_BOOT_DRIVER(meson_spifc_a1
) = {
376 .name
= "meson_spifc_a1",
378 .of_match
= meson_spifc_ids
,
379 .ops
= &amlogic_spifc_a1_ops
,
380 .probe
= amlogic_spifc_a1_probe
,
381 .remove
= amlogic_spifc_a1_remove
,
382 .priv_auto
= sizeof(struct amlogic_spifc_a1
),