1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * DFL device driver for Nios private feature on Intel PAC (Programmable |
4 | * Acceleration Card) N3000 |
5 | * |
6 | * Copyright (C) 2019-2020 Intel Corporation, Inc. |
7 | * |
8 | * Authors: |
9 | * Wu Hao <hao.wu@intel.com> |
10 | * Xu Yilun <yilun.xu@intel.com> |
11 | */ |
12 | #include <linux/bitfield.h> |
13 | #include <linux/dfl.h> |
14 | #include <linux/errno.h> |
15 | #include <linux/io.h> |
16 | #include <linux/io-64-nonatomic-lo-hi.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> |
20 | #include <linux/regmap.h> |
21 | #include <linux/stddef.h> |
22 | #include <linux/spi/altera.h> |
23 | #include <linux/spi/spi.h> |
24 | #include <linux/types.h> |
25 | |
26 | /* |
27 | * N3000 Nios private feature registers, named as NIOS_SPI_XX on spec. |
28 | * NS is the abbreviation of NIOS_SPI. |
29 | */ |
30 | #define N3000_NS_PARAM 0x8 |
31 | #define N3000_NS_PARAM_SHIFT_MODE_MSK BIT_ULL(1) |
32 | #define N3000_NS_PARAM_SHIFT_MODE_MSB 0 |
33 | #define N3000_NS_PARAM_SHIFT_MODE_LSB 1 |
34 | #define N3000_NS_PARAM_DATA_WIDTH GENMASK_ULL(7, 2) |
35 | #define N3000_NS_PARAM_NUM_CS GENMASK_ULL(13, 8) |
36 | #define N3000_NS_PARAM_CLK_POL BIT_ULL(14) |
37 | #define N3000_NS_PARAM_CLK_PHASE BIT_ULL(15) |
38 | #define N3000_NS_PARAM_PERIPHERAL_ID GENMASK_ULL(47, 32) |
39 | |
40 | #define N3000_NS_CTRL 0x10 |
41 | #define N3000_NS_CTRL_WR_DATA GENMASK_ULL(31, 0) |
42 | #define N3000_NS_CTRL_ADDR GENMASK_ULL(44, 32) |
43 | #define N3000_NS_CTRL_CMD_MSK GENMASK_ULL(63, 62) |
44 | #define N3000_NS_CTRL_CMD_NOP 0 |
45 | #define N3000_NS_CTRL_CMD_RD 1 |
46 | #define N3000_NS_CTRL_CMD_WR 2 |
47 | |
48 | #define N3000_NS_STAT 0x18 |
49 | #define N3000_NS_STAT_RD_DATA GENMASK_ULL(31, 0) |
50 | #define N3000_NS_STAT_RW_VAL BIT_ULL(32) |
51 | |
52 | /* Nios handshake registers, indirect access */ |
53 | #define N3000_NIOS_INIT 0x1000 |
54 | #define N3000_NIOS_INIT_DONE BIT(0) |
55 | #define N3000_NIOS_INIT_START BIT(1) |
56 | /* Mode for retimer A, link 0, the same below */ |
57 | #define N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK GENMASK(9, 8) |
58 | #define N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK GENMASK(11, 10) |
59 | #define N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK GENMASK(13, 12) |
60 | #define N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK GENMASK(15, 14) |
61 | #define N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK GENMASK(17, 16) |
62 | #define N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK GENMASK(19, 18) |
63 | #define N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK GENMASK(21, 20) |
64 | #define N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK GENMASK(23, 22) |
65 | #define N3000_NIOS_INIT_REQ_FEC_MODE_NO 0x0 |
66 | #define N3000_NIOS_INIT_REQ_FEC_MODE_KR 0x1 |
67 | #define N3000_NIOS_INIT_REQ_FEC_MODE_RS 0x2 |
68 | |
69 | #define N3000_NIOS_FW_VERSION 0x1004 |
70 | #define N3000_NIOS_FW_VERSION_PATCH GENMASK(23, 20) |
71 | #define N3000_NIOS_FW_VERSION_MINOR GENMASK(27, 24) |
72 | #define N3000_NIOS_FW_VERSION_MAJOR GENMASK(31, 28) |
73 | |
74 | /* The retimers we use on Intel PAC N3000 is Parkvale, abbreviated to PKVL */ |
75 | #define N3000_NIOS_PKVL_A_MODE_STS 0x1020 |
76 | #define N3000_NIOS_PKVL_B_MODE_STS 0x1024 |
77 | #define N3000_NIOS_PKVL_MODE_STS_GROUP_MSK GENMASK(15, 8) |
78 | #define N3000_NIOS_PKVL_MODE_STS_GROUP_OK 0x0 |
79 | #define N3000_NIOS_PKVL_MODE_STS_ID_MSK GENMASK(7, 0) |
80 | /* When GROUP MASK field == GROUP_OK */ |
81 | #define N3000_NIOS_PKVL_MODE_ID_RESET 0x0 |
82 | #define N3000_NIOS_PKVL_MODE_ID_4X10G 0x1 |
83 | #define N3000_NIOS_PKVL_MODE_ID_4X25G 0x2 |
84 | #define N3000_NIOS_PKVL_MODE_ID_2X25G 0x3 |
85 | #define N3000_NIOS_PKVL_MODE_ID_2X25G_2X10G 0x4 |
86 | #define N3000_NIOS_PKVL_MODE_ID_1X25G 0x5 |
87 | |
88 | #define N3000_NIOS_REGBUS_RETRY_COUNT 10000 /* loop count */ |
89 | |
90 | #define N3000_NIOS_INIT_TIMEOUT 10000000 /* usec */ |
91 | #define N3000_NIOS_INIT_TIME_INTV 100000 /* usec */ |
92 | |
93 | #define N3000_NIOS_INIT_REQ_FEC_MODE_MSK_ALL \ |
94 | (N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK | \ |
95 | N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK | \ |
96 | N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK | \ |
97 | N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK | \ |
98 | N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK | \ |
99 | N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK | \ |
100 | N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK | \ |
101 | N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK) |
102 | |
103 | #define N3000_NIOS_INIT_REQ_FEC_MODE_NO_ALL \ |
104 | (FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK, \ |
105 | N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ |
106 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK, \ |
107 | N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ |
108 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK, \ |
109 | N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ |
110 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK, \ |
111 | N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ |
112 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK, \ |
113 | N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ |
114 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK, \ |
115 | N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ |
116 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK, \ |
117 | N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ |
118 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK, \ |
119 | N3000_NIOS_INIT_REQ_FEC_MODE_NO)) |
120 | |
121 | #define N3000_NIOS_INIT_REQ_FEC_MODE_KR_ALL \ |
122 | (FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK, \ |
123 | N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ |
124 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK, \ |
125 | N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ |
126 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK, \ |
127 | N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ |
128 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK, \ |
129 | N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ |
130 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK, \ |
131 | N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ |
132 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK, \ |
133 | N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ |
134 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK, \ |
135 | N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ |
136 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK, \ |
137 | N3000_NIOS_INIT_REQ_FEC_MODE_KR)) |
138 | |
139 | #define N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL \ |
140 | (FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK, \ |
141 | N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ |
142 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK, \ |
143 | N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ |
144 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK, \ |
145 | N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ |
146 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK, \ |
147 | N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ |
148 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK, \ |
149 | N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ |
150 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK, \ |
151 | N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ |
152 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK, \ |
153 | N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ |
154 | FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK, \ |
155 | N3000_NIOS_INIT_REQ_FEC_MODE_RS)) |
156 | |
157 | struct n3000_nios { |
158 | void __iomem *base; |
159 | struct regmap *regmap; |
160 | struct device *dev; |
161 | struct platform_device *altera_spi; |
162 | }; |
163 | |
164 | static ssize_t nios_fw_version_show(struct device *dev, |
165 | struct device_attribute *attr, char *buf) |
166 | { |
167 | struct n3000_nios *nn = dev_get_drvdata(dev); |
168 | unsigned int val; |
169 | int ret; |
170 | |
171 | ret = regmap_read(map: nn->regmap, N3000_NIOS_FW_VERSION, val: &val); |
172 | if (ret) |
173 | return ret; |
174 | |
175 | return sysfs_emit(buf, fmt: "%x.%x.%x\n" , |
176 | (u8)FIELD_GET(N3000_NIOS_FW_VERSION_MAJOR, val), |
177 | (u8)FIELD_GET(N3000_NIOS_FW_VERSION_MINOR, val), |
178 | (u8)FIELD_GET(N3000_NIOS_FW_VERSION_PATCH, val)); |
179 | } |
180 | static DEVICE_ATTR_RO(nios_fw_version); |
181 | |
182 | #define IS_MODE_STATUS_OK(mode_stat) \ |
183 | (FIELD_GET(N3000_NIOS_PKVL_MODE_STS_GROUP_MSK, (mode_stat)) == \ |
184 | N3000_NIOS_PKVL_MODE_STS_GROUP_OK) |
185 | |
186 | #define IS_RETIMER_FEC_SUPPORTED(retimer_mode) \ |
187 | ((retimer_mode) != N3000_NIOS_PKVL_MODE_ID_RESET && \ |
188 | (retimer_mode) != N3000_NIOS_PKVL_MODE_ID_4X10G) |
189 | |
190 | static int get_retimer_mode(struct n3000_nios *nn, unsigned int mode_stat_reg, |
191 | unsigned int *retimer_mode) |
192 | { |
193 | unsigned int val; |
194 | int ret; |
195 | |
196 | ret = regmap_read(map: nn->regmap, reg: mode_stat_reg, val: &val); |
197 | if (ret) |
198 | return ret; |
199 | |
200 | if (!IS_MODE_STATUS_OK(val)) |
201 | return -EFAULT; |
202 | |
203 | *retimer_mode = FIELD_GET(N3000_NIOS_PKVL_MODE_STS_ID_MSK, val); |
204 | |
205 | return 0; |
206 | } |
207 | |
208 | static ssize_t retimer_A_mode_show(struct device *dev, |
209 | struct device_attribute *attr, char *buf) |
210 | { |
211 | struct n3000_nios *nn = dev_get_drvdata(dev); |
212 | unsigned int mode; |
213 | int ret; |
214 | |
215 | ret = get_retimer_mode(nn, N3000_NIOS_PKVL_A_MODE_STS, retimer_mode: &mode); |
216 | if (ret) |
217 | return ret; |
218 | |
219 | return sysfs_emit(buf, fmt: "0x%x\n" , mode); |
220 | } |
221 | static DEVICE_ATTR_RO(retimer_A_mode); |
222 | |
223 | static ssize_t retimer_B_mode_show(struct device *dev, |
224 | struct device_attribute *attr, char *buf) |
225 | { |
226 | struct n3000_nios *nn = dev_get_drvdata(dev); |
227 | unsigned int mode; |
228 | int ret; |
229 | |
230 | ret = get_retimer_mode(nn, N3000_NIOS_PKVL_B_MODE_STS, retimer_mode: &mode); |
231 | if (ret) |
232 | return ret; |
233 | |
234 | return sysfs_emit(buf, fmt: "0x%x\n" , mode); |
235 | } |
236 | static DEVICE_ATTR_RO(retimer_B_mode); |
237 | |
238 | static ssize_t fec_mode_show(struct device *dev, |
239 | struct device_attribute *attr, char *buf) |
240 | { |
241 | unsigned int val, retimer_a_mode, retimer_b_mode, fec_modes; |
242 | struct n3000_nios *nn = dev_get_drvdata(dev); |
243 | int ret; |
244 | |
245 | /* FEC mode setting is not supported in early FW versions */ |
246 | ret = regmap_read(map: nn->regmap, N3000_NIOS_FW_VERSION, val: &val); |
247 | if (ret) |
248 | return ret; |
249 | |
250 | if (FIELD_GET(N3000_NIOS_FW_VERSION_MAJOR, val) < 3) |
251 | return sysfs_emit(buf, fmt: "not supported\n" ); |
252 | |
253 | /* If no 25G links, FEC mode setting is not supported either */ |
254 | ret = get_retimer_mode(nn, N3000_NIOS_PKVL_A_MODE_STS, retimer_mode: &retimer_a_mode); |
255 | if (ret) |
256 | return ret; |
257 | |
258 | ret = get_retimer_mode(nn, N3000_NIOS_PKVL_B_MODE_STS, retimer_mode: &retimer_b_mode); |
259 | if (ret) |
260 | return ret; |
261 | |
262 | if (!IS_RETIMER_FEC_SUPPORTED(retimer_a_mode) && |
263 | !IS_RETIMER_FEC_SUPPORTED(retimer_b_mode)) |
264 | return sysfs_emit(buf, fmt: "not supported\n" ); |
265 | |
266 | /* get the valid FEC mode for 25G links */ |
267 | ret = regmap_read(map: nn->regmap, N3000_NIOS_INIT, val: &val); |
268 | if (ret) |
269 | return ret; |
270 | |
271 | /* |
272 | * FEC mode should always be the same for all links, as we set them |
273 | * in this way. |
274 | */ |
275 | fec_modes = (val & N3000_NIOS_INIT_REQ_FEC_MODE_MSK_ALL); |
276 | if (fec_modes == N3000_NIOS_INIT_REQ_FEC_MODE_NO_ALL) |
277 | return sysfs_emit(buf, fmt: "no\n" ); |
278 | else if (fec_modes == N3000_NIOS_INIT_REQ_FEC_MODE_KR_ALL) |
279 | return sysfs_emit(buf, fmt: "kr\n" ); |
280 | else if (fec_modes == N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL) |
281 | return sysfs_emit(buf, fmt: "rs\n" ); |
282 | |
283 | return -EFAULT; |
284 | } |
285 | static DEVICE_ATTR_RO(fec_mode); |
286 | |
287 | static struct attribute *n3000_nios_attrs[] = { |
288 | &dev_attr_nios_fw_version.attr, |
289 | &dev_attr_retimer_A_mode.attr, |
290 | &dev_attr_retimer_B_mode.attr, |
291 | &dev_attr_fec_mode.attr, |
292 | NULL, |
293 | }; |
294 | ATTRIBUTE_GROUPS(n3000_nios); |
295 | |
296 | static int n3000_nios_init_done_check(struct n3000_nios *nn) |
297 | { |
298 | unsigned int val, state_a, state_b; |
299 | struct device *dev = nn->dev; |
300 | int ret, ret2; |
301 | |
302 | /* |
303 | * The SPI is shared by the Nios core inside the FPGA, Nios will use |
304 | * this SPI master to do some one time initialization after power up, |
305 | * and then release the control to OS. The driver needs to poll on |
306 | * INIT_DONE to see when driver could take the control. |
307 | * |
308 | * Please note that after Nios firmware version 3.0.0, INIT_START is |
309 | * introduced, so driver needs to trigger START firstly and then check |
310 | * INIT_DONE. |
311 | */ |
312 | |
313 | ret = regmap_read(map: nn->regmap, N3000_NIOS_FW_VERSION, val: &val); |
314 | if (ret) |
315 | return ret; |
316 | |
317 | /* |
318 | * If Nios version register is totally uninitialized(== 0x0), then the |
319 | * Nios firmware is missing. So host could take control of SPI master |
320 | * safely, but initialization work for Nios is not done. To restore the |
321 | * card, we need to reprogram a new Nios firmware via the BMC chip on |
322 | * SPI bus. So the driver doesn't error out, it continues to create the |
323 | * spi controller device and spi_board_info for BMC. |
324 | */ |
325 | if (val == 0) { |
326 | dev_err(dev, "Nios version reg = 0x%x, skip INIT_DONE check, but the retimer may be uninitialized\n" , |
327 | val); |
328 | return 0; |
329 | } |
330 | |
331 | if (FIELD_GET(N3000_NIOS_FW_VERSION_MAJOR, val) >= 3) { |
332 | /* read NIOS_INIT to check if retimer initialization is done */ |
333 | ret = regmap_read(map: nn->regmap, N3000_NIOS_INIT, val: &val); |
334 | if (ret) |
335 | return ret; |
336 | |
337 | /* check if retimers are initialized already */ |
338 | if (val & (N3000_NIOS_INIT_DONE | N3000_NIOS_INIT_START)) |
339 | goto nios_init_done; |
340 | |
341 | /* configure FEC mode per module param */ |
342 | val = N3000_NIOS_INIT_START; |
343 | |
344 | /* |
345 | * When the retimer is to be set to 10G mode, there is no FEC |
346 | * mode setting, so the REQ_FEC_MODE field will be ignored by |
347 | * Nios firmware in this case. But we should still fill the FEC |
348 | * mode field cause host could not get the retimer working mode |
349 | * until the Nios init is done. |
350 | * |
351 | * For now the driver doesn't support the retimer FEC mode |
352 | * switching per user's request. It is always set to Reed |
353 | * Solomon FEC. |
354 | * |
355 | * The driver will set the same FEC mode for all links. |
356 | */ |
357 | val |= N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL; |
358 | |
359 | ret = regmap_write(map: nn->regmap, N3000_NIOS_INIT, val); |
360 | if (ret) |
361 | return ret; |
362 | } |
363 | |
364 | nios_init_done: |
365 | /* polls on NIOS_INIT_DONE */ |
366 | ret = regmap_read_poll_timeout(nn->regmap, N3000_NIOS_INIT, val, |
367 | val & N3000_NIOS_INIT_DONE, |
368 | N3000_NIOS_INIT_TIME_INTV, |
369 | N3000_NIOS_INIT_TIMEOUT); |
370 | if (ret) |
371 | dev_err(dev, "NIOS_INIT_DONE %s\n" , |
372 | (ret == -ETIMEDOUT) ? "timed out" : "check error" ); |
373 | |
374 | ret2 = regmap_read(map: nn->regmap, N3000_NIOS_PKVL_A_MODE_STS, val: &state_a); |
375 | if (ret2) |
376 | return ret2; |
377 | |
378 | ret2 = regmap_read(map: nn->regmap, N3000_NIOS_PKVL_B_MODE_STS, val: &state_b); |
379 | if (ret2) |
380 | return ret2; |
381 | |
382 | if (!ret) { |
383 | /* |
384 | * After INIT_DONE is detected, it still needs to check if the |
385 | * Nios firmware reports any error during the retimer |
386 | * configuration. |
387 | */ |
388 | if (IS_MODE_STATUS_OK(state_a) && IS_MODE_STATUS_OK(state_b)) |
389 | return 0; |
390 | |
391 | /* |
392 | * If the retimer configuration is failed, the Nios firmware |
393 | * will still release the spi controller for host to |
394 | * communicate with the BMC. It makes possible for people to |
395 | * reprogram a new Nios firmware and restore the card. So the |
396 | * driver doesn't error out, it continues to create the spi |
397 | * controller device and spi_board_info for BMC. |
398 | */ |
399 | dev_err(dev, "NIOS_INIT_DONE OK, but err on retimer init\n" ); |
400 | } |
401 | |
402 | dev_err(nn->dev, "PKVL_A_MODE_STS 0x%x\n" , state_a); |
403 | dev_err(nn->dev, "PKVL_B_MODE_STS 0x%x\n" , state_b); |
404 | |
405 | return ret; |
406 | } |
407 | |
408 | static struct spi_board_info m10_n3000_info = { |
409 | .modalias = "m10-n3000" , |
410 | .max_speed_hz = 12500000, |
411 | .bus_num = 0, |
412 | .chip_select = 0, |
413 | }; |
414 | |
415 | static int create_altera_spi_controller(struct n3000_nios *nn) |
416 | { |
417 | struct altera_spi_platform_data pdata = { 0 }; |
418 | struct platform_device_info pdevinfo = { 0 }; |
419 | void __iomem *base = nn->base; |
420 | u64 v; |
421 | |
422 | v = readq(addr: base + N3000_NS_PARAM); |
423 | |
424 | pdata.mode_bits = SPI_CS_HIGH; |
425 | if (FIELD_GET(N3000_NS_PARAM_CLK_POL, v)) |
426 | pdata.mode_bits |= SPI_CPOL; |
427 | if (FIELD_GET(N3000_NS_PARAM_CLK_PHASE, v)) |
428 | pdata.mode_bits |= SPI_CPHA; |
429 | |
430 | pdata.num_chipselect = FIELD_GET(N3000_NS_PARAM_NUM_CS, v); |
431 | pdata.bits_per_word_mask = |
432 | SPI_BPW_RANGE_MASK(1, FIELD_GET(N3000_NS_PARAM_DATA_WIDTH, v)); |
433 | |
434 | pdata.num_devices = 1; |
435 | pdata.devices = &m10_n3000_info; |
436 | |
437 | dev_dbg(nn->dev, "%s cs %u bpm 0x%x mode 0x%x\n" , __func__, |
438 | pdata.num_chipselect, pdata.bits_per_word_mask, |
439 | pdata.mode_bits); |
440 | |
441 | pdevinfo.name = "subdev_spi_altera" ; |
442 | pdevinfo.id = PLATFORM_DEVID_AUTO; |
443 | pdevinfo.parent = nn->dev; |
444 | pdevinfo.data = &pdata; |
445 | pdevinfo.size_data = sizeof(pdata); |
446 | |
447 | nn->altera_spi = platform_device_register_full(pdevinfo: &pdevinfo); |
448 | return PTR_ERR_OR_ZERO(ptr: nn->altera_spi); |
449 | } |
450 | |
451 | static void destroy_altera_spi_controller(struct n3000_nios *nn) |
452 | { |
453 | platform_device_unregister(nn->altera_spi); |
454 | } |
455 | |
456 | static int n3000_nios_poll_stat_timeout(void __iomem *base, u64 *v) |
457 | { |
458 | int loops; |
459 | |
460 | /* |
461 | * We don't use the time based timeout here for performance. |
462 | * |
463 | * The regbus read/write is on the critical path of Intel PAC N3000 |
464 | * image programming. The time based timeout checking will add too much |
465 | * overhead on it. Usually the state changes in 1 or 2 loops on the |
466 | * test server, and we set 10000 times loop here for safety. |
467 | */ |
468 | for (loops = N3000_NIOS_REGBUS_RETRY_COUNT; loops > 0 ; loops--) { |
469 | *v = readq(addr: base + N3000_NS_STAT); |
470 | if (*v & N3000_NS_STAT_RW_VAL) |
471 | break; |
472 | cpu_relax(); |
473 | } |
474 | |
475 | return (loops > 0) ? 0 : -ETIMEDOUT; |
476 | } |
477 | |
478 | static int n3000_nios_reg_write(void *context, unsigned int reg, unsigned int val) |
479 | { |
480 | struct n3000_nios *nn = context; |
481 | u64 v; |
482 | int ret; |
483 | |
484 | v = FIELD_PREP(N3000_NS_CTRL_CMD_MSK, N3000_NS_CTRL_CMD_WR) | |
485 | FIELD_PREP(N3000_NS_CTRL_ADDR, reg) | |
486 | FIELD_PREP(N3000_NS_CTRL_WR_DATA, val); |
487 | writeq(val: v, addr: nn->base + N3000_NS_CTRL); |
488 | |
489 | ret = n3000_nios_poll_stat_timeout(base: nn->base, v: &v); |
490 | if (ret) |
491 | dev_err(nn->dev, "fail to write reg 0x%x val 0x%x: %d\n" , |
492 | reg, val, ret); |
493 | |
494 | return ret; |
495 | } |
496 | |
497 | static int n3000_nios_reg_read(void *context, unsigned int reg, unsigned int *val) |
498 | { |
499 | struct n3000_nios *nn = context; |
500 | u64 v; |
501 | int ret; |
502 | |
503 | v = FIELD_PREP(N3000_NS_CTRL_CMD_MSK, N3000_NS_CTRL_CMD_RD) | |
504 | FIELD_PREP(N3000_NS_CTRL_ADDR, reg); |
505 | writeq(val: v, addr: nn->base + N3000_NS_CTRL); |
506 | |
507 | ret = n3000_nios_poll_stat_timeout(base: nn->base, v: &v); |
508 | if (ret) |
509 | dev_err(nn->dev, "fail to read reg 0x%x: %d\n" , reg, ret); |
510 | else |
511 | *val = FIELD_GET(N3000_NS_STAT_RD_DATA, v); |
512 | |
513 | return ret; |
514 | } |
515 | |
516 | static const struct regmap_config n3000_nios_regbus_cfg = { |
517 | .reg_bits = 32, |
518 | .reg_stride = 4, |
519 | .val_bits = 32, |
520 | .fast_io = true, |
521 | |
522 | .reg_write = n3000_nios_reg_write, |
523 | .reg_read = n3000_nios_reg_read, |
524 | }; |
525 | |
526 | static int n3000_nios_probe(struct dfl_device *ddev) |
527 | { |
528 | struct device *dev = &ddev->dev; |
529 | struct n3000_nios *nn; |
530 | int ret; |
531 | |
532 | nn = devm_kzalloc(dev, size: sizeof(*nn), GFP_KERNEL); |
533 | if (!nn) |
534 | return -ENOMEM; |
535 | |
536 | dev_set_drvdata(dev: &ddev->dev, data: nn); |
537 | |
538 | nn->dev = dev; |
539 | |
540 | nn->base = devm_ioremap_resource(dev: &ddev->dev, res: &ddev->mmio_res); |
541 | if (IS_ERR(ptr: nn->base)) |
542 | return PTR_ERR(ptr: nn->base); |
543 | |
544 | nn->regmap = devm_regmap_init(dev, NULL, nn, &n3000_nios_regbus_cfg); |
545 | if (IS_ERR(ptr: nn->regmap)) |
546 | return PTR_ERR(ptr: nn->regmap); |
547 | |
548 | ret = n3000_nios_init_done_check(nn); |
549 | if (ret) |
550 | return ret; |
551 | |
552 | ret = create_altera_spi_controller(nn); |
553 | if (ret) |
554 | dev_err(dev, "altera spi controller create failed: %d\n" , ret); |
555 | |
556 | return ret; |
557 | } |
558 | |
559 | static void n3000_nios_remove(struct dfl_device *ddev) |
560 | { |
561 | struct n3000_nios *nn = dev_get_drvdata(dev: &ddev->dev); |
562 | |
563 | destroy_altera_spi_controller(nn); |
564 | } |
565 | |
566 | #define FME_FEATURE_ID_N3000_NIOS 0xd |
567 | |
568 | static const struct dfl_device_id n3000_nios_ids[] = { |
569 | { FME_ID, FME_FEATURE_ID_N3000_NIOS }, |
570 | { } |
571 | }; |
572 | MODULE_DEVICE_TABLE(dfl, n3000_nios_ids); |
573 | |
574 | static struct dfl_driver n3000_nios_driver = { |
575 | .drv = { |
576 | .name = "dfl-n3000-nios" , |
577 | .dev_groups = n3000_nios_groups, |
578 | }, |
579 | .id_table = n3000_nios_ids, |
580 | .probe = n3000_nios_probe, |
581 | .remove = n3000_nios_remove, |
582 | }; |
583 | |
584 | module_dfl_driver(n3000_nios_driver); |
585 | |
586 | MODULE_DESCRIPTION("Driver for Nios private feature on Intel PAC N3000" ); |
587 | MODULE_AUTHOR("Intel Corporation" ); |
588 | MODULE_LICENSE("GPL v2" ); |
589 | |