]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/altera/socfpga/socfpga_a10_manager.c
Merge compiler-rt trunk r300890, and update build glue.
[FreeBSD/FreeBSD.git] / sys / arm / altera / socfpga / socfpga_a10_manager.c
1 /*-
2  * Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 /*
32  * Intel Arria 10 FPGA Manager.
33  * Chapter 4, Arria 10 Hard Processor System Technical Reference Manual.
34  * Chapter A, FPGA Reconfiguration.
35  */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/bus.h>
43 #include <sys/kernel.h>
44 #include <sys/module.h>
45 #include <sys/malloc.h>
46 #include <sys/rman.h>
47 #include <sys/timeet.h>
48 #include <sys/timetc.h>
49 #include <sys/conf.h>
50 #include <sys/uio.h>
51
52 #include <dev/ofw/openfirm.h>
53 #include <dev/ofw/ofw_bus.h>
54 #include <dev/ofw/ofw_bus_subr.h>
55
56 #include <machine/bus.h>
57 #include <machine/cpu.h>
58 #include <machine/intr.h>
59
60 #include <arm/altera/socfpga/socfpga_common.h>
61
62 #define FPGAMGR_DCLKCNT                 0x8     /* DCLK Count Register */
63 #define FPGAMGR_DCLKSTAT                0xC     /* DCLK Status Register */
64 #define FPGAMGR_GPO                     0x10    /* General-Purpose Output Register */
65 #define FPGAMGR_GPI                     0x14    /* General-Purpose Input Register */
66 #define FPGAMGR_MISCI                   0x18    /* Miscellaneous Input Register */
67 #define IMGCFG_CTRL_00                  0x70
68 #define  S2F_CONDONE_OE                 (1 << 24)
69 #define  S2F_NSTATUS_OE                 (1 << 16)
70 #define  CTRL_00_NCONFIG                (1 << 8)
71 #define  CTRL_00_NENABLE_CONDONE        (1 << 2)
72 #define  CTRL_00_NENABLE_NSTATUS        (1 << 1)
73 #define  CTRL_00_NENABLE_NCONFIG        (1 << 0)
74 #define IMGCFG_CTRL_01                  0x74
75 #define  CTRL_01_S2F_NCE                (1 << 24)
76 #define  CTRL_01_S2F_PR_REQUEST         (1 << 16)
77 #define  CTRL_01_S2F_NENABLE_CONFIG     (1 << 0)
78 #define IMGCFG_CTRL_02                  0x78
79 #define  CTRL_02_CDRATIO_S              16
80 #define  CTRL_02_CDRATIO_M              (0x3 << CTRL_02_CDRATIO_S)
81 #define  CTRL_02_CFGWIDTH_16            (0 << 24)
82 #define  CTRL_02_CFGWIDTH_32            (1 << 24)
83 #define  CTRL_02_EN_CFG_DATA            (1 << 8)
84 #define  CTRL_02_EN_CFG_CTRL            (1 << 0)
85 #define IMGCFG_STAT                     0x80
86 #define  F2S_PR_ERROR                   (1 << 11)
87 #define  F2S_PR_DONE                    (1 << 10)
88 #define  F2S_PR_READY                   (1 << 9)
89 #define  F2S_MSEL_S                     16
90 #define  F2S_MSEL_M                     (0x7 << F2S_MSEL_S)
91 #define  MSEL_PASSIVE_FAST              0
92 #define  MSEL_PASSIVE_SLOW              1
93 #define  F2S_NCONFIG_PIN                (1 << 12)
94 #define  F2S_CONDONE_OE                 (1 << 7)
95 #define  F2S_NSTATUS_PIN                (1 << 4)
96 #define  F2S_CONDONE_PIN                (1 << 6)
97 #define  F2S_USERMODE                   (1 << 2)
98
99 struct fpgamgr_a10_softc {
100         struct resource         *res[2];
101         bus_space_tag_t         bst_data;
102         bus_space_handle_t      bsh_data;
103         struct cdev             *mgr_cdev;
104         device_t                dev;
105 };
106
107 static struct resource_spec fpgamgr_a10_spec[] = {
108         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
109         { SYS_RES_MEMORY,       1,      RF_ACTIVE },
110         { -1, 0 }
111 };
112
113 static int
114 fpga_wait_dclk_pulses(struct fpgamgr_a10_softc *sc, int npulses)
115 {
116         int tout;
117
118         /* Clear done bit, if any */
119         if (READ4(sc, FPGAMGR_DCLKSTAT) != 0)
120                 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
121
122         /* Request DCLK pulses */
123         WRITE4(sc, FPGAMGR_DCLKCNT, npulses);
124
125         /* Wait finish */
126         tout = 1000;
127         while (tout > 0) {
128                 if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) {
129                         WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
130                         break;
131                 }
132                 tout--;
133                 DELAY(10);
134         }
135         if (tout == 0) {
136                 device_printf(sc->dev,
137                     "Error: dclkpulses wait timeout\n");
138                 return (1);
139         }
140
141         return (0);
142 }
143
144
145 static int
146 fpga_open(struct cdev *dev, int flags __unused,
147     int fmt __unused, struct thread *td __unused)
148 {
149         struct fpgamgr_a10_softc *sc;
150         int tout;
151         int msel;
152         int reg;
153
154         sc = dev->si_drv1;
155
156         /* Step 1 */
157         reg = READ4(sc, IMGCFG_STAT);
158         if ((reg & F2S_USERMODE) == 0) {
159                 device_printf(sc->dev, "Error: invalid mode\n");
160                 return (ENXIO);
161         };
162
163         /* Step 2 */
164         reg = READ4(sc, IMGCFG_STAT);
165         msel = (reg & F2S_MSEL_M) >> F2S_MSEL_S;
166         if ((msel != MSEL_PASSIVE_FAST) && \
167             (msel != MSEL_PASSIVE_SLOW)) {
168                 device_printf(sc->dev,
169                     "Error: invalid msel %d\n", msel);
170                 return (ENXIO);
171         };
172
173         /*
174          * Step 3.
175          * TODO: add support for compressed, encrypted images.
176          */
177         reg = READ4(sc, IMGCFG_CTRL_02);
178         reg &= ~(CTRL_02_CDRATIO_M);
179         WRITE4(sc, IMGCFG_CTRL_02, reg);
180
181         reg = READ4(sc, IMGCFG_CTRL_02);
182         reg &= ~CTRL_02_CFGWIDTH_32;
183         WRITE4(sc, IMGCFG_CTRL_02, reg);
184
185         /* Step 4. a */
186         reg = READ4(sc, IMGCFG_CTRL_01);
187         reg &= ~CTRL_01_S2F_PR_REQUEST;
188         WRITE4(sc, IMGCFG_CTRL_01, reg);
189
190         reg = READ4(sc, IMGCFG_CTRL_00);
191         reg |= CTRL_00_NCONFIG;
192         WRITE4(sc, IMGCFG_CTRL_00, reg);
193
194         /* b */
195         reg = READ4(sc, IMGCFG_CTRL_01);
196         reg &= ~CTRL_01_S2F_NCE;
197         WRITE4(sc, IMGCFG_CTRL_01, reg);
198
199         /* c */
200         reg = READ4(sc, IMGCFG_CTRL_02);
201         reg |= CTRL_02_EN_CFG_CTRL;
202         WRITE4(sc, IMGCFG_CTRL_02, reg);
203
204         /* d */
205         reg = READ4(sc, IMGCFG_CTRL_00);
206         reg &= ~S2F_CONDONE_OE;
207         reg &= ~S2F_NSTATUS_OE;
208         reg |= CTRL_00_NCONFIG;
209         reg |= CTRL_00_NENABLE_NSTATUS;
210         reg |= CTRL_00_NENABLE_CONDONE;
211         reg &= ~CTRL_00_NENABLE_NCONFIG;
212         WRITE4(sc, IMGCFG_CTRL_00, reg);
213
214         /* Step 5 */
215         reg = READ4(sc, IMGCFG_CTRL_01);
216         reg &= ~CTRL_01_S2F_NENABLE_CONFIG;
217         WRITE4(sc, IMGCFG_CTRL_01, reg);
218
219         /* Step 6 */
220         fpga_wait_dclk_pulses(sc, 0x100);
221
222         /* Step 7. a */
223         reg = READ4(sc, IMGCFG_CTRL_01);
224         reg |= CTRL_01_S2F_PR_REQUEST;
225         WRITE4(sc, IMGCFG_CTRL_01, reg);
226
227         /* b, c */
228         fpga_wait_dclk_pulses(sc, 0x7ff);
229
230         /* Step 8 */
231         tout = 10;
232         while (tout--) {
233                 reg = READ4(sc, IMGCFG_STAT);
234                 if (reg & F2S_PR_ERROR) {
235                         device_printf(sc->dev,
236                             "Error: PR failed on open.\n");
237                         return (ENXIO);
238                 }
239                 if (reg & F2S_PR_READY) {
240                         break;
241                 }
242         }
243         if (tout == 0) {
244                 device_printf(sc->dev,
245                     "Error: Timeout waiting PR ready bit.\n");
246                 return (ENXIO);
247         }
248
249         return (0);
250 }
251
252 static int
253 fpga_close(struct cdev *dev, int flags __unused,
254     int fmt __unused, struct thread *td __unused)
255 {
256         struct fpgamgr_a10_softc *sc;
257         int tout;
258         int reg;
259
260         sc = dev->si_drv1;
261
262         /* Step 10 */
263         tout = 10;
264         while (tout--) {
265                 reg = READ4(sc, IMGCFG_STAT);
266                 if (reg & F2S_PR_ERROR) {
267                         device_printf(sc->dev,
268                             "Error: PR failed.\n");
269                         return (ENXIO);
270                 }
271                 if (reg & F2S_PR_DONE) {
272                         break;
273                 }
274         }
275
276         /* Step 11 */
277         reg = READ4(sc, IMGCFG_CTRL_01);
278         reg &= ~CTRL_01_S2F_PR_REQUEST;
279         WRITE4(sc, IMGCFG_CTRL_01, reg);
280
281         /* Step 12, 13 */
282         fpga_wait_dclk_pulses(sc, 0x100);
283
284         /* Step 14 */
285         reg = READ4(sc, IMGCFG_CTRL_02);
286         reg &= ~CTRL_02_EN_CFG_CTRL;
287         WRITE4(sc, IMGCFG_CTRL_02, reg);
288
289         /* Step 15 */
290         reg = READ4(sc, IMGCFG_CTRL_01);
291         reg |= CTRL_01_S2F_NCE;
292         WRITE4(sc, IMGCFG_CTRL_01, reg);
293
294         /* Step 16 */
295         reg = READ4(sc, IMGCFG_CTRL_01);
296         reg |= CTRL_01_S2F_NENABLE_CONFIG;
297         WRITE4(sc, IMGCFG_CTRL_01, reg);
298
299         /* Step 17 */
300         reg = READ4(sc, IMGCFG_STAT);
301         if ((reg & F2S_USERMODE) == 0) {
302                 device_printf(sc->dev,
303                     "Error: invalid mode\n");
304                 return (ENXIO);
305         };
306
307         if ((reg & F2S_CONDONE_PIN) == 0) {
308                 device_printf(sc->dev,
309                     "Error: configuration not done\n");
310                 return (ENXIO);
311         };
312
313         if ((reg & F2S_NSTATUS_PIN) == 0) {
314                 device_printf(sc->dev,
315                     "Error: nstatus pin\n");
316                 return (ENXIO);
317         };
318
319         return (0);
320 }
321
322 static int
323 fpga_write(struct cdev *dev, struct uio *uio, int ioflag)
324 {
325         struct fpgamgr_a10_softc *sc;
326         uint32_t buffer;
327
328         sc = dev->si_drv1;
329
330         /*
331          * Step 9.
332          * Device supports 4-byte writes only.
333          */
334
335         while (uio->uio_resid >= 4) {
336                 uiomove(&buffer, 4, uio);
337                 bus_space_write_4(sc->bst_data, sc->bsh_data,
338                     0x0, buffer);
339         }
340
341         switch (uio->uio_resid) {
342         case 3:
343                 uiomove(&buffer, 3, uio);
344                 buffer &= 0xffffff;
345                 bus_space_write_4(sc->bst_data, sc->bsh_data,
346                     0x0, buffer);
347                 break;
348         case 2:
349                 uiomove(&buffer, 2, uio);
350                 buffer &= 0xffff;
351                 bus_space_write_4(sc->bst_data, sc->bsh_data,
352                     0x0, buffer);
353                 break;
354         case 1:
355                 uiomove(&buffer, 1, uio);
356                 buffer &= 0xff;
357                 bus_space_write_4(sc->bst_data, sc->bsh_data,
358                     0x0, buffer);
359                 break;
360         default:
361                 break;
362         };
363
364         return (0);
365 }
366
367 static int
368 fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
369     struct thread *td)
370 {
371
372         return (0);
373 }
374
375 static struct cdevsw fpga_cdevsw = {
376         .d_version =    D_VERSION,
377         .d_open =       fpga_open,
378         .d_close =      fpga_close,
379         .d_write =      fpga_write,
380         .d_ioctl =      fpga_ioctl,
381         .d_name =       "FPGA Manager",
382 };
383
384 static int
385 fpgamgr_a10_probe(device_t dev)
386 {
387
388         if (!ofw_bus_status_okay(dev))
389                 return (ENXIO);
390
391         if (!ofw_bus_is_compatible(dev, "altr,socfpga-a10-fpga-mgr"))
392                 return (ENXIO);
393
394         device_set_desc(dev, "Arria 10 FPGA Manager");
395
396         return (BUS_PROBE_DEFAULT);
397 }
398
399 static int
400 fpgamgr_a10_attach(device_t dev)
401 {
402         struct fpgamgr_a10_softc *sc;
403
404         sc = device_get_softc(dev);
405         sc->dev = dev;
406
407         if (bus_alloc_resources(dev, fpgamgr_a10_spec, sc->res)) {
408                 device_printf(dev, "Could not allocate resources.\n");
409                 return (ENXIO);
410         }
411
412         /* Memory interface */
413         sc->bst_data = rman_get_bustag(sc->res[1]);
414         sc->bsh_data = rman_get_bushandle(sc->res[1]);
415
416         sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
417             0600, "fpga%d", device_get_unit(sc->dev));
418
419         if (sc->mgr_cdev == NULL) {
420                 device_printf(dev, "Failed to create character device.\n");
421                 return (ENXIO);
422         }
423
424         sc->mgr_cdev->si_drv1 = sc;
425
426         return (0);
427 }
428
429 static device_method_t fpgamgr_a10_methods[] = {
430         DEVMETHOD(device_probe,         fpgamgr_a10_probe),
431         DEVMETHOD(device_attach,        fpgamgr_a10_attach),
432         { 0, 0 }
433 };
434
435 static driver_t fpgamgr_a10_driver = {
436         "fpgamgr_a10",
437         fpgamgr_a10_methods,
438         sizeof(struct fpgamgr_a10_softc),
439 };
440
441 static devclass_t fpgamgr_a10_devclass;
442
443 DRIVER_MODULE(fpgamgr_a10, simplebus, fpgamgr_a10_driver,
444     fpgamgr_a10_devclass, 0, 0);