134a01893SRuslan Bukin /*-
234a01893SRuslan Bukin * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
334a01893SRuslan Bukin * All rights reserved.
434a01893SRuslan Bukin *
534a01893SRuslan Bukin * This software was developed by SRI International and the University of
634a01893SRuslan Bukin * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
734a01893SRuslan Bukin * ("CTSRD"), as part of the DARPA CRASH research programme.
834a01893SRuslan Bukin *
934a01893SRuslan Bukin * Redistribution and use in source and binary forms, with or without
1034a01893SRuslan Bukin * modification, are permitted provided that the following conditions
1134a01893SRuslan Bukin * are met:
1234a01893SRuslan Bukin * 1. Redistributions of source code must retain the above copyright
1334a01893SRuslan Bukin * notice, this list of conditions and the following disclaimer.
1434a01893SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright
1534a01893SRuslan Bukin * notice, this list of conditions and the following disclaimer in the
1634a01893SRuslan Bukin * documentation and/or other materials provided with the distribution.
1734a01893SRuslan Bukin *
1834a01893SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1934a01893SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2034a01893SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2134a01893SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2234a01893SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2334a01893SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2434a01893SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2534a01893SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2634a01893SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2734a01893SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2834a01893SRuslan Bukin * SUCH DAMAGE.
2934a01893SRuslan Bukin */
3034a01893SRuslan Bukin
3134a01893SRuslan Bukin /*
3234a01893SRuslan Bukin * Altera FPGA Manager.
3334a01893SRuslan Bukin * Chapter 4, Cyclone V Device Handbook (CV-5V2 2014.07.22)
3434a01893SRuslan Bukin */
3534a01893SRuslan Bukin
3634a01893SRuslan Bukin #include <sys/param.h>
3734a01893SRuslan Bukin #include <sys/systm.h>
3834a01893SRuslan Bukin #include <sys/bus.h>
3934a01893SRuslan Bukin #include <sys/kernel.h>
4034a01893SRuslan Bukin #include <sys/module.h>
4134a01893SRuslan Bukin #include <sys/malloc.h>
4234a01893SRuslan Bukin #include <sys/rman.h>
4334a01893SRuslan Bukin #include <sys/timeet.h>
4434a01893SRuslan Bukin #include <sys/timetc.h>
4534a01893SRuslan Bukin #include <sys/conf.h>
4634a01893SRuslan Bukin #include <sys/uio.h>
4734a01893SRuslan Bukin
4834a01893SRuslan Bukin #include <dev/ofw/openfirm.h>
4934a01893SRuslan Bukin #include <dev/ofw/ofw_bus.h>
5034a01893SRuslan Bukin #include <dev/ofw/ofw_bus_subr.h>
5134a01893SRuslan Bukin
5234a01893SRuslan Bukin #include <machine/bus.h>
5334a01893SRuslan Bukin #include <machine/cpu.h>
5434a01893SRuslan Bukin #include <machine/intr.h>
5534a01893SRuslan Bukin
5634a01893SRuslan Bukin #include <arm/altera/socfpga/socfpga_common.h>
5734a01893SRuslan Bukin
5834a01893SRuslan Bukin /* FPGA Manager Module Registers */
5934a01893SRuslan Bukin #define FPGAMGR_STAT 0x0 /* Status Register */
6034a01893SRuslan Bukin #define STAT_MSEL_MASK 0x1f
6134a01893SRuslan Bukin #define STAT_MSEL_SHIFT 3
6234a01893SRuslan Bukin #define STAT_MODE_SHIFT 0
6334a01893SRuslan Bukin #define STAT_MODE_MASK 0x7
6434a01893SRuslan Bukin #define FPGAMGR_CTRL 0x4 /* Control Register */
6534a01893SRuslan Bukin #define CTRL_AXICFGEN (1 << 8)
6634a01893SRuslan Bukin #define CTRL_CDRATIO_MASK 0x3
6734a01893SRuslan Bukin #define CTRL_CDRATIO_SHIFT 6
6834a01893SRuslan Bukin #define CTRL_CFGWDTH_MASK 1
6934a01893SRuslan Bukin #define CTRL_CFGWDTH_SHIFT 9
7034a01893SRuslan Bukin #define CTRL_NCONFIGPULL (1 << 2)
7134a01893SRuslan Bukin #define CTRL_NCE (1 << 1)
7234a01893SRuslan Bukin #define CTRL_EN (1 << 0)
7334a01893SRuslan Bukin #define FPGAMGR_DCLKCNT 0x8 /* DCLK Count Register */
7434a01893SRuslan Bukin #define FPGAMGR_DCLKSTAT 0xC /* DCLK Status Register */
7534a01893SRuslan Bukin #define FPGAMGR_GPO 0x10 /* General-Purpose Output Register */
7634a01893SRuslan Bukin #define FPGAMGR_GPI 0x14 /* General-Purpose Input Register */
7734a01893SRuslan Bukin #define FPGAMGR_MISCI 0x18 /* Miscellaneous Input Register */
7834a01893SRuslan Bukin
7934a01893SRuslan Bukin /* Configuration Monitor (MON) Registers */
8034a01893SRuslan Bukin #define GPIO_INTEN 0x830 /* Interrupt Enable Register */
8134a01893SRuslan Bukin #define GPIO_INTMASK 0x834 /* Interrupt Mask Register */
8234a01893SRuslan Bukin #define GPIO_INTTYPE_LEVEL 0x838 /* Interrupt Level Register */
8334a01893SRuslan Bukin #define GPIO_INT_POLARITY 0x83C /* Interrupt Polarity Register */
8434a01893SRuslan Bukin #define GPIO_INTSTATUS 0x840 /* Interrupt Status Register */
8534a01893SRuslan Bukin #define GPIO_RAW_INTSTATUS 0x844 /* Raw Interrupt Status Register */
8634a01893SRuslan Bukin #define GPIO_PORTA_EOI 0x84C /* Clear Interrupt Register */
8734a01893SRuslan Bukin #define PORTA_EOI_NS (1 << 0)
8834a01893SRuslan Bukin #define GPIO_EXT_PORTA 0x850 /* External Port A Register */
898aabb971SRuslan Bukin #define EXT_PORTA_CDP (1 << 10) /* Configuration done */
9034a01893SRuslan Bukin #define GPIO_LS_SYNC 0x860 /* Synchronization Level Register */
9134a01893SRuslan Bukin #define GPIO_VER_ID_CODE 0x86C /* GPIO Version Register */
9234a01893SRuslan Bukin #define GPIO_CONFIG_REG2 0x870 /* Configuration Register 2 */
9334a01893SRuslan Bukin #define GPIO_CONFIG_REG1 0x874 /* Configuration Register 1 */
9434a01893SRuslan Bukin
9534a01893SRuslan Bukin #define MSEL_PP16_FAST_NOAES_NODC 0x0
9634a01893SRuslan Bukin #define MSEL_PP16_FAST_AES_NODC 0x1
9734a01893SRuslan Bukin #define MSEL_PP16_FAST_AESOPT_DC 0x2
9834a01893SRuslan Bukin #define MSEL_PP16_SLOW_NOAES_NODC 0x4
9934a01893SRuslan Bukin #define MSEL_PP16_SLOW_AES_NODC 0x5
10034a01893SRuslan Bukin #define MSEL_PP16_SLOW_AESOPT_DC 0x6
10134a01893SRuslan Bukin #define MSEL_PP32_FAST_NOAES_NODC 0x8
10234a01893SRuslan Bukin #define MSEL_PP32_FAST_AES_NODC 0x9
10334a01893SRuslan Bukin #define MSEL_PP32_FAST_AESOPT_DC 0xa
10434a01893SRuslan Bukin #define MSEL_PP32_SLOW_NOAES_NODC 0xc
10534a01893SRuslan Bukin #define MSEL_PP32_SLOW_AES_NODC 0xd
10634a01893SRuslan Bukin #define MSEL_PP32_SLOW_AESOPT_DC 0xe
10734a01893SRuslan Bukin
10834a01893SRuslan Bukin #define CFGWDTH_16 0
10934a01893SRuslan Bukin #define CFGWDTH_32 1
11034a01893SRuslan Bukin
11134a01893SRuslan Bukin #define CDRATIO_1 0
11234a01893SRuslan Bukin #define CDRATIO_2 1
11334a01893SRuslan Bukin #define CDRATIO_4 2
11434a01893SRuslan Bukin #define CDRATIO_8 3
11534a01893SRuslan Bukin
11634a01893SRuslan Bukin #define FPGAMGR_MODE_POWEROFF 0x0
11734a01893SRuslan Bukin #define FPGAMGR_MODE_RESET 0x1
11834a01893SRuslan Bukin #define FPGAMGR_MODE_CONFIG 0x2
11934a01893SRuslan Bukin #define FPGAMGR_MODE_INIT 0x3
12034a01893SRuslan Bukin #define FPGAMGR_MODE_USER 0x4
12134a01893SRuslan Bukin
12234a01893SRuslan Bukin struct cfgmgr_mode {
12334a01893SRuslan Bukin int msel;
12434a01893SRuslan Bukin int cfgwdth;
12534a01893SRuslan Bukin int cdratio;
12634a01893SRuslan Bukin };
12734a01893SRuslan Bukin
12834a01893SRuslan Bukin static struct cfgmgr_mode cfgmgr_modes[] = {
12934a01893SRuslan Bukin { MSEL_PP16_FAST_NOAES_NODC, CFGWDTH_16, CDRATIO_1 },
13034a01893SRuslan Bukin { MSEL_PP16_FAST_AES_NODC, CFGWDTH_16, CDRATIO_2 },
13134a01893SRuslan Bukin { MSEL_PP16_FAST_AESOPT_DC, CFGWDTH_16, CDRATIO_4 },
13234a01893SRuslan Bukin { MSEL_PP16_SLOW_NOAES_NODC, CFGWDTH_16, CDRATIO_1 },
13334a01893SRuslan Bukin { MSEL_PP16_SLOW_AES_NODC, CFGWDTH_16, CDRATIO_2 },
13434a01893SRuslan Bukin { MSEL_PP16_SLOW_AESOPT_DC, CFGWDTH_16, CDRATIO_4 },
13534a01893SRuslan Bukin { MSEL_PP32_FAST_NOAES_NODC, CFGWDTH_32, CDRATIO_1 },
13634a01893SRuslan Bukin { MSEL_PP32_FAST_AES_NODC, CFGWDTH_32, CDRATIO_4 },
13734a01893SRuslan Bukin { MSEL_PP32_FAST_AESOPT_DC, CFGWDTH_32, CDRATIO_8 },
13834a01893SRuslan Bukin { MSEL_PP32_SLOW_NOAES_NODC, CFGWDTH_32, CDRATIO_1 },
13934a01893SRuslan Bukin { MSEL_PP32_SLOW_AES_NODC, CFGWDTH_32, CDRATIO_4 },
14034a01893SRuslan Bukin { MSEL_PP32_SLOW_AESOPT_DC, CFGWDTH_32, CDRATIO_8 },
14134a01893SRuslan Bukin { -1, -1, -1 },
14234a01893SRuslan Bukin };
14334a01893SRuslan Bukin
14434a01893SRuslan Bukin struct fpgamgr_softc {
14534a01893SRuslan Bukin struct resource *res[3];
14634a01893SRuslan Bukin bus_space_tag_t bst_data;
14734a01893SRuslan Bukin bus_space_handle_t bsh_data;
14834a01893SRuslan Bukin struct cdev *mgr_cdev;
14934a01893SRuslan Bukin device_t dev;
15034a01893SRuslan Bukin };
15134a01893SRuslan Bukin
15234a01893SRuslan Bukin static struct resource_spec fpgamgr_spec[] = {
15334a01893SRuslan Bukin { SYS_RES_MEMORY, 0, RF_ACTIVE },
15434a01893SRuslan Bukin { SYS_RES_MEMORY, 1, RF_ACTIVE },
15534a01893SRuslan Bukin { SYS_RES_IRQ, 0, RF_ACTIVE },
15634a01893SRuslan Bukin { -1, 0 }
15734a01893SRuslan Bukin };
15834a01893SRuslan Bukin
15934a01893SRuslan Bukin static int
fpgamgr_state_get(struct fpgamgr_softc * sc)16034a01893SRuslan Bukin fpgamgr_state_get(struct fpgamgr_softc *sc)
16134a01893SRuslan Bukin {
16234a01893SRuslan Bukin int reg;
16334a01893SRuslan Bukin
16434a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_STAT);
16534a01893SRuslan Bukin reg >>= STAT_MODE_SHIFT;
16634a01893SRuslan Bukin reg &= STAT_MODE_MASK;
16734a01893SRuslan Bukin
16834a01893SRuslan Bukin return reg;
16934a01893SRuslan Bukin }
17034a01893SRuslan Bukin
17134a01893SRuslan Bukin static int
fpgamgr_state_wait(struct fpgamgr_softc * sc,int state)17234a01893SRuslan Bukin fpgamgr_state_wait(struct fpgamgr_softc *sc, int state)
17334a01893SRuslan Bukin {
17434a01893SRuslan Bukin int tout;
17534a01893SRuslan Bukin
17634a01893SRuslan Bukin tout = 1000;
17734a01893SRuslan Bukin while (tout > 0) {
17834a01893SRuslan Bukin if (fpgamgr_state_get(sc) == state)
17934a01893SRuslan Bukin break;
18034a01893SRuslan Bukin tout--;
18134a01893SRuslan Bukin DELAY(10);
18234a01893SRuslan Bukin }
18334a01893SRuslan Bukin if (tout == 0) {
18434a01893SRuslan Bukin return (1);
18534a01893SRuslan Bukin }
18634a01893SRuslan Bukin
18734a01893SRuslan Bukin return (0);
18834a01893SRuslan Bukin }
18934a01893SRuslan Bukin
19034a01893SRuslan Bukin static int
fpga_open(struct cdev * dev,int flags __unused,int fmt __unused,struct thread * td __unused)1918aabb971SRuslan Bukin fpga_open(struct cdev *dev, int flags __unused,
19234a01893SRuslan Bukin int fmt __unused, struct thread *td __unused)
19334a01893SRuslan Bukin {
19434a01893SRuslan Bukin struct fpgamgr_softc *sc;
19534a01893SRuslan Bukin struct cfgmgr_mode *mode;
19634a01893SRuslan Bukin int msel;
19734a01893SRuslan Bukin int reg;
19834a01893SRuslan Bukin int i;
19934a01893SRuslan Bukin
20034a01893SRuslan Bukin sc = dev->si_drv1;
20134a01893SRuslan Bukin
20234a01893SRuslan Bukin msel = READ4(sc, FPGAMGR_STAT);
20334a01893SRuslan Bukin msel >>= STAT_MSEL_SHIFT;
20434a01893SRuslan Bukin msel &= STAT_MSEL_MASK;
20534a01893SRuslan Bukin
20634a01893SRuslan Bukin mode = NULL;
20734a01893SRuslan Bukin for (i = 0; cfgmgr_modes[i].msel != -1; i++) {
20834a01893SRuslan Bukin if (msel == cfgmgr_modes[i].msel) {
20934a01893SRuslan Bukin mode = &cfgmgr_modes[i];
21034a01893SRuslan Bukin break;
21134a01893SRuslan Bukin }
21234a01893SRuslan Bukin }
21334a01893SRuslan Bukin if (mode == NULL) {
21434a01893SRuslan Bukin device_printf(sc->dev, "Can't configure: unknown mode\n");
21534a01893SRuslan Bukin return (ENXIO);
21634a01893SRuslan Bukin }
21734a01893SRuslan Bukin
21834a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_CTRL);
21934a01893SRuslan Bukin reg &= ~(CTRL_CDRATIO_MASK << CTRL_CDRATIO_SHIFT);
22034a01893SRuslan Bukin reg |= (mode->cdratio << CTRL_CDRATIO_SHIFT);
22134a01893SRuslan Bukin reg &= ~(CTRL_CFGWDTH_MASK << CTRL_CFGWDTH_SHIFT);
22234a01893SRuslan Bukin reg |= (mode->cfgwdth << CTRL_CFGWDTH_SHIFT);
22334a01893SRuslan Bukin reg &= ~(CTRL_NCE);
22434a01893SRuslan Bukin WRITE4(sc, FPGAMGR_CTRL, reg);
22534a01893SRuslan Bukin
22634a01893SRuslan Bukin /* Enable configuration */
22734a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_CTRL);
22834a01893SRuslan Bukin reg |= (CTRL_EN);
22934a01893SRuslan Bukin WRITE4(sc, FPGAMGR_CTRL, reg);
23034a01893SRuslan Bukin
23134a01893SRuslan Bukin /* Reset FPGA */
23234a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_CTRL);
23334a01893SRuslan Bukin reg |= (CTRL_NCONFIGPULL);
23434a01893SRuslan Bukin WRITE4(sc, FPGAMGR_CTRL, reg);
23534a01893SRuslan Bukin
23634a01893SRuslan Bukin /* Wait reset state */
23734a01893SRuslan Bukin if (fpgamgr_state_wait(sc, FPGAMGR_MODE_RESET)) {
23834a01893SRuslan Bukin device_printf(sc->dev, "Can't get RESET state\n");
23934a01893SRuslan Bukin return (ENXIO);
24034a01893SRuslan Bukin }
24134a01893SRuslan Bukin
24234a01893SRuslan Bukin /* Release from reset */
24334a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_CTRL);
24434a01893SRuslan Bukin reg &= ~(CTRL_NCONFIGPULL);
24534a01893SRuslan Bukin WRITE4(sc, FPGAMGR_CTRL, reg);
24634a01893SRuslan Bukin
24734a01893SRuslan Bukin if (fpgamgr_state_wait(sc, FPGAMGR_MODE_CONFIG)) {
24834a01893SRuslan Bukin device_printf(sc->dev, "Can't get CONFIG state\n");
24934a01893SRuslan Bukin return (ENXIO);
25034a01893SRuslan Bukin }
25134a01893SRuslan Bukin
25234a01893SRuslan Bukin /* Clear nSTATUS edge interrupt */
25334a01893SRuslan Bukin WRITE4(sc, GPIO_PORTA_EOI, PORTA_EOI_NS);
25434a01893SRuslan Bukin
25534a01893SRuslan Bukin /* Enter configuration state */
25634a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_CTRL);
25734a01893SRuslan Bukin reg |= (CTRL_AXICFGEN);
25834a01893SRuslan Bukin WRITE4(sc, FPGAMGR_CTRL, reg);
25934a01893SRuslan Bukin
26034a01893SRuslan Bukin return (0);
26134a01893SRuslan Bukin }
26234a01893SRuslan Bukin
26334a01893SRuslan Bukin static int
fpga_wait_dclk_pulses(struct fpgamgr_softc * sc,int npulses)26434a01893SRuslan Bukin fpga_wait_dclk_pulses(struct fpgamgr_softc *sc, int npulses)
26534a01893SRuslan Bukin {
26634a01893SRuslan Bukin int tout;
26734a01893SRuslan Bukin
26834a01893SRuslan Bukin /* Clear done bit, if any */
26934a01893SRuslan Bukin if (READ4(sc, FPGAMGR_DCLKSTAT) != 0)
27034a01893SRuslan Bukin WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
27134a01893SRuslan Bukin
27234a01893SRuslan Bukin /* Request DCLK pulses */
27334a01893SRuslan Bukin WRITE4(sc, FPGAMGR_DCLKCNT, npulses);
27434a01893SRuslan Bukin
27534a01893SRuslan Bukin /* Wait finish */
27634a01893SRuslan Bukin tout = 1000;
27734a01893SRuslan Bukin while (tout > 0) {
27834a01893SRuslan Bukin if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) {
27934a01893SRuslan Bukin WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
28034a01893SRuslan Bukin break;
28134a01893SRuslan Bukin }
28234a01893SRuslan Bukin tout--;
28334a01893SRuslan Bukin DELAY(10);
28434a01893SRuslan Bukin }
28534a01893SRuslan Bukin if (tout == 0) {
28634a01893SRuslan Bukin return (1);
28734a01893SRuslan Bukin }
28834a01893SRuslan Bukin
28934a01893SRuslan Bukin return (0);
29034a01893SRuslan Bukin }
29134a01893SRuslan Bukin
29234a01893SRuslan Bukin static int
fpga_close(struct cdev * dev,int flags __unused,int fmt __unused,struct thread * td __unused)2938aabb971SRuslan Bukin fpga_close(struct cdev *dev, int flags __unused,
29434a01893SRuslan Bukin int fmt __unused, struct thread *td __unused)
29534a01893SRuslan Bukin {
29634a01893SRuslan Bukin struct fpgamgr_softc *sc;
29734a01893SRuslan Bukin int reg;
29834a01893SRuslan Bukin
29934a01893SRuslan Bukin sc = dev->si_drv1;
30034a01893SRuslan Bukin
30134a01893SRuslan Bukin reg = READ4(sc, GPIO_EXT_PORTA);
3028aabb971SRuslan Bukin if ((reg & EXT_PORTA_CDP) == 0) {
30334a01893SRuslan Bukin device_printf(sc->dev, "Err: configuration failed\n");
30434a01893SRuslan Bukin return (ENXIO);
30534a01893SRuslan Bukin }
30634a01893SRuslan Bukin
30734a01893SRuslan Bukin /* Exit configuration state */
30834a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_CTRL);
30934a01893SRuslan Bukin reg &= ~(CTRL_AXICFGEN);
31034a01893SRuslan Bukin WRITE4(sc, FPGAMGR_CTRL, reg);
31134a01893SRuslan Bukin
31234a01893SRuslan Bukin /* Wait dclk pulses */
31334a01893SRuslan Bukin if (fpga_wait_dclk_pulses(sc, 4)) {
31434a01893SRuslan Bukin device_printf(sc->dev, "Can't proceed 4 dclk pulses\n");
31534a01893SRuslan Bukin return (ENXIO);
31634a01893SRuslan Bukin }
31734a01893SRuslan Bukin
31834a01893SRuslan Bukin if (fpgamgr_state_wait(sc, FPGAMGR_MODE_USER)) {
31934a01893SRuslan Bukin device_printf(sc->dev, "Can't get USER mode\n");
32034a01893SRuslan Bukin return (ENXIO);
32134a01893SRuslan Bukin }
32234a01893SRuslan Bukin
32334a01893SRuslan Bukin /* Disable configuration */
32434a01893SRuslan Bukin reg = READ4(sc, FPGAMGR_CTRL);
32534a01893SRuslan Bukin reg &= ~(CTRL_EN);
32634a01893SRuslan Bukin WRITE4(sc, FPGAMGR_CTRL, reg);
32734a01893SRuslan Bukin
32834a01893SRuslan Bukin return (0);
32934a01893SRuslan Bukin }
33034a01893SRuslan Bukin
33134a01893SRuslan Bukin static int
fpga_write(struct cdev * dev,struct uio * uio,int ioflag)33234a01893SRuslan Bukin fpga_write(struct cdev *dev, struct uio *uio, int ioflag)
33334a01893SRuslan Bukin {
33434a01893SRuslan Bukin struct fpgamgr_softc *sc;
33534a01893SRuslan Bukin int buffer;
33634a01893SRuslan Bukin
33734a01893SRuslan Bukin sc = dev->si_drv1;
33834a01893SRuslan Bukin
33934a01893SRuslan Bukin /*
34034a01893SRuslan Bukin * Device supports 4-byte copy only.
34134a01893SRuslan Bukin * TODO: add padding for <4 bytes.
34234a01893SRuslan Bukin */
34334a01893SRuslan Bukin
34434a01893SRuslan Bukin while (uio->uio_resid > 0) {
34534a01893SRuslan Bukin uiomove(&buffer, 4, uio);
34634a01893SRuslan Bukin bus_space_write_4(sc->bst_data, sc->bsh_data,
34734a01893SRuslan Bukin 0x0, buffer);
34834a01893SRuslan Bukin }
34934a01893SRuslan Bukin
35034a01893SRuslan Bukin return (0);
35134a01893SRuslan Bukin }
35234a01893SRuslan Bukin
35334a01893SRuslan Bukin static int
fpga_ioctl(struct cdev * dev,u_long cmd,caddr_t addr,int flags,struct thread * td)35434a01893SRuslan Bukin fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
35534a01893SRuslan Bukin struct thread *td)
35634a01893SRuslan Bukin {
35734a01893SRuslan Bukin
35834a01893SRuslan Bukin return (0);
35934a01893SRuslan Bukin }
36034a01893SRuslan Bukin
36134a01893SRuslan Bukin static struct cdevsw fpga_cdevsw = {
36234a01893SRuslan Bukin .d_version = D_VERSION,
36334a01893SRuslan Bukin .d_open = fpga_open,
36434a01893SRuslan Bukin .d_close = fpga_close,
36534a01893SRuslan Bukin .d_write = fpga_write,
36634a01893SRuslan Bukin .d_ioctl = fpga_ioctl,
36734a01893SRuslan Bukin .d_name = "FPGA Manager",
36834a01893SRuslan Bukin };
36934a01893SRuslan Bukin
37034a01893SRuslan Bukin static int
fpgamgr_probe(device_t dev)3718aabb971SRuslan Bukin fpgamgr_probe(device_t dev)
3728aabb971SRuslan Bukin {
3738aabb971SRuslan Bukin
3748aabb971SRuslan Bukin if (!ofw_bus_status_okay(dev))
3758aabb971SRuslan Bukin return (ENXIO);
3768aabb971SRuslan Bukin
37742815783SRuslan Bukin if (!ofw_bus_is_compatible(dev, "altr,socfpga-fpga-mgr"))
3788aabb971SRuslan Bukin return (ENXIO);
3798aabb971SRuslan Bukin
3808aabb971SRuslan Bukin device_set_desc(dev, "FPGA Manager");
3818aabb971SRuslan Bukin return (BUS_PROBE_DEFAULT);
3828aabb971SRuslan Bukin }
3838aabb971SRuslan Bukin
3848aabb971SRuslan Bukin static int
fpgamgr_attach(device_t dev)38534a01893SRuslan Bukin fpgamgr_attach(device_t dev)
38634a01893SRuslan Bukin {
38734a01893SRuslan Bukin struct fpgamgr_softc *sc;
38834a01893SRuslan Bukin
38934a01893SRuslan Bukin sc = device_get_softc(dev);
39034a01893SRuslan Bukin sc->dev = dev;
39134a01893SRuslan Bukin
39234a01893SRuslan Bukin if (bus_alloc_resources(dev, fpgamgr_spec, sc->res)) {
39334a01893SRuslan Bukin device_printf(dev, "could not allocate resources\n");
39434a01893SRuslan Bukin return (ENXIO);
39534a01893SRuslan Bukin }
39634a01893SRuslan Bukin
39734a01893SRuslan Bukin /* Memory interface */
39834a01893SRuslan Bukin sc->bst_data = rman_get_bustag(sc->res[1]);
39934a01893SRuslan Bukin sc->bsh_data = rman_get_bushandle(sc->res[1]);
40034a01893SRuslan Bukin
40134a01893SRuslan Bukin sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
40234a01893SRuslan Bukin 0600, "fpga%d", device_get_unit(sc->dev));
40334a01893SRuslan Bukin
40434a01893SRuslan Bukin if (sc->mgr_cdev == NULL) {
40534a01893SRuslan Bukin device_printf(dev, "Failed to create character device.\n");
40634a01893SRuslan Bukin return (ENXIO);
40734a01893SRuslan Bukin }
40834a01893SRuslan Bukin
40934a01893SRuslan Bukin sc->mgr_cdev->si_drv1 = sc;
41034a01893SRuslan Bukin
41134a01893SRuslan Bukin return (0);
41234a01893SRuslan Bukin }
41334a01893SRuslan Bukin
41434a01893SRuslan Bukin static device_method_t fpgamgr_methods[] = {
41534a01893SRuslan Bukin DEVMETHOD(device_probe, fpgamgr_probe),
41634a01893SRuslan Bukin DEVMETHOD(device_attach, fpgamgr_attach),
41734a01893SRuslan Bukin { 0, 0 }
41834a01893SRuslan Bukin };
41934a01893SRuslan Bukin
42034a01893SRuslan Bukin static driver_t fpgamgr_driver = {
42134a01893SRuslan Bukin "fpgamgr",
42234a01893SRuslan Bukin fpgamgr_methods,
42334a01893SRuslan Bukin sizeof(struct fpgamgr_softc),
42434a01893SRuslan Bukin };
42534a01893SRuslan Bukin
426*75996aa1SJohn Baldwin DRIVER_MODULE(fpgamgr, simplebus, fpgamgr_driver, 0, 0);
427