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)
+

Reply via email to