305baba8d4c97dfb9d0f63ecf30edbadbc301199
[dpdk.git] / drivers / raw / ifpga / base / opae_intel_max10.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2019 Intel Corporation
3  */
4
5 #include "opae_intel_max10.h"
6 #include <libfdt.h>
7
8 static struct intel_max10_device *g_max10;
9
10 int max10_reg_read(unsigned int reg, unsigned int *val)
11 {
12         if (!g_max10)
13                 return -ENODEV;
14
15         return spi_transaction_read(g_max10->spi_tran_dev,
16                         reg, 4, (unsigned char *)val);
17 }
18
19 int max10_reg_write(unsigned int reg, unsigned int val)
20 {
21         unsigned int tmp = val;
22
23         if (!g_max10)
24                 return -ENODEV;
25
26         return spi_transaction_write(g_max10->spi_tran_dev,
27                         reg, 4, (unsigned char *)&tmp);
28 }
29
30 static struct max10_compatible_id max10_id_table[] = {
31         {.compatible = MAX10_PAC,},
32         {.compatible = MAX10_PAC_N3000,},
33         {.compatible = MAX10_PAC_END,}
34 };
35
36 static struct max10_compatible_id *max10_match_compatible(const char *fdt_root)
37 {
38         struct max10_compatible_id *id = max10_id_table;
39
40         for (; strcmp(id->compatible, MAX10_PAC_END); id++) {
41                 if (fdt_node_check_compatible(fdt_root, 0, id->compatible))
42                         continue;
43
44                 return id;
45         }
46
47         return NULL;
48 }
49
50 static inline bool
51 is_max10_pac_n3000(struct intel_max10_device *max10)
52 {
53         return max10->id && !strcmp(max10->id->compatible,
54                         MAX10_PAC_N3000);
55 }
56
57 static void max10_check_capability(struct intel_max10_device *max10)
58 {
59         if (!max10->fdt_root)
60                 return;
61
62         if (is_max10_pac_n3000(max10)) {
63                 max10->flags |= MAX10_FLAGS_NO_I2C2 |
64                                 MAX10_FLAGS_NO_BMCIMG_FLASH;
65                 dev_info(max10, "found %s card\n", max10->id->compatible);
66         }
67 }
68
69 static int altera_nor_flash_read(u32 offset,
70                 void *buffer, u32 len)
71 {
72         int word_len;
73         int i;
74         unsigned int *buf = (unsigned int *)buffer;
75         unsigned int value;
76         int ret;
77
78         if (!buffer || len <= 0)
79                 return -ENODEV;
80
81         word_len = len/4;
82
83         for (i = 0; i < word_len; i++) {
84                 ret = max10_reg_read(offset + i*4,
85                                 &value);
86                 if (ret)
87                         return -EBUSY;
88
89                 *buf++ = value;
90         }
91
92         return 0;
93 }
94
95 static int enable_nor_flash(bool on)
96 {
97         unsigned int val = 0;
98         int ret;
99
100         ret = max10_reg_read(RSU_REG_OFF, &val);
101         if (ret) {
102                 dev_err(NULL "enabling flash error\n");
103                 return ret;
104         }
105
106         if (on)
107                 val |= RSU_ENABLE;
108         else
109                 val &= ~RSU_ENABLE;
110
111         return max10_reg_write(RSU_REG_OFF, val);
112 }
113
114 static int init_max10_device_table(struct intel_max10_device *max10)
115 {
116         struct max10_compatible_id *id;
117         struct fdt_header hdr;
118         char *fdt_root = NULL;
119
120         u32 dt_size, dt_addr, val;
121         int ret;
122
123         ret = max10_reg_read(DT_AVAIL_REG_OFF, &val);
124         if (ret) {
125                 dev_err(max10 "cannot read DT_AVAIL_REG\n");
126                 return ret;
127         }
128
129         if (!(val & DT_AVAIL)) {
130                 dev_err(max10 "DT not available\n");
131                 return -EINVAL;
132         }
133
134         ret = max10_reg_read(DT_BASE_ADDR_REG_OFF, &dt_addr);
135         if (ret) {
136                 dev_info(max10 "cannot get base addr of device table\n");
137                 return ret;
138         }
139
140         ret = enable_nor_flash(true);
141         if (ret) {
142                 dev_err(max10 "fail to enable flash\n");
143                 return ret;
144         }
145
146         ret = altera_nor_flash_read(dt_addr, &hdr, sizeof(hdr));
147         if (ret) {
148                 dev_err(max10 "read fdt header fail\n");
149                 goto done;
150         }
151
152         ret = fdt_check_header(&hdr);
153         if (ret) {
154                 dev_err(max10 "check fdt header fail\n");
155                 goto done;
156         }
157
158         dt_size = fdt_totalsize(&hdr);
159         if (dt_size > DFT_MAX_SIZE) {
160                 dev_err(max10 "invalid device table size\n");
161                 ret = -EINVAL;
162                 goto done;
163         }
164
165         fdt_root = opae_malloc(dt_size);
166         if (!fdt_root) {
167                 ret = -ENOMEM;
168                 goto done;
169         }
170
171         ret = altera_nor_flash_read(dt_addr, fdt_root, dt_size);
172         if (ret) {
173                 dev_err(max10 "cannot read device table\n");
174                 goto done;
175         }
176
177         id = max10_match_compatible(fdt_root);
178         if (!id) {
179                 dev_err(max10 "max10 compatible not found\n");
180                 ret = -ENODEV;
181                 goto done;
182         }
183
184         max10->flags |= MAX10_FLAGS_DEVICE_TABLE;
185
186         max10->id = id;
187         max10->fdt_root = fdt_root;
188
189 done:
190         ret = enable_nor_flash(false);
191
192         if (ret && fdt_root)
193                 opae_free(fdt_root);
194
195         return ret;
196 }
197
198 struct intel_max10_device *
199 intel_max10_device_probe(struct altera_spi_device *spi,
200                 int chipselect)
201 {
202         struct intel_max10_device *dev;
203         int ret;
204         unsigned int val;
205
206         dev = opae_malloc(sizeof(*dev));
207         if (!dev)
208                 return NULL;
209
210         dev->spi_master = spi;
211
212         dev->spi_tran_dev = spi_transaction_init(spi, chipselect);
213         if (!dev->spi_tran_dev) {
214                 dev_err(dev, "%s spi tran init fail\n", __func__);
215                 goto free_dev;
216         }
217
218         /* set the max10 device firstly */
219         g_max10 = dev;
220
221         /* init the MAX10 device table */
222         ret = init_max10_device_table(dev);
223         if (ret) {
224                 dev_err(dev, "init max10 device table fail\n");
225                 goto free_dev;
226         }
227
228         max10_check_capability(dev);
229
230         /* read FPGA loading information */
231         ret = max10_reg_read(FPGA_PAGE_INFO_OFF, &val);
232         if (ret) {
233                 dev_err(dev, "fail to get FPGA loading info\n");
234                 goto spi_tran_fail;
235         }
236         dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
237
238         return dev;
239
240 spi_tran_fail:
241         if (dev->fdt_root)
242                 opae_free(dev->fdt_root);
243         spi_transaction_remove(dev->spi_tran_dev);
244 free_dev:
245         g_max10 = NULL;
246         opae_free(dev);
247
248         return NULL;
249 }
250
251 int intel_max10_device_remove(struct intel_max10_device *dev)
252 {
253         if (!dev)
254                 return 0;
255
256         if (dev->spi_tran_dev)
257                 spi_transaction_remove(dev->spi_tran_dev);
258
259         if (dev->fdt_root)
260                 opae_free(dev->fdt_root);
261
262         g_max10 = NULL;
263         opae_free(dev);
264
265         return 0;
266 }