I have written some software to support the PRU (Programmable Realtime Unit) integrated in Texas Instrument's line of ARM SoCs, specifically the am335x chips. The PRU is a 32-bit realtime processor that exists as a subsystem on the SoC. You can read more about it in the linked man pages.
Included below is a omap/am335x/sitara-specific device driver [tipru(4)] and userspace utility [pructl(1)]. Both are complete and fully documented in their respective man pages which I have also uploaded for convenience: http://ce.gl/tipru.4.html http://ce.gl/pructl.1.html You can find the userspace utility at http://ce.gl/pructl.tar.gz A simple demonstration of the driver in action, after loading and executing code that generates a 129KHz square wave: http://ce.gl/tipru.jpg I have done my best to make this code as palpable as possible but I'm sure there are still outstanding issues. Any advice/pointers are welcome, I have both the time and the inclination to get this code tree-ready. Ian Index: etc/etc.armv7/MAKEDEV =================================================================== RCS file: /cvs/src/etc/etc.armv7/MAKEDEV,v retrieving revision 1.19 diff -u -p -r1.19 MAKEDEV --- etc/etc.armv7/MAKEDEV 21 May 2016 22:15:09 -0000 1.19 +++ etc/etc.armv7/MAKEDEV 4 Jul 2016 08:54:16 -0000 @@ -4,7 +4,7 @@ # generated from: # # OpenBSD: etc.armv7/MAKEDEV.md,v 1.12 2016/05/21 21:30:22 kettenis Exp -# OpenBSD: MAKEDEV.common,v 1.88 2016/05/21 15:17:49 deraadt Exp +# OpenBSD: MAKEDEV.common,v 1.89 2016/05/26 16:29:51 deraadt Exp # OpenBSD: MAKEDEV.mi,v 1.82 2016/03/12 17:58:59 espie Exp # OpenBSD: MAKEDEV.sub,v 1.14 2005/02/07 06:14:18 david Exp # @@ -59,6 +59,7 @@ # usb* Bus control devices used by usbd for attach/detach # Special purpose devices: # apm Power management device +# tipru Programmable realtime unit # audio* Audio devices # bio ioctl tunnel pseudo-device # bktr* Video frame grabbers @@ -231,7 +232,7 @@ vscsi*) ;; video*) - M video$U c 38 $U 600 + M video$U c 38 $U 600 MKlist[${#MKlist[*]}]=";[ -e video ] || ln -s video$U video" ;; @@ -328,6 +329,10 @@ audio*) MKlist[${#MKlist[*]}]=";[ -e audioctl ] || ln -s audioctl$U audioctl" ;; +tipru*) + M tipru c 29 0 200 + ;; + apm*) M apm c 34 0 644 M apmctl c 34 8 644 @@ -469,14 +474,14 @@ local) ;; all) - R gpio0 gpio1 gpio2 gpio3 gpio4 gpio5 gpio6 gpio7 gpio8 vnd0 - R vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 sd5 sd6 sd7 sd8 sd9 cd0 - R cd1 rd0 tap0 tap1 tap2 tap3 tun0 tun1 tun2 tun3 bio pty0 - R diskmap vscsi0 ch0 bpf fuse pppx hotplug ptm local wscons - R pci0 pci1 pci2 pci3 uall rmidi0 rmidi1 rmidi2 rmidi3 rmidi4 - R rmidi5 rmidi6 rmidi7 tuner0 radio0 video0 video1 uk0 random - R tty00 tty01 tty02 tty03 tty04 tty05 tty06 tty07 tty08 tty09 - R tty0a tty0b apm pf wd0 wd1 wd2 wd3 std st0 st1 fd + R tipru0 gpio0 gpio1 gpio2 gpio3 gpio4 gpio5 gpio6 gpio7 + R gpio8 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 sd4 sd5 sd6 sd7 + R sd8 sd9 cd0 cd1 rd0 tap0 tap1 tap2 tap3 tun0 tun1 tun2 tun3 + R bio pty0 diskmap vscsi0 ch0 bpf fuse pppx hotplug ptm local + R wscons pci0 pci1 pci2 pci3 uall rmidi0 rmidi1 rmidi2 rmidi3 + R rmidi4 rmidi5 rmidi6 rmidi7 tuner0 radio0 video0 video1 uk0 + R random tty00 tty01 tty02 tty03 tty04 tty05 tty06 tty07 tty08 + R tty09 tty0a tty0b apm pf wd0 wd1 wd2 wd3 std st0 st1 fd ;; wd*|sd*) Index: etc/etc.armv7/MAKEDEV.md =================================================================== RCS file: /cvs/src/etc/etc.armv7/MAKEDEV.md,v retrieving revision 1.12 diff -u -p -r1.12 MAKEDEV.md --- etc/etc.armv7/MAKEDEV.md 21 May 2016 21:30:22 -0000 1.12 +++ etc/etc.armv7/MAKEDEV.md 4 Jul 2016 08:54:16 -0000 @@ -27,6 +27,8 @@ dnl ADVISED OF THE POSSIBILITY OF SUCH D dnl dnl __devitem(apm, apm, Power management device)dnl +__devitem(tipru, tipru, Programmable realtime unit)dnl +_mkdev(tipru, tipru*, {-M tipru c major_tipru_c 0 200-})dnl _TITLE(make) _DEV(all) _DEV(ramdisk) @@ -64,6 +66,7 @@ _DEV(ulpt, 66) _DEV(usb, 64) _TITLE(spec) _DEV(apm, 34) +_DEV(tipru, 29) _DEV(au, 36) _DEV(bio, 52) _DEV(bktr, 75) @@ -114,3 +117,4 @@ target(all, cd, 0, 1)dnl target(all, sd, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9)dnl target(all, vnd, 0, 1, 2, 3)dnl target(all, gpio, 0, 1, 2, 3, 4, 5, 6, 7, 8)dnl +target(all, tipru, 0)dnl Index: share/man/man4/man4.armv7/tipru.4 =================================================================== RCS file: share/man/man4/man4.armv7/tipru.4 diff -N share/man/man4/man4.armv7/tipru.4 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ share/man/man4/man4.armv7/tipru.4 4 Jul 2016 08:54:22 -0000 @@ -0,0 +1,113 @@ +.\" Copyright (c) 2016 Ian Sutton <i...@kremlin.cc> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: May 11 2016 $ +.Dt TIPRU 4 armv7 +.Os +.Sh NAME +.Nm tipru +.Nd Texas Instruments programmable realtime unit controller +.Sh SYNOPSIS +.Nm "tipru* at omap0" +.Sh DESCRIPTION +The +.Nm +driver supports the Programmable Realtime Unit and Industrial Communication +Subsystem (PRU-ICSS) integrated in Texas Instruments' line of AM335x SoCs. The +PRU is a pair of 32-bit modified Harvard architecture processor cores which run +a simple RISC instruction set. The PRU forgoes any kind of heuristic caching +mechanisms (TLBs, L1/L2/etc caches) as well as instruction pipelining as to +allow for completely predictable and deterministic timing behavior. The PRU is +clocked at 200MHz and executes one instruction every cycle insofar as it +operates within its local data/instruction/shared memory spaces (See +.Sx CAVEATS +for additional details.) +.Pp +.Nm Ap +s primary interface is through its write-only character device file. Writes to +this file populate the PRU's data/instruction/shared memory and must occur at +predefined offsets. Further +.Xr ioctl 2 +calls control the PRU's execution. +.Sh IOCTLS +The following +.Xr ioctl 2 +commands are supported: +.Bl -tag -width Ds +.It Dv PRUCTRL Fa "int *" +Start/halt PRU cores. Setting a core's *_SEL bit will change its execution state +to whatever the corresponding *_EN bit specifies. +.It Dv PRUIRQEN Fa "int *" +Not yet implemented. +.It Dv PRUIRQBLOCK Fa "int *" +Not yet implemented. +.It Dv PRURESET +Halts all PRU cores, zeroes all data/instruction/shared memory, and resets +cores' program counters. +.El +.Sh FILES +.Bl -tag -width XXXXXXXXXXXXXXX -compact +.It Pa /dev/tipru +Character device for accessing PRU instruction/data space and +controlling chip. +.El +.Sh ERRORS +.Bl -tag -width Er +.It Bq Er ENODEV +Character device was opened with mode other than +.Dv O_WRONLY +or a read was attempted. +.It Bq Er EBUSY +Another process already has an open file descriptor on the character device file. +.It Bq Er ENOTSUPP +Driver received an unsupported +.Xr ioctl 2 +call. +.It Bq Er EFAULT +Write attempted at offset not corresponding to top of PRU's +data/instruction/shared memory. +.It Bq Er EOVERFLOW +Write attempted that would overflow targeted memory space. +.El +.Sh SEE ALSO +.Xr pructl 1 , +.Xr intro 4 +.Sh HISTORY +The +.Nm +driver will hopefully soon appear in +.Ox 6.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Ian Sutton Aq Mt i...@kremlin.cc . +.Sh CAVEATS +While the PRU has its own data/instruction/shared memory, it is capable of +accessing all physical addresses on the system (even its own control registers). +Disabling the OCP ports (the mechanism through which the PRU accesses outside$ +memory) provides no extra security as the PRU itself can arbitrarily enable it +(See +.Sx BUGS +for additional details.) +.Pp +The PRU's runtime characteristics are only deterministic insofar as it accesses +memory within its own local address space. All timing guarantees are forfeit +once non-local memory is accessed (See AM335x Technical Reference Manual for$ +more details.) +.Sh BUGS +If the PRU attempts to access memory outside its own local address space, the +system will hang unless the OCP master ports are enabled via the SYSCFG register +(See AM335x Technical Reference Manual for more details.) Index: share/man/man8/man8.armv7/MAKEDEV.8 =================================================================== RCS file: /cvs/src/share/man/man8/man8.armv7/MAKEDEV.8,v retrieving revision 1.12 diff -u -p -r1.12 MAKEDEV.8 --- share/man/man8/man8.armv7/MAKEDEV.8 28 Apr 2016 18:17:31 -0000 1.12 +++ share/man/man8/man8.armv7/MAKEDEV.8 4 Jul 2016 08:54:22 -0000 @@ -1,10 +1,10 @@ -.\" $OpenBSD: MAKEDEV.8,v 1.12 2016/04/28 18:17:31 natano Exp $ +.\" $OpenBSD$ .\" .\" THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. .\" generated from: .\" -.\" OpenBSD: etc.armv7/MAKEDEV.md,v 1.10 2016/04/25 20:38:10 tedu Exp -.\" OpenBSD: MAKEDEV.common,v 1.86 2016/04/25 20:39:42 tedu Exp +.\" OpenBSD: etc.armv7/MAKEDEV.md,v 1.12 2016/05/21 21:30:22 kettenis Exp +.\" OpenBSD: MAKEDEV.common,v 1.89 2016/05/26 16:29:51 deraadt Exp .\" OpenBSD: MAKEDEV.man,v 1.8 2016/03/12 17:59:27 espie Exp .\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp .\" @@ -170,6 +170,9 @@ Bus control devices used by usbd for att .It Ar apm Power management device, see .Xr apm 4 . +.It Ar tipru +Programmable realtime unit, see +.Xr tipru 4 . .It Ar audio* Audio devices, see .Xr audio 4 . Index: sys/arch/arm/arm/conf.c =================================================================== RCS file: /cvs/src/sys/arch/arm/arm/conf.c,v retrieving revision 1.46 diff -u -p -r1.46 conf.c --- sys/arch/arm/arm/conf.c 23 May 2016 00:05:34 -0000 1.46 +++ sys/arch/arm/arm/conf.c 4 Jul 2016 08:54:22 -0000 @@ -145,6 +145,8 @@ cdev_decl(radio); #include <arm/conf.h> +cdev_decl(tipru); + /* Block devices */ struct bdevsw bdevsw[] = { @@ -301,7 +303,7 @@ struct cdevsw cdevsw[] = { cdev_disk_init(NCD,cd), /* 26: SCSI CD-ROM */ cdev_ch_init(NCH,ch), /* 27: SCSI autochanger */ cdev_uk_init(NUK,uk), /* 28: SCSI unknown */ - cdev_notdef(), /* 29: */ + cdev_disk_init(1, tipru), /* 29: Realtime processor */ cdev_notdef(), /* 30: */ cdev_notdef(), /* 31: */ cdev_notdef(), /* 32: */ Index: sys/arch/armv7/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v retrieving revision 1.27 diff -u -p -r1.27 GENERIC --- sys/arch/armv7/conf/GENERIC 28 Jun 2016 04:41:37 -0000 1.27 +++ sys/arch/armv7/conf/GENERIC 4 Jul 2016 08:54:22 -0000 @@ -76,6 +76,7 @@ cpsw* at fdt? com* at fdt? # onboard uarts ommmc* at fdt? # SD/MMC card controller sdmmc* at ommmc? # SD/MMC bus +tipru* at omap? # PRU-ICSS ehci* at omap? # EHCI (shim) usb* at ehci? Index: sys/arch/armv7/conf/RAMDISK =================================================================== RCS file: /cvs/src/sys/arch/armv7/conf/RAMDISK,v retrieving revision 1.24 diff -u -p -r1.24 RAMDISK --- sys/arch/armv7/conf/RAMDISK 28 Jun 2016 04:41:37 -0000 1.24 +++ sys/arch/armv7/conf/RAMDISK 4 Jul 2016 08:54:22 -0000 @@ -75,6 +75,7 @@ cpsw* at fdt? com* at fdt? # onboard uarts ommmc* at fdt? # SD/MMC card controller sdmmc* at ommmc? # SD/MMC bus +tipru* at omap? # Realtime processor ehci* at omap? # EHCI (shim) usb* at ehci? Index: sys/arch/armv7/conf/files.armv7 =================================================================== RCS file: /cvs/src/sys/arch/armv7/conf/files.armv7,v retrieving revision 1.19 diff -u -p -r1.19 files.armv7 --- sys/arch/armv7/conf/files.armv7 23 May 2016 00:05:35 -0000 1.19 +++ sys/arch/armv7/conf/files.armv7 4 Jul 2016 08:54:22 -0000 @@ -7,6 +7,7 @@ major {wd = 16} major {sd = 24} major {cd = 26} major {rd = 18} +major {tipru = 98} file arch/arm/arm/conf.c Index: sys/arch/armv7/omap/am335x.c =================================================================== RCS file: /cvs/src/sys/arch/armv7/omap/am335x.c,v retrieving revision 1.7 diff -u -p -r1.7 am335x.c --- sys/arch/armv7/omap/am335x.c 18 Mar 2014 07:34:17 -0000 1.7 +++ sys/arch/armv7/omap/am335x.c 4 Jul 2016 08:54:22 -0000 @@ -105,6 +105,17 @@ #define IIC1_IRQ 71 #define IIC2_IRQ 30 +#define PRU_SIZE 0x80000 +#define PRU_ADDR 0x4A300000 +#define PRU_IRQ0 20 +#define PRU_IRQ1 21 +#define PRU_IRQ2 22 +#define PRU_IRQ3 23 +#define PRU_IRQ4 24 +#define PRU_IRQ5 25 +#define PRU_IRQ6 26 +#define PRU_IRQ7 27 + struct armv7_dev am335x_devs[] = { /* @@ -168,6 +179,16 @@ struct armv7_dev am335x_devs[] = { .mem = { { WD_ADDR, WD_SIZE } } }, + /* + * PRU + */ + + { .name = "tipru", + .unit = 0, + .mem = { { PRU_ADDR, PRU_SIZE } }, + .irq = { PRU_IRQ0 } + }, + /* * UART */ Index: sys/arch/armv7/omap/am335x_prcmreg.h =================================================================== RCS file: /cvs/src/sys/arch/armv7/omap/am335x_prcmreg.h,v retrieving revision 1.4 diff -u -p -r1.4 am335x_prcmreg.h --- sys/arch/armv7/omap/am335x_prcmreg.h 18 Mar 2014 07:34:17 -0000 1.4 +++ sys/arch/armv7/omap/am335x_prcmreg.h 4 Jul 2016 08:54:22 -0000 @@ -31,6 +31,7 @@ #define PRCM_AM335X_GPIO2_CLKCTRL 0x00b0 #define PRCM_AM335X_GPIO3_CLKCTRL 0x00b4 #define PRCM_AM335X_TPCC_CLKCTRL 0x00bc +#define PRCM_AM335X_PRU_ICSS_CLKCTRL 0x00e8 #define PRCM_AM335X_MMC1_CLKCTRL 0x00f4 #define PRCM_AM335X_MMC2_CLKCTRL 0x00f8 #define PRCM_AM335X_TPTC1_CLKCTRL 0x00fc Index: sys/arch/armv7/omap/files.omap =================================================================== RCS file: /cvs/src/sys/arch/armv7/omap/files.omap,v retrieving revision 1.13 diff -u -p -r1.13 files.omap --- sys/arch/armv7/omap/files.omap 26 Jun 2016 09:06:35 -0000 1.13 +++ sys/arch/armv7/omap/files.omap 4 Jul 2016 08:54:22 -0000 @@ -26,6 +26,10 @@ attach sitaracm at omap file arch/armv7/omap/am335x_cm_padconf.c sitaracm file arch/armv7/omap/sitara_cm.c sitaracm +device tipru +attach tipru at omap +file arch/armv7/omap/tipru.c tipru + device omgpio: gpiobus attach omgpio at omap file arch/armv7/omap/omgpio.c omgpio Index: sys/arch/armv7/omap/omap.c =================================================================== RCS file: /cvs/src/sys/arch/armv7/omap/omap.c,v retrieving revision 1.15 diff -u -p -r1.15 omap.c --- sys/arch/armv7/omap/omap.c 26 Jun 2016 09:06:35 -0000 1.15 +++ sys/arch/armv7/omap/omap.c 4 Jul 2016 08:54:22 -0000 @@ -57,6 +57,7 @@ struct board_dev beaglebone_devs[] = { { "edma", 0 }, { "dmtimer", 0 }, { "dmtimer", 1 }, + { "tipru", 0 }, { "omgpio", 0 }, { "omgpio", 1 }, { "omgpio", 2 }, Index: sys/arch/armv7/omap/prcm.c =================================================================== RCS file: /cvs/src/sys/arch/armv7/omap/prcm.c,v retrieving revision 1.9 diff -u -p -r1.9 prcm.c --- sys/arch/armv7/omap/prcm.c 8 May 2014 21:17:01 -0000 1.9 +++ sys/arch/armv7/omap/prcm.c 4 Jul 2016 08:54:22 -0000 @@ -325,6 +325,8 @@ prcm_am335x_clkctrl(int mod) return PRCM_AM335X_I2C1_CLKCTRL; case PRCM_I2C2: return PRCM_AM335X_I2C2_CLKCTRL; + case PRCM_PRU_ICSS: + return PRCM_AM335X_PRU_ICSS_CLKCTRL; default: panic("%s: module not found\n", __func__); } @@ -354,6 +356,11 @@ prcm_am335x_enablemodule(struct prcm_sof clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE; bus_space_write_4(sc->sc_iot, sc->sc_prcm, reg, clkctrl); + /* PRU has its own special reset register */ + if(reg == PRCM_AM335X_PRU_ICSS_CLKCTRL) { + bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_PRM_PER, 0); + } + /* wait until module is enabled */ while (bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg) & 0x30000) ; Index: sys/arch/armv7/omap/prcmvar.h =================================================================== RCS file: /cvs/src/sys/arch/armv7/omap/prcmvar.h,v retrieving revision 1.5 diff -u -p -r1.5 prcmvar.h --- sys/arch/armv7/omap/prcmvar.h 18 Mar 2014 07:34:17 -0000 1.5 +++ sys/arch/armv7/omap/prcmvar.h 4 Jul 2016 08:54:22 -0000 @@ -51,6 +51,7 @@ enum PRCM_MODULES { PRCM_I2C0, PRCM_I2C1, PRCM_I2C2, + PRCM_PRU_ICSS, }; #define PRCM_REG_MAX 6 Index: sys/arch/armv7/omap/tipru.c =================================================================== RCS file: sys/arch/armv7/omap/tipru.c diff -N sys/arch/armv7/omap/tipru.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/omap/tipru.c 4 Jul 2016 08:54:22 -0000 @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2016 Ian Sutton <i...@kremlin.cc> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/malloc.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/ioctl.h> +#include <machine/bus.h> + +#include <armv7/armv7/armv7var.h> +#include <armv7/omap/prcmvar.h> + +#include <sys/fcntl.h> +#include <sys/stat.h> + +#include "tipru.h" + +#define HREAD4(sc, reg) \ + (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) +#define HSET4(sc, reg, bits) \ + HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) +#define HCLR4(sc, reg, bits) \ + HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) + +#define DEVUNIT(x) (minor(x) & 0x7f) + +struct tipru_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +#define PRU_RUN 0x1 +#define PRU_OCP 0x2 +#define PRU_STEP 0x4 +#define PRU_SLEEP 0x8 + uint8_t sc_hwflags; +#define PRU_XCLUDE 0x1 + uint8_t sc_swflags; +}; + +void tipru_attach(struct device *, struct device *, void *); +void tipru_ctl(struct tipru_softc *, int); +/*int tipru_intr(void *); */ + +struct cfattach tipru_ca = { + sizeof(struct tipru_softc), NULL, tipru_attach +}; + +struct cfdriver tipru_cd = { + NULL, "tipru", DV_DULL +}; + +void +tipru_attach(struct device *parent, struct device *self, void *args) +{ + struct tipru_softc *sc = (struct tipru_softc *) self; + struct armv7_attach_args *aa = args; + uint32_t rev; + + sc->sc_iot = aa->aa_iot; + if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, + aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) + panic("%s: bus_space_map failed!", __func__); + + prcm_enablemodule(PRCM_PRU_ICSS); + + rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PRUx_CFG + PRUx_CFG_REVID); + printf(" revid 0x%08x\n", rev); + + HSET4(sc, PRUx_CFG + PRUx_CFG_SYSCFG, PRUx_CFG_SYSCFG_STANDBY_INIT); + while(HREAD4(sc, PRUx_CFG + PRUx_CFG_SYSCFG_SUB_MWAIT)); +} + +int +tipruopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + struct tipru_softc *sc; + int unit; + + unit = DEVUNIT(dev); + if(unit >= tipru_cd.cd_ndevs) + return ENXIO; + + sc = tipru_cd.cd_devs[unit]; + + if(ISSET(flag, O_WRONLY)) + return ENODEV; + else if(ISSET(sc->sc_swflags, PRU_XCLUDE)) + return EBUSY; + + sc->sc_swflags |= PRU_XCLUDE; + + return 0; +} + +int +tipruclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + struct tipru_softc *sc; + int unit; + + unit = DEVUNIT(dev); + if(unit >= tipru_cd.cd_ndevs) + return ENXIO; + + sc = tipru_cd.cd_devs[unit]; + + sc->sc_swflags &= (sc->sc_swflags & ~PRU_XCLUDE); + return 0; +} + +int +tipruioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct tipru_softc *sc; + int unit, i; + + unit = DEVUNIT(dev); + if(unit >= tipru_cd.cd_ndevs) + return ENXIO; + + sc = tipru_cd.cd_devs[unit]; + + switch(cmd) { + case PRUCTL: + tipru_ctl(sc, (int)*data); + break; + case PRUIRQEN: + break; + case PRUIRQBLOCK: + break; + case PRURESET: + tipru_ctl(sc, 0x0); + HCLR4(sc, PRU0_CTRL, PRUx_CTRL_PCTR_RST_VAL_MASK); + HCLR4(sc, PRU1_CTRL, PRUx_CTRL_PCTR_RST_VAL_MASK); + + for(i = 0; i < 2048; i++) { + HWRITE4(sc, PRU0_DRAM + i*4, 0x0); + HWRITE4(sc, PRU1_DRAM + i*4, 0x0); + HWRITE4(sc, PRU0_IRAM + i*4, 0x0); + HWRITE4(sc, PRU1_IRAM + i*4, 0x0); + } + + for(i = 0; i < 3072; i++) + HWRITE4(sc, PRUx_SHRRAM + i*4, 0x0); + break; + default: + return EOPNOTSUPP; + } + + return 0; +} + +int +tipruread(dev_t dev, struct uio *uio, int flags) +{ + return ENODEV; +} + +int +tipruwrite(dev_t dev, struct uio *uio, int flags) +{ + struct tipru_softc *sc; + int unit, lim, i, j; + uint32_t *wbuf; + + unit = DEVUNIT(dev); + if(unit >= tipru_cd.cd_ndevs) + return ENXIO; + + sc = tipru_cd.cd_devs[unit]; + + switch(uio->uio_offset) { + case PRU0_DRAM: + case PRU1_DRAM: + case PRU0_IRAM: + case PRU1_IRAM: + /* FALLTHROUGH */ + lim = PRU_RAM_SIZE; + break; + case PRUx_SHRRAM: + lim = PRU_SHR_SIZE; + break; + default: + return EFAULT; + } + + for(i = 0; i < uio->uio_iovcnt; i++) { + if(uio->uio_iov[i].iov_len > lim) + return EOVERFLOW; + + for(j = 0; j < uio->uio_iov[i].iov_len / 4; j++) { + wbuf = uio->uio_iov[i].iov_base + 4 * j; + HWRITE4(sc, uio->uio_offset + j * 4, *wbuf); + } + } + + return 0; +} + +void +tipru_ctl(struct tipru_softc *sc, int target_runstate) +{ + if(target_runstate & PRUCTL_PRU0_SEL && target_runstate & PRUCTL_PRU0_EN) { + HSET4(sc, PRU0_CTRL, PRUx_CTRL_EN); + while(!ISSET(HREAD4(sc, PRU0_CTRL) , PRUx_CTRL_RUNSTATE)); + } else if(target_runstate & PRUCTL_PRU0_SEL) { + HCLR4(sc, PRU0_CTRL, PRUx_CTRL_EN); + while(ISSET(HREAD4(sc, PRU0_CTRL) , PRUx_CTRL_RUNSTATE)); + } + + if(target_runstate & PRUCTL_PRU1_SEL && target_runstate & PRUCTL_PRU1_EN) { + HSET4(sc, PRU1_CTRL, PRUx_CTRL_EN); + while(!ISSET(HREAD4(sc, PRU1_CTRL) , PRUx_CTRL_RUNSTATE)); + } else if(target_runstate & PRUCTL_PRU1_SEL) { + HCLR4(sc, PRU1_CTRL, PRUx_CTRL_EN); + while(ISSET(HREAD4(sc, PRU1_CTRL) , PRUx_CTRL_RUNSTATE)); + } +} +#if 0 +#define PRUx_CTRL_CTBIR0_OFST 0x20 + +#define PRUx_CTRL_CTBIR1_OFST 0x24 + +#define PRUx_CTRL_CTPPR0_OFST 0x28 + +#define PRUx_CTRL_CTPPR1_OFST 0x2C + +#define PRU_CTRL 0x00 +#define PRU_SYS 0x04 +#define PRU_WAKEUP_EN 0x08 +#define PRU_CYCLE 0x0C +#define PRU_STALL 0x10 +#define PRU_CTBIR0 0x20 +#define PRU_CTBIR1 0x24 +#define PRU_CTPPR0 0x28 +#define PRU_CTPPR1 0x2C + +/* #define PRU0_CFG_GPCFG_OFST 0x08 TODO */ + +#endif + Index: sys/arch/armv7/omap/tipru.h =================================================================== RCS file: sys/arch/armv7/omap/tipru.h diff -N sys/arch/armv7/omap/tipru.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/omap/tipru.h 4 Jul 2016 08:54:22 -0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016 Ian Sutton <i...@kremlin.cc> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* RAM segments, global context */ +#define PRU0_DRAM 0x00000 +#define PRU1_DRAM 0x02000 +#define PRUx_SHRRAM 0x10000 +#define PRU0_IRAM 0x34000 +#define PRU1_IRAM 0x38000 + +#define PRU_RAM_SIZE 0x02000 +#define PRU_SHR_SIZE 0x03000 + +/* register groups, global context */ +#define PRUx_INTC 0x20000 +#define PRU0_CTRL 0x22000 +#define PRU1_CTRL 0x24000 +#define PRU0_DBG 0x22400 +#define PRU1_DBG 0x24400 +#define PRUx_CFG 0x26000 +#define PRUx_UART 0x28000 +#define PRUx_IEP 0x2e000 +#define PRUx_ECAP 0x30000 + +/* control registers */ +#define PRUx_CTRL_PCTR_RST_VAL_SHAMT 16 +#define PRUx_CTRL_PCTR_RST_VAL_MASK (16 << PRUx_CTRL_PCTR_RST_VAL_SHAMT) +#define PRUx_CTRL_RUNSTATE (1 << 15) +#define PRUx_CTRL_SINGLE_STEP (1 << 8) +#define PRUx_CTRL_CTR_EN (1 << 3) +#define PRUx_CTRL_SLEEPING (1 << 2) +#define PRUx_CTRL_EN (1 << 1) +#define PRUx_CTRL_SOFT_RST_N (1 << 0) + +#define PRUx_CTRL_STS 0x04 +#define PRUx_CTRL_STS_PCTR_SHAMT 0 +#define PRUx_CTRL_SYS_PCTR_MASK (16 << PRUx_SYS_PCTR_SHAMT) + +#define PRUx_CTRL_WAKEUP_EN 0x08 +#define PRUx_CTRL_CYCLE_OFST 0x0C +#define PRUx_CTRL_STALL_OFST 0x10 + +/* intr. registers XXX */ + +/* configuration registers */ +#define PRUx_CFG_REVID 0x00 + +#define PRUx_CFG_SYSCFG 0x04 +#define PRUx_CFG_SYSCFG_SUB_MWAIT (1 << 5) +#define PRUx_CFG_SYSCFG_STANDBY_INIT (1 << 4) +#define PRUx_CFG_SYSCFG_STANDBY_MODE_SHAMT 2 +#define PRUx_CFG_SYSCFG_STANDBY_MODE_MASK (2 << PRUx_CFG_SYSCFG_STANDBY_MODE_SHAMT) +#define PRUx_CFG_SYSCFG_IDLE_MODE_SHAMT 0 +#define PRUx_CFG_SYSCFG_IDLE_MODE_MASK (2 << PRUx_CFG_SYSCFG_IDLE_MODE_SHAMT) + +#define PRUCTL_PRU0_SEL 0x1 +#define PRUCTL_PRU1_SEL 0x2 +#define PRUCTL_PRU0_EN 0x4 +#define PRUCTL_PRU1_EN 0x8 + +#define PRUCTL _IOW('P', 0, int) +#define PRUIRQEN _IOW('P', 1, int) +#define PRUIRQBLOCK _IOW('P', 2, int) +#define PRURESET _IO ('P', 3) +