On Wed, Jul 6, 2016 at 5:41 AM, Damien Miller <[email protected]> wrote:
> That sounds like a reasonable compromise - it would let the admin load
> code to the PRUs in rc.securelevel for later use, or set
> kern.securelevel=0 in sysctl.conf if they wanted to do development
> on a multi-user system.

OK -- I have tested and fixed the previous design. It is now working
exactly as stated in the man page from my prior mail. Below patch is now
in a review-ready state.

On Wed, Jul 6, 2016 at 3:27 AM, Ian Sutton <[email protected]> wrote:
> mainbus -> fdt is next.

tipru(4) now attaches via flattened device tree. However, the dtb
included in miniroot-am335x-60.fs is erroneously devoid of a PRU node.
Here is a patch for the decompiled source file:

http://ce.gl/am335x-boneblack.dts.patch

And the resultant binary for convenience's sake:

http://ce.gl/am335x-boneblack.dtb

To replace it (on BBB, assuming root disk is sd0):

# mount /dev/sd0i /mnt
# curl http://ce.gl/am335x-boneblack.dtb > /mnt/am335x-boneblack.dtb
# umount /mnt
# reboot

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       9 Jul 2016 07:06:54 -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
@@ -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    9 Jul 2016 07:06:54 -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   9 Jul 2016 07:07:02 -0000
@@ -0,0 +1,221 @@
+.\" Copyright (c) 2016 Ian Sutton <[email protected]>
+.\"
+.\" 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 fdt?"
+.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. All
+.Xr write 2
+operations and some
+.Xr ioctl 2
+operations must occur when the system's
+.Xr securelevel 7
+is equal to or lesser than zero, and only after
+.Nm
+has been explicitly enabled via
+.Xr ioctl 2
+call listed in the following section. (See
+.Sx SECURITY CONSIDERATIONS
+for additional details.)
+.Sh IOCTLS
+The following
+.Xr ioctl 2
+commands are supported, and allowed only when system
+.Xr securelevel 7
+is lesser than or equal to zero:
+.Bl -tag -width Ds -offset XXX
+.It Dv PRUEN
+Enables the
+.Nm
+driver itself. All the following
+.Xr ioctl 2
+calls in this section, along with all
+.Xr open 2
+and
+.Xr write 2
+operations attempted on
+.Nm Ap s
+character device file will fail if they are attempted before a successful call
+to this
+.Xr ioctl 2 Ns .
+.It Dv PRUIRQEN Fa "int *"
+Not yet implemented.
+.It Dv PRURESET
+Halts all PRU cores, zeroes all data/instruction/shared memory, and resets
+cores' program counters.
+.El
+.Pp
+The following
+.Xr ioctl 2
+commands are supported, and allowed only when system
+.Xr securelevel 7
+is greater than zero:
+.Bl -tag -width Ds -offset XXX
+.It Dv PRUIRQBLOCK Fa "int *"
+Not yet implemented.
+.It Dv PRUKILL
+Halts and resets PRU cores, and zeroes all data/instruction/shared memory
+spaces. No further PRU activity occurs (or is even possible) after this
+.Xr ioctl 2
+call is made until the system is rebooted.
+.El
+.Pp
+The following
+.Xr ioctl 2
+commands are supported, and allowed regardless of system
+.Xr securelevel 7 Ns :
+.Bl -tag -width Ds -offset XXX
+.It Dv PRUCTL Fa "int *"
+Start/halt PRU cores. Setting a core's *_SEL bit will change its execution 
state
+to whatever the corresponding *_EN bit specifies.
+.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
+.Xr read 2
+call 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 ENOSYS
+Driver received an unimplemented
+.Xr ioctl 2
+call.
+.It Bq Er EFAULT
+.Xr write 2
+attempted at offset not corresponding to top of PRU's data/instruction/shared 
memory.
+.It Bq Er EOVERFLOW
+.Xr write 2
+attempted that would overflow targeted memory space.
+.It Bq Er EPERM
+.Xr write 2 Ns ,
+.Xr open 2 Ns ,
+or
+.Xr ioctl 2
+call attempted by user other than root, or attempted when the system was in an
+improper
+.Xr securelevel 7
+for the attempted call.
+.It Bq Er ECANCELED
+Operation attempted after
+.Nm
+driver was disabled via
+.Dv PRUKILL
+.Xr ioctl 2
+call or attempted before a
+.Dv PRUEN
+.Xr ioctl 2
+call completed successfully.
+.El
+.Sh SEE ALSO
+.Xr pructl 1 ,
+.Xr intro 4 ,
+.Xr securelevel 7
+.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 [email protected] .
+.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.
+.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. This is due to a silicon bug wholly irrectifiable by software (See
+AM335x Technical Reference Manual for additional details.)
+.Sh SECURITY CONSIDERATIONS
+The PRU has comprehensive and unconditional access to all physical memory
+present in the system. Accordingly,
+.Nm
+implements a number of additional safeguards to prevent exploitation, listed 
below:
+.Bl -bullet -width left
+.It
+.Nm
+will only grant file descriptors, honor
+.Xr write 2
+attempts, and process
+.Xr ioctl 2
+calls from real root (ruid 0) regardless of the device file's permission bits,
+user login class, or current
+.Xr securelevel 7 Ns .
+.It
+.Nm
+comes disabled by default. Attempts to enable
+.Nm Ns ,
+and following modification of the instruction/data/shared memory spaces, are 
only
+allowed when the system's
+.Xr securelevel 7
+is equal or lesser than zero. When the system's
+.Xr securelevel 7
+is greater than zero the PRU cores may only be started or halted via the
+.Dv PRUCTL
+.Xr ioctl 2
+call, and the driver itself may be disabled via the
+.Dv PRUKILL
+.Xr ioctl 2
+call which effectively halts and prevents the PRU from performing any actions
+until the system is rebooted.
+.El
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 9 Jul 2016 07:07:03 -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 
 .\"
@@ -23,7 +23,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: April 28 2016 $
+.Dd $Mdocdate: March 12 2016 $
 .Dt MAKEDEV 8 armv7
 .Os
 .Sh NAME
@@ -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     9 Jul 2016 07:07:03 -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 9 Jul 2016 07:07:03 -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 fdt?                 # 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 9 Jul 2016 07:07:03 -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 fdt?                 # Realtime processor
 
 ehci*          at omap?                # EHCI (shim)
 usb*           at ehci?
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        9 Jul 2016 07:07:03 -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[] = {
 
        /*
@@ -166,6 +177,16 @@ struct armv7_dev am335x_devs[] = {
        { .name = "omdog",
          .unit = 0,
          .mem = { { WD_ADDR, WD_SIZE } }
+       },
+
+       /* 
+        * PRU
+        */
+
+       { .name = "tipru",
+         .unit = 0,
+         .mem = { { PRU_ADDR, PRU_SIZE } },
+         .irq = { PRU_IRQ0 }
        },
 
        /*
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        9 Jul 2016 07:07:03 -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      9 Jul 2016 07:07:03 -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 fdt
+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/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  9 Jul 2016 07:07:03 -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__);
        }
@@ -353,6 +355,11 @@ prcm_am335x_enablemodule(struct prcm_sof
        clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK;
        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       9 Jul 2016 07:07:03 -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 9 Jul 2016 07:07:03 -0000
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2016 Ian Sutton <[email protected]>
+ *
+ * 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 <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.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 DEVNAME(sc)    (sc)->sc_dev.dv_xname
+#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
+#define PRU_ENABLED            0x2
+#define PRU_KILLED             0x4
+       uint8_t                 sc_swflags;
+};
+
+int  tipru_match(struct device *, void *, void *);
+void tipru_attach(struct device *, struct device *, void *);
+void tipru_ctl(struct tipru_softc *, int);
+/*int  tipru_intr(void *); */
+void tipru_reset(struct tipru_softc *);
+
+struct cfattach tipru_ca = {
+       sizeof(struct tipru_softc), tipru_match, tipru_attach
+};
+
+struct cfdriver tipru_cd = {
+       NULL, "tipru", DV_DULL
+};
+
+int
+tipru_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+
+       return OF_is_compatible(faa->fa_node, "ti,pruss-v2");
+}
+
+void
+tipru_attach(struct device *parent, struct device *self, void *args)
+{
+       struct fdt_attach_args *aa = args;
+       struct tipru_softc *sc = (struct tipru_softc *) self;
+       uint32_t rev;
+
+       sc->sc_iot = aa->fa_iot;
+       if (bus_space_map(sc->sc_iot, aa->fa_reg[0],
+           aa->fa_reg[1], 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));
+
+       tipru_reset(sc);
+}
+
+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(p->p_ucred->cr_ruid || p->p_ucred->cr_uid)
+           return EPERM;
+       if(ISSET(sc->sc_swflags, PRU_KILLED))
+           return ECANCELED;
+       if(ISSET(flag, O_WRONLY))
+           return ENODEV;
+       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];
+
+       if(ISSET(sc->sc_swflags, PRU_KILLED))
+           return ECANCELED;
+
+       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;
+
+       unit = DEVUNIT(dev);
+       if(unit >= tipru_cd.cd_ndevs)
+           return ENXIO;
+       sc = tipru_cd.cd_devs[unit];
+
+       if(p->p_ucred->cr_ruid || p->p_ucred->cr_uid)
+           return EPERM;
+
+       if (ISSET(sc->sc_swflags, PRU_KILLED))
+           return ECANCELED;
+       
+       if (cmd == PRUEN) {
+           if(securelevel > 0)
+               return ECANCELED;
+
+           printf("%s: enabled\n", DEVNAME(sc));
+           sc->sc_swflags |= PRU_ENABLED;
+           return 0;
+       } else if (!ISSET(sc->sc_swflags, PRU_ENABLED))
+           return ECANCELED;
+
+       switch(cmd) {
+       /* Begin seclevel 0 ioctls */
+       case PRUIRQEN:
+           if(securelevel > 0)
+               return EPERM;
+           return ENOSYS;
+           break;
+       case PRURESET: /* XXX maybe we allow this in any securelevel */
+           if(securelevel > 0)
+               return EPERM;
+           tipru_reset(sc);
+           break;
+       /* End prior, begin seclevel 1 ioctls */
+       case PRUIRQBLOCK:
+           if(securelevel < 1)
+               return EPERM;
+           return ENOSYS;
+           break;
+       case PRUKILL:
+           if(securelevel < 1)
+               return EPERM;
+           tipru_reset(sc);
+           sc->sc_swflags |= PRU_KILLED;
+           sc->sc_swflags &= ~PRU_ENABLED;
+       /* End prior, begin seclevel-agnostic ioctls */
+       case PRUCTL:
+           tipru_ctl(sc, (int)*data);
+           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];
+
+       if(uio->uio_procp->p_ucred->cr_ruid || uio->uio_procp->p_ucred->cr_uid
+           || securelevel > 0)
+           return EPERM;
+
+       if(!ISSET(sc->sc_swflags, PRU_ENABLED) || ISSET(sc->sc_swflags, 
PRU_KILLED))
+           return ECANCELED;
+
+       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;
+}
+
+/* XXX clear intrs. here when irqs implemented. pending intrs. prevent hw halt 
*/
+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));
+       }
+}
+
+void
+tipru_reset(struct tipru_softc *sc)
+{
+       int i;
+
+       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);
+}
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 9 Jul 2016 07:07:03 -0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016 Ian Sutton <[email protected]>
+ *
+ * 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)
+#define PRUEN                  _IO ('P', 4)
+#define PRUKILL                        _IO ('P', 5)

Reply via email to