On Thu, April 25, 2013 7:30 pm, Alexey E. Suslikov wrote:
> Raphael Graf <r <at> undefined.ch> writes:
>
>> I have a beaglebone (AM3359) running OpenBSD, see below.
>> Is there any interest in such code?
>
> Diffs are interesting. Teasers are not.
>
So here's what I have at the moment.
Some parts are just horrible hacks (notably the prcm stuff), beware.
I'll start sending (smaller) diffs when ready.
Index: beagle/beagle_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/beagle/beagle/beagle_machdep.c,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 beagle_machdep.c
--- beagle/beagle_machdep.c 30 Aug 2012 15:51:13 -0000 1.15
+++ beagle/beagle_machdep.c 26 Apr 2013 14:43:24 -0000
@@ -882,6 +882,9 @@ initarm(void *arg0, void *arg1, void *ar
case BOARD_ID_OMAP3_BEAGLE:
printf("board type: beagle\n");
break;
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ printf("board type: beaglebone\n");
+ break;
case BOARD_ID_OMAP3_OVERO:
printf("board type: overo\n");
break;
@@ -979,6 +982,9 @@ consinit(void)
case BOARD_ID_OMAP3_BEAGLE:
case BOARD_ID_OMAP3_OVERO:
paddr = 0x49020000;
+ break;
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ paddr = 0x44E09000; /* UART0 */
break;
case BOARD_ID_OMAP4_PANDA:
paddr = 0x48020000;
Index: conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/beagle/conf/GENERIC,v
retrieving revision 1.14
diff -u -p -u -p -r1.14 GENERIC
--- conf/GENERIC 27 Sep 2012 14:01:35 -0000 1.14
+++ conf/GENERIC 26 Apr 2013 14:43:24 -0000
@@ -68,6 +68,7 @@ prcm* at soc? # power/clock controlle
omdog* at soc? # watchdog timer
omgpio* at soc? # user-visible GPIO pins?
gptimer* at soc? # general purpose timers
+dmtimer* at soc? # general purpose timers
ommmc* at soc? # SD/MMC card controller
omusbtll* at soc?
Index: conf/RAMDISK
===================================================================
RCS file: /cvs/src/sys/arch/beagle/conf/RAMDISK,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 RAMDISK
--- conf/RAMDISK 27 Sep 2012 14:01:35 -0000 1.16
+++ conf/RAMDISK 26 Apr 2013 14:43:24 -0000
@@ -73,6 +73,7 @@ prcm* at soc? # power/clock controlle
omdog* at soc? # watchdog timer
omgpio* at soc? # user-visible GPIO pins?
gptimer* at soc? # general purpose timers
+dmtimer* at soc? # general purpose timers
ommmc* at soc? # SD/MMC card controller
omusbtll* at soc?
Index: conf/files.beagle
===================================================================
RCS file: /cvs/src/sys/arch/beagle/conf/files.beagle,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 files.beagle
--- conf/files.beagle 27 Mar 2013 17:33:13 -0000 1.12
+++ conf/files.beagle 26 Apr 2013 14:43:24 -0000
@@ -31,6 +31,7 @@ attach omap at mainbus
file arch/beagle/dev/omap.c omap
file arch/beagle/dev/omap3.c omap
file arch/beagle/dev/omap4.c omap
+file arch/beagle/dev/am335x.c omap
# cortex based peripherals
device ampintc
@@ -62,6 +63,10 @@ file arch/beagle/dev/intc.c intc
device gptimer
attach gptimer at soc
file arch/beagle/dev/gptimer.c gptimer
+
+device dmtimer
+attach dmtimer at soc
+file arch/beagle/dev/dmtimer.c dmtimer
device omdog
attach omdog at soc
Index: dev/am335x.c
===================================================================
RCS file: dev/am335x.c
diff -N dev/am335x.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ dev/am335x.c 26 Apr 2013 14:43:24 -0000
@@ -0,0 +1,161 @@
+/* $OpenBSD: omap3.c,v 1.4 2011/11/10 23:43:01 uwe Exp $ */
+
+/*
+ * Copyright (c) 2011 Uwe Stuehler <[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/types.h>
+#include <sys/param.h>
+#include <machine/bus.h>
+
+#include <beagle/dev/omapvar.h>
+
+#define PRCM_ADDR 0x44E00000
+#define PRCM_SIZE 0x2000
+
+#define INTC_ADDR 0x48200000
+#define INTC_SIZE 0x1000
+#define INTC_NUM_IRQ 128
+
+#define DMTIMERx_SIZE 0x1000
+#define DMTIMER0_ADDR 0x44E05000
+#define DMTIMER1_ADDR 0x44E31000 /* 1MS */
+#define DMTIMER2_ADDR 0x48040000
+#define DMTIMER3_ADDR 0x48042000
+#define DMTIMER4_ADDR 0x48044000
+#define DMTIMER5_ADDR 0x48046000
+#define DMTIMER6_ADDR 0x48048000
+#define DMTIMER7_ADDR 0x4804A000
+
+#define DMTIMER0_IRQ 66
+#define DMTIMER1_IRQ 67
+#define DMTIMER2_IRQ 68
+#define DMTIMER3_IRQ 69
+#define DMTIMER4_IRQ 92
+#define DMTIMER5_IRQ 93
+#define DMTIMER6_IRQ 94
+#define DMTIMER7_IRQ 95
+
+#define WD_ADDR 0x44E35000
+#define WD_SIZE 0x80
+
+#define GPIOx_SIZE 0x1000
+#define GPIO0_ADDR 0x44E07000
+#define GPIO1_ADDR 0x4804C000
+#define GPIO2_ADDR 0x481AC000
+#define GPIO3_ADDR 0x481AE000
+
+#define GPIO0_IRQ 96
+#define GPIO1_IRQ 98
+#define GPIO2_IRQ 32
+#define GPIO3_IRQ 62
+
+#define UARTx_SIZE 0x400
+#define UART0_ADDR 0x44E09000
+#define UART1_ADDR 0x48022000
+#define UART2_ADDR 0x48024000
+#define UART3_ADDR 0x481A6000
+#define UART4_ADDR 0x481A8000
+#define UART5_ADDR 0x481AA000
+
+#define UART0_IRQ 72
+#define UART1_IRQ 73
+#define UART2_IRQ 74
+#define UART3_IRQ 44
+#define UART4_IRQ 45
+#define UART5_IRQ 46
+
+#define HSMMCx_SIZE 0x200
+#define HSMMC0_ADDR 0x48060000
+#define HSMMC0_IRQ 64
+
+#define USBTLL_ADDR 0x48062000
+#define USBTLL_SIZE 0x1000
+
+struct omap_dev am335x_devs[] = {
+
+ /*
+ * Power, Reset and Clock Manager
+ */
+
+ { .name = "prcm",
+ .unit = 0,
+ .mem = { { PRCM_ADDR, PRCM_SIZE } },
+ },
+
+ /*
+ * Interrupt Controller
+ */
+
+ { .name = "intc",
+ .unit = 0,
+ .mem = { { INTC_ADDR, INTC_SIZE } },
+ },
+
+ /*
+ * General Purpose Timers
+ */
+
+ { .name = "dmtimer",
+ .unit = 1, /* XXX see gptimer.c */
+ .mem = { { DMTIMER2_ADDR, DMTIMERx_SIZE } },
+ .irq = { DMTIMER2_IRQ }
+ },
+
+ { .name = "dmtimer",
+ .unit = 0, /* XXX see gptimer.c */
+ .mem = { { DMTIMER3_ADDR, DMTIMERx_SIZE } },
+ .irq = { DMTIMER3_IRQ }
+ },
+
+ /*
+ * Watchdog Timer
+ */
+
+ { .name = "omdog",
+ .unit = 0,
+ .mem = { { WD_ADDR, WD_SIZE } }
+ },
+
+ /*
+ * UART
+ */
+
+ { .name = "com",
+ .unit = 0,
+ .mem = { { UART0_ADDR, UARTx_SIZE } },
+ .irq = { UART0_IRQ }
+ },
+
+ /*
+ * MMC
+ */
+
+ { .name = "ommmc",
+ .unit = 0,
+ .mem = { { HSMMC0_ADDR, HSMMCx_SIZE } },
+ .irq = { HSMMC0_IRQ }
+ },
+
+ { .name = NULL,
+ .unit = 0
+ }
+};
+
+void
+am335x_init(void)
+{
+ omap_set_devs(am335x_devs);
+}
Index: dev/dmtimer.c
===================================================================
RCS file: dev/dmtimer.c
diff -N dev/dmtimer.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ dev/dmtimer.c 26 Apr 2013 14:43:24 -0000
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <[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.
+ */
+
+/*
+ * WARNING - this timer initializion has not been checked
+ * to see if it will do _ANYTHING_ sane if the omap enters
+ * low power mode.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/evcount.h>
+#include <sys/device.h>
+#include <sys/timetc.h>
+#include <dev/clock_subr.h>
+#include <machine/bus.h>
+#include <beagle/dev/omapvar.h>
+#include <beagle/dev/prcmvar.h>
+
+#include <machine/intr.h>
+#include <arm/cpufunc.h>
+
+/* registers */
+#define DM_TIDR 0x000 /* revision */
+#define DM_TIOCP_CFG 0x010
+#define DM_TIOCP_CFG_IDLEMODE 0x0000000c
+#define DM_TIOCP_CFG_EMUFREE 0x00000002
+#define DM_TIOCP_CFG_SOFTRESET 0x00000001
+#define DM_TISR 0x028 /* timer irq
status register*/
+#define GP_TISTAT_TCAR 0x00000004
+#define GP_TISTAT_OVF 0x00000002
+#define GP_TISTAT_MATCH 0x00000001
+#define DM_TIER 0x2c /* timer irq
enable set register (set only!!!) */
+#define DM_TIER_TCAR_EN 0x4
+#define DM_TIER_OVF_EN 0x2
+#define DM_TIER_MAT_EN 0x1
+#define DM_TWER 0x034 /* timer wakeup
enable register */
+#define DM_TWER_TCAR_EN 0x00000004
+#define DM_TWER_OVF_EN 0x00000002
+#define DM_TWER_MAT_EN 0x00000001
+#define DM_TCLR 0x038 /* timer
control register*/
+#define DM_TCLR_GPO (1<<14)
+#define DM_TCLR_CAPT (1<<13)
+#define DM_TCLR_PT (1<<12)
+#define DM_TCLR_TRG (3<<10)
+#define DM_TCLR_TRG_O (1<<10)
+#define DM_TCLR_TRG_OM (2<<10)
+#define DM_TCLR_TCM (3<<8)
+#define DM_TCLR_TCM_RISE (1<<8)
+#define DM_TCLR_TCM_FALL (2<<8)
+#define DM_TCLR_TCM_BOTH (3<<8)
+#define DM_TCLR_SCPWM (1<<7)
+#define DM_TCLR_CE (1<<6)
+#define DM_TCLR_PRE (1<<5)
+#define DM_TCLR_PTV (7<<2)
+#define DM_TCLR_AR (1<<1)
+#define DM_TCLR_ST (1<<0)
+#define DM_TCRR 0x03c /* counter */
+#define DM_TLDR 0x040 /* reload */
+#define DM_TTGR 0x044
+#define DM_TWPS 0x048 /* write posted
status register*/
+#define DM_TWPS_TCLR 0x01
+#define DM_TWPS_TCRR 0x02
+#define DM_TWPS_TLDR 0x04
+#define DM_TWPS_TTGR 0x08
+#define DM_TWPS_TMAR 0x10
+#define DM_TWPS_ALL 0x1f
+#define DM_TMAR 0x04c
+#define DM_TCAR 0x050
+#define GP_TSICR 0x054
+#define GP_TSICR_POSTED 0x00000002
+#define GP_TSICR_SFT 0x00000001
+#define DM_TCAR2 0x058
+
+#define TIMER_FREQUENCY 32768 /* 32kHz is used,
selectable */
+
+static struct evcount clk_count;
+static struct evcount stat_count;
+
+void dmtimer_attach(struct device *parent, struct device *self, void *args);
+int dmtimer_intr(void *frame);
+void dmtimer_wait(int reg);
+void dmtimer_cpu_initclocks(void);
+void dmtimer_delay(u_int);
+void dmtimer_setstatclockrate(int newhz);
+
+bus_space_tag_t dmtimer_iot;
+bus_space_handle_t dmtimer_ioh0, dmtimer_ioh1 = 0;
+int dmtimer_irq = 0;
+
+u_int dmtimer_get_timecount(struct timecounter *);
+
+static struct timecounter dmtimer_timecounter = {
+ dmtimer_get_timecount, NULL, 0x7fffffff, 0, "dmtimer", 0, NULL
+};
+
+volatile u_int32_t nexttickevent;
+volatile u_int32_t nextstatevent;
+u_int32_t ticks_per_second;
+u_int32_t ticks_per_intr;
+u_int32_t ticks_err_cnt;
+u_int32_t ticks_err_sum;
+u_int32_t statvar, statmin;
+
+struct cfattach dmtimer_ca = {
+ sizeof (struct device), NULL, dmtimer_attach
+};
+
+struct cfdriver dmtimer_cd = {
+ NULL, "dmtimer", DV_DULL
+};
+
+void
+dmtimer_attach(struct device *parent, struct device *self, void *args)
+{
+ struct omap_attach_args *oa = args;
+ bus_space_handle_t ioh;
+ u_int32_t rev;
+
+ dmtimer_iot = oa->oa_iot;
+
+ if (bus_space_map(dmtimer_iot, oa->oa_dev->mem[0].addr,
+ oa->oa_dev->mem[0].size, 0, &ioh))
+ panic("dmtimer_attach: bus_space_map failed!\n");
+
+ prcm_setclock(1, PRCM_CLK_SPEED_32);
+ prcm_setclock(2, PRCM_CLK_SPEED_32);
+
+ prcm_enablemodule(AM335X_PRCM_CM_PER_TIMER2_CLKCTRL);
+ prcm_enablemodule(AM335X_PRCM_CM_PER_TIMER3_CLKCTRL);
+
+ rev = bus_space_read_4(dmtimer_iot, ioh, DM_TIDR);
+
+ printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
+
+ if (self->dv_unit == 0) { /* timer 2*/
+ dmtimer_ioh0 = ioh;
+ dmtimer_irq = oa->oa_dev->irq[0];
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TCLR, 0); /*
timer control register, stop timer */
+ } else if (self->dv_unit == 1) { /* timer 3*/
+ /* start timer because it is used in delay */
+ /* interrupts are disabled */
+ dmtimer_ioh1 = ioh;
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR, 0); /*
timer counter register */
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh1, DM_TLDR, 0); /*
timer load register */
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh1, DM_TCLR,
+ DM_TCLR_AR | DM_TCLR_ST);
+ dmtimer_wait(DM_TWPS_ALL);
+
+ dmtimer_timecounter.tc_frequency = TIMER_FREQUENCY;
+ tc_init(&dmtimer_timecounter);
+ }
+ else
+ panic("attaching too many dmtimers at 0x%x",
+ oa->oa_dev->mem[0].addr);
+
+ arm_clock_register(dmtimer_cpu_initclocks, dmtimer_delay,
+ dmtimer_setstatclockrate);
+}
+
+/*
+ * See comment in arm/xscale/i80321_clock.c
+ *
+ * counter is count up, but with autoreload timers it is not possible
+ * to detect how many interrupts passed while interrupts were blocked.
+ * also it is not possible to atomically add to the register
+ * get get it to precisely fire at a non-fixed interval.
+ *
+ * To work around this two timers are used, GPT1 is used as a reference
+ * clock without reload , however we just ignore the interrupt it
+ * would (may?) generate.
+ *
+ * Internally this keeps track of when the next timer should fire
+ * and based on that time and the current value of the reference
+ * clock a number is written into the timer count register to schedule
+ * the next event.
+ */
+
+int
+dmtimer_intr(void *frame)
+{
+ u_int32_t now, r;
+ u_int32_t nextevent, duration;
+
+ /* read the free running counter */
+ now = bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR);
+
+ while ((int32_t) (nexttickevent - now) < 0) {
+ nexttickevent += ticks_per_intr;
+ ticks_err_sum += ticks_err_cnt;
+#if 0
+ if (ticks_err_sum > hz) {
+ u_int32_t match_error;
+ match_error = ticks_err_sum / hz
+ ticks_err_sum -= (match_error * hz);
+ }
+#else
+ /* looping a few times is faster than divide */
+ while (ticks_err_sum > hz) {
+ nexttickevent += 1;
+ ticks_err_sum -= hz;
+ }
+#endif
+ clk_count.ec_count++;
+ hardclock(frame);
+ }
+
+ while ((int32_t) (nextstatevent - now) < 0) {
+ do {
+ r = random() & (statvar -1);
+ } while (r == 0); /* random == 0 not allowed */
+ nextstatevent += statmin + r;
+ /* XXX - correct nextstatevent? */
+ stat_count.ec_count++;
+ statclock(frame);
+ }
+ if ((now - nexttickevent) < (now - nextstatevent))
+ nextevent = nexttickevent;
+ else
+ nextevent = nextstatevent;
+
+/* XXX */
+ duration = nextevent -
+ bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR);
+#if 0
+ printf("duration 0x%x %x %x\n", nextevent -
+ bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR),
+ bus_space_read_4(dmtimer_iot, dmtimer_ioh0, DM_TCRR),
+ bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR));
+#endif
+
+
+ if (duration <= 0)
+ duration = 1; /* trigger immediately. */
+
+ if (duration > ticks_per_intr) {
+ /*
+ * If interrupts are blocked too long, like during
+ * the root prompt or ddb, the timer can roll over,
+ * this will allow the system to continue to run
+ * even if time is lost.
+ */
+ duration = ticks_per_intr;
+ nexttickevent = now;
+ nextstatevent = now;
+ }
+
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TISR,
+ bus_space_read_4(dmtimer_iot, dmtimer_ioh0, DM_TISR));
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TISR, 7);
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TCRR, -duration); /*
set counter of timer 2 */
+
+ return 1;
+}
+
+/*
+ * would be interesting to play with trigger mode while having one timer
+ * in 32KHz mode, and the other timer running in sysclk mode and use
+ * the high resolution speeds (matters more for delay than tick timer
+ */
+
+void
+dmtimer_cpu_initclocks()
+{
+ stathz = 128;
+ profhz = 1024;
+
+ ticks_per_second = TIMER_FREQUENCY; /* 32768 */
+
+ setstatclockrate(stathz);
+
+ ticks_per_intr = ticks_per_second / hz;
+ ticks_err_cnt = ticks_per_second % hz;
+ ticks_err_sum = 0;
+
+ prcm_setclock(1, PRCM_CLK_SPEED_32);
+ prcm_setclock(2, PRCM_CLK_SPEED_32);
+ /* establish interrupts */
+ arm_intr_establish(dmtimer_irq, IPL_CLOCK, dmtimer_intr, /*
timer 2 irq */
+ NULL, "tick");
+
+ /* setup timer 0 (hardware timer 3) */
+ /* reset? - XXX */
+
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TLDR, 0); /*
value loaded on overflow */
+
+ nexttickevent = nextstatevent = bus_space_read_4(dmtimer_iot,
+ dmtimer_ioh1, DM_TCRR) + ticks_per_intr;
+
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TIER, DM_TIER_OVF_EN);
/* timer interrupt on overflow enable (timer 2)*/
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TWER, DM_TWER_OVF_EN);
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TCLR, /* timter control
reg. autoreload and start */
+ DM_TCLR_AR | DM_TCLR_ST);
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TISR, /*clear
interrupt flags */
+ bus_space_read_4(dmtimer_iot, dmtimer_ioh0, DM_TISR));
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(dmtimer_iot, dmtimer_ioh0, DM_TCRR, -ticks_per_intr);
/* set counter value to -ticks_per_intr */
+ dmtimer_wait(DM_TWPS_ALL);
+}
+
+void
+dmtimer_wait(int reg)
+{
+ while (bus_space_read_4(dmtimer_iot, dmtimer_ioh0, DM_TWPS) & reg)
+ ;
+}
+
+#if 0
+void
+microtime(struct timeval *tvp)
+{
+ int s;
+ int deltacnt;
+ u_int32_t counter, expected;
+ s = splhigh();
+
+ if (1) { /* not inited */
+ tvp->tv_sec = 0;
+ tvp->tv_usec = 0;
+ return;
+ }
+ s = splhigh();
+ counter = bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR);
+ expected = nexttickevent;
+
+ *tvp = time;
+ splx(s);
+
+ deltacnt = counter - expected + ticks_per_intr;
+
+#if 1
+ /* low frequency timer algorithm */
+ tvp->tv_usec += deltacnt * 1000000ULL / TIMER_FREQUENCY;
+#else
+ /* high frequency timer algorithm - XXX */
+ tvp->tv_usec += deltacnt / (TIMER_FREQUENCY / 1000000ULL);
+#endif
+
+ while (tvp->tv_usec >= 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+
+}
+#endif
+
+void
+dmtimer_delay(u_int usecs)
+{
+ u_int32_t clock, oclock, delta, delaycnt;
+ volatile int j;
+ int csec, usec;
+
+ if (usecs > (0x80000000 / (TIMER_FREQUENCY))) {
+ csec = usecs / 10000;
+ usec = usecs % 10000;
+
+ delaycnt = (TIMER_FREQUENCY / 100) * csec +
+ (TIMER_FREQUENCY / 100) * usec / 10000;
+ } else {
+ delaycnt = TIMER_FREQUENCY * usecs / 1000000;
+ }
+ if (delaycnt <= 1)
+ for (j = 100; j > 0; j--)
+ ;
+
+ if (dmtimer_ioh1 == 0) {
+ /* BAH */
+ for (; usecs > 0; usecs--)
+ for (j = 100; j > 0; j--)
+ ;
+ return;
+ }
+ oclock = bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR);
+ while (1) {
+ for (j = 100; j > 0; j--)
+ ;
+ clock = bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR);
+ delta = clock - oclock;
+ if (delta > delaycnt)
+ break;
+ }
+
+}
+
+void
+dmtimer_setstatclockrate(int newhz)
+{
+ int minint, statint;
+ int s;
+
+ s = splclock();
+
+ statint = ticks_per_second / newhz;
+ /* calculate largest 2^n which is smaller that just over half statint */
+ statvar = 0x40000000; /* really big power of two */
+ minint = statint / 2 + 100;
+ while (statvar > minint)
+ statvar >>= 1;
+
+ statmin = statint - (statvar >> 1);
+
+ splx(s);
+
+ /*
+ * XXX this allows the next stat timer to occur then it switches
+ * to the new frequency. Rather than switching instantly.
+ */
+}
+
+
+u_int
+dmtimer_get_timecount(struct timecounter *tc)
+{
+ return bus_space_read_4(dmtimer_iot, dmtimer_ioh1, DM_TCRR);
+}
Index: dev/intc.c
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/intc.c,v
retrieving revision 1.10
diff -u -p -u -p -r1.10 intc.c
--- dev/intc.c 10 Nov 2011 19:37:01 -0000 1.10
+++ dev/intc.c 26 Apr 2013 14:43:24 -0000
@@ -36,7 +36,7 @@
#define INTC_SIR_FIQ 0x44 /* R */
#define INTC_CONTROL 0x48 /* RW */
#define INTC_CONTROL_NEWIRQ 0x1
-#define INTC_CONTROL_NEWFIQ 0x1
+#define INTC_CONTROL_NEWFIQ 0x2
#define INTC_CONTROL_GLOBALMASK 0x1
#define INTC_PROTECTION 0x4c /* RW */
#define INTC_PROTECTION_PROT 1 /* only privileged mode */
@@ -53,33 +53,6 @@
#define INTC_PENDING_IRQn(i) 0x80+(0x20*i)+0x18 /* R */
#define INTC_PENDING_FIQn(i) 0x80+(0x20*i)+0x1c /* R */
-#define INTC_ITR0 0x80 /* R */
-#define INTC_MIR0 0x84 /* RW */
-#define INTC_CLEAR0 0x88 /* RW */
-#define INTC_SET0 0x8c /* RW */
-#define INTC_ISR_SET0 0x90 /* RW */
-#define INTC_ISR_CLEAR0 0x94 /* RW */
-#define INTC_PENDING_IRQ0 0x98 /* R */
-#define INTC_PENDING_FIQ0 0x9c /* R */
-
-#define INTC_ITR1 0xa0 /* R */
-#define INTC_MIR1 0xa4 /* RW */
-#define INTC_CLEAR1 0xa8 /* RW */
-#define INTC_SET1 0xac /* RW */
-#define INTC_ISR_SET1 0xb0 /* RW */
-#define INTC_ISR_CLEAR1 0xb4 /* RW */
-#define INTC_PENDING_IRQ1 0xb8 /* R */
-#define INTC_PENDING_FIQ1 0xbc /* R */
-
-#define INTC_ITR2 0xc0 /* R */
-#define INTC_MIR2 0xc4 /* RW */
-#define INTC_CLEAR2 0xc8 /* RW */
-#define INTC_SET2 0xcc /* RW */
-#define INTC_ISR_SET2 0xd0 /* RW */
-#define INTC_ISR_CLEAR2 0xd4 /* RW */
-#define INTC_PENDING_IRQ2 0xd8 /* R */
-#define INTC_PENDING_FIQ2 0xdc /* R */
-
#define INTC_ILRn(i) 0x100+(4*i)
#define INTC_ILR_IRQ 0x0 /* not of FIQ */
#define INTC_ILR_FIQ 0x1
@@ -112,7 +85,7 @@ volatile int softint_pending;
struct intrq intc_handler[NIRQ];
u_int32_t intc_smask[NIPL];
-u_int32_t intc_imask[3][NIPL];
+u_int32_t intc_imask[INTC_NUM_BANKS][NIPL];
bus_space_tag_t intc_iot;
bus_space_handle_t intc_ioh;
@@ -159,9 +132,8 @@ intc_attach(struct device *parent, struc
/* XXX - check power saving bit */
/* mask all interrupts */
- bus_space_write_4(intc_iot, intc_ioh, INTC_MIR0, 0xffffffff);
- bus_space_write_4(intc_iot, intc_ioh, INTC_MIR1, 0xffffffff);
- bus_space_write_4(intc_iot, intc_ioh, INTC_MIR2, 0xffffffff);
+ for (i = 0; i < INTC_NUM_BANKS; i++)
+ bus_space_write_4(intc_iot, intc_ioh, INTC_MIRn(i), 0xffffffff);
for (i = 0; i < NIRQ; i++) {
bus_space_write_4(intc_iot, intc_ioh, INTC_ILRn(i),
@@ -295,7 +267,7 @@ intc_setipl(int new)
}
#endif
ci->ci_cpl = new;
- for (i = 0; i < 3; i++)
+ for (i = 0; i < INTC_NUM_BANKS; i++)
bus_space_write_4(intc_iot, intc_ioh,
INTC_MIRn(i), intc_imask[i][new]);
bus_space_write_4(intc_iot, intc_ioh, INTC_CONTROL,
@@ -310,7 +282,7 @@ intc_intr_bootstrap(vaddr_t addr)
extern struct bus_space armv7_bs_tag;
intc_iot = &armv7_bs_tag;
intc_ioh = addr;
- for (i = 0; i < 3; i++)
+ for (i = 0; i < INTC_NUM_BANKS; i++)
for (j = 0; j < NIPL; j++)
intc_imask[i][j] = 0xffffffff;
}
Index: dev/intc.h
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/intc.h,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 intc.h
--- dev/intc.h 24 Oct 2011 22:49:07 -0000 1.2
+++ dev/intc.h 26 Apr 2013 14:43:24 -0000
@@ -36,7 +36,10 @@ int intc_splraise(int ipl);
int intc_spllower(int ipl);
void intc_setsoftintr(int si);
-#define INTC_NUM_IRQ 96
+#ifndef INTC_NUM_IRQ
+ #define INTC_NUM_IRQ 96
+#endif
+#define INTC_NUM_BANKS INTC_NUM_IRQ/32
/*
* An useful function for interrupt handlers.
Index: dev/omap.c
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/omap.c,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 omap.c
--- dev/omap.c 25 Apr 2013 23:07:17 -0000 1.4
+++ dev/omap.c 26 Apr 2013 14:43:24 -0000
@@ -66,6 +66,17 @@ struct board_dev beagleboard_devs[] = {
{ NULL, 0 }
};
+struct board_dev beaglebone_devs[] = {
+ { "prcm", 0 },
+ { "intc", 0 },
+ { "dmtimer", 0 },
+ { "dmtimer", 1 },
+ { "omdog", 0 },
+ { "ommmc", 0 }, /* HSMMC0 */
+ { "com", 0 }, /* UART0 */
+ { NULL, 0 }
+};
+
struct board_dev overo_devs[] = {
{ "prcm", 0 },
{ "intc", 0 },
@@ -134,6 +145,11 @@ omap_attach(struct device *parent, struc
printf(": BeagleBoard\n");
omap3_init();
board_devs = beagleboard_devs;
+ break;
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ printf(": BeagleBone\n");
+ am335x_init();
+ board_devs = beaglebone_devs;
break;
case BOARD_ID_OMAP3_OVERO:
printf(": Gumstix Overo\n");
Index: dev/omapvar.h
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/omapvar.h,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 omapvar.h
--- dev/omapvar.h 10 Nov 2011 19:37:01 -0000 1.1
+++ dev/omapvar.h 26 Apr 2013 14:43:24 -0000
@@ -44,6 +44,7 @@ struct omap_dev *omap_find_dev(const cha
void omap3_init(void);
void omap4_init(void);
+void am335x_init(void);
/* XXX */
void *avic_intr_establish(int irqno, int level, int (*func)(void *),
@@ -51,6 +52,7 @@ void *avic_intr_establish(int irqno, int
/* board identification - from uboot */
#define BOARD_ID_OMAP3_BEAGLE 1546
+#define BOARD_ID_AM335X_BEAGLEBONE 3589
#define BOARD_ID_OMAP3_OVERO 1798
#define BOARD_ID_OMAP4_PANDA 2791
extern uint32_t board_id;
Index: dev/omdog.c
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/omdog.c,v
retrieving revision 1.5
diff -u -p -u -p -r1.5 omdog.c
--- dev/omdog.c 15 Nov 2011 23:01:11 -0000 1.5
+++ dev/omdog.c 26 Apr 2013 14:43:24 -0000
@@ -26,7 +26,6 @@
#include <machine/intr.h>
#include <machine/bus.h>
#include <beagle/dev/omapvar.h>
-#include <beagle/dev/omgpiovar.h>
/* registers */
#define WIDR 0x00
@@ -77,7 +76,7 @@ omdog_attach(struct device *parent, stru
sc->sc_iot = oa->oa_iot;
if (bus_space_map(sc->sc_iot, oa->oa_dev->mem[0].addr,
oa->oa_dev->mem[0].size, 0, &sc->sc_ioh))
- panic("gptimer_attach: bus_space_map failed!");
+ panic("%s: bus_space_map failed!", __func__);
rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, WIDR);
Index: dev/ommmc.c
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/ommmc.c,v
retrieving revision 1.14
diff -u -p -u -p -r1.14 ommmc.c
--- dev/ommmc.c 15 Nov 2011 21:46:44 -0000 1.14
+++ dev/ommmc.c 26 Apr 2013 14:43:25 -0000
@@ -39,7 +39,7 @@
#define MMCHS3_ADDR 0x480AD000
/*
- * NOTE: on OMAP4430 these registers skew by 0x100
+ * NOTE: on OMAP4430/AM335x these registers skew by 0x100
* this is handled by mapping at base address + 0x100
* then all but the REVISION register is 'correctly' mapped.
*/
@@ -183,8 +183,6 @@
void ommmc_attach(struct device *parent, struct device *self, void *args);
-#include <machine/bus.h>
-
struct ommmc_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
@@ -358,11 +356,12 @@ ommmc_attach(struct device *parent, stru
struct sdmmcbus_attach_args saa;
int baseaddr;
int error = 1;
+ u_int32_t rev;
/* XXX - ICLKEN, FCLKEN? */
baseaddr = oa->oa_dev->mem[0].addr;
- if (board_id == BOARD_ID_OMAP4_PANDA) {
+ if (board_id == BOARD_ID_OMAP4_PANDA || board_id ==
BOARD_ID_AM335X_BEAGLEBONE) {
/* omap4430 has mmc registers offset +0x100, but not revision */
baseaddr += 0x100;
}
@@ -370,9 +369,7 @@ ommmc_attach(struct device *parent, stru
sc->sc_iot = oa->oa_iot;
if (bus_space_map(sc->sc_iot, baseaddr, oa->oa_dev->mem[0].size,
0, &sc->sc_ioh))
- panic("omgpio_attach: bus_space_map failed!");
-
- printf("\n");
+ panic("%s: bus_space_map failed!", __func__);
/* XXX DMA channels? */
/* FIXME prcm_enableclock(sc->clockbit); */
@@ -394,6 +391,10 @@ ommmc_attach(struct device *parent, stru
* Reset the host controller and enable interrupts.
*/
(void)ommmc_host_reset(sc);
+
+ /* read revision */
+ rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MMCHS_REV);
+ printf(" rev %d.%d\n", (rev & 0xf0000000) >> 28, (rev & 0x0f000000) >>
24);
#if 0
/* Determine host capabilities. */
Index: dev/omusbtll.c
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/omusbtll.c,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 omusbtll.c
--- dev/omusbtll.c 10 Nov 2011 19:37:01 -0000 1.4
+++ dev/omusbtll.c 26 Apr 2013 14:43:25 -0000
@@ -112,7 +112,7 @@ omusbtll_attach(struct device *parent, s
sc->sc_iot = oa->oa_iot;
if (bus_space_map(sc->sc_iot, oa->oa_dev->mem[0].addr,
oa->oa_dev->mem[0].size, 0, &sc->sc_ioh)) {
- printf("omgpio_attach: bus_space_map failed!\n");
+ printf("%s: bus_space_map failed!\n", __func__);
return;
}
Index: dev/prcm.c
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/prcm.c,v
retrieving revision 1.9
diff -u -p -u -p -r1.9 prcm.c
--- dev/prcm.c 10 Nov 2011 19:37:01 -0000 1.9
+++ dev/prcm.c 26 Apr 2013 14:43:25 -0000
@@ -185,7 +185,10 @@ prcm_attach(struct device *parent, struc
reg = bus_space_read_4(prcm_iot, prcm_ioh, PRCM_REVISION);
printf(" rev %d.%d\n", reg >> 4 & 0xf, reg & 0xf);
-
+
+ if (board_id == BOARD_ID_AM335X_BEAGLEBONE)
+ return;
+
/* Setup the 120MHZ DPLL5 clock, to be used by USB. */
prcm_setup_dpll5();
@@ -241,31 +244,55 @@ prcm_attach(struct device *parent, struc
void
prcm_setclock(int clock, int speed)
{
-#if 1
u_int32_t oreg, reg, mask;
- if (clock == 1) {
- oreg = bus_space_read_4(prcm_iot, prcm_ioh, CM_CLKSEL_WKUP);
- mask = 1;
- reg = (oreg &~mask) | (speed & mask);
- printf(" prcm_setclock old %08x new %08x", oreg, reg );
- bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL_WKUP, reg);
- } else if (clock >= 2 && clock <= 9) {
- int shift = (clock-2);
- oreg = bus_space_read_4(prcm_iot, prcm_ioh, CM_CLKSEL_PER);
-
- mask = 1 << (mask);
- reg = (oreg & ~mask) | ( (speed << shift) & mask);
- printf(" prcm_setclock old %08x new %08x", oreg, reg);
-
- bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL_PER, reg);
- } else
- panic("prcm_setclock invalid clock %d", clock);
-#endif
+
+ if (board_id == BOARD_ID_AM335X_BEAGLEBONE) {
+ /* set CLKSEL register */
+ if (clock == 1) {
+ /* for timer 2 */
+ oreg = bus_space_read_4(prcm_iot, prcm_ioh,
+ AM335X_PRCM_CM_DPLL_CLKSEL_TIMER2_CLK);
+ mask = 3;
+ reg = oreg & ~mask;
+ reg |=0x02;
+ bus_space_write_4(prcm_iot, prcm_ioh,
+ AM335X_PRCM_CM_DPLL_CLKSEL_TIMER2_CLK, reg);
+ } else if (clock == 2) {
+ /* for timer 3 */
+ oreg = bus_space_read_4(prcm_iot, prcm_ioh,
+ AM335X_PRCM_CM_DPLL_CLKSEL_TIMER3_CLK);
+ mask = 3;
+ reg = oreg & ~mask;
+ reg |=0x02;
+ bus_space_write_4(prcm_iot, prcm_ioh,
+ AM335X_PRCM_CM_DPLL_CLKSEL_TIMER3_CLK, reg);
+ }
+ } else {
+ if (clock == 1) {
+ oreg = bus_space_read_4(prcm_iot, prcm_ioh,
CM_CLKSEL_WKUP);
+ mask = 1;
+ reg = (oreg &~mask) | (speed & mask);
+ printf(" prcm_setclock old %08x new %08x", oreg, reg );
+ bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL_WKUP,
reg);
+ } else if (clock >= 2 && clock <= 9) {
+ int shift = (clock-2);
+ oreg = bus_space_read_4(prcm_iot, prcm_ioh,
CM_CLKSEL_PER);
+
+ mask = 1 << (shift);
+ reg = (oreg & ~mask) | ( (speed << shift) & mask);
+ printf(" prcm_setclock old %08x new %08x", oreg, reg);
+
+ bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL_PER,
reg);
+ } else
+ panic("prcm_setclock invalid clock %d", clock);
+ }
}
void
prcm_enableclock(int bit)
{
+ if (board_id == BOARD_ID_AM335X_BEAGLEBONE)
+ return;
u_int32_t fclk, iclk, fmask, imask, mbit;
int freg, ireg, reg;
printf("prcm_enableclock %d:", bit);
@@ -297,6 +324,29 @@ prcm_enableclock(int bit)
}
printf ("\n");
}
+
+void
+prcm_enablemodule(uint32_t reg)
+{
+ uint32_t clkctrl;
+
+ switch (board_id) {
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ /*set enable bits in CLKCTRL register */
+ clkctrl = bus_space_read_4(prcm_iot, prcm_ioh, reg);
+ clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK;
+ clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE;
+ bus_space_write_4(prcm_iot, prcm_ioh, reg, clkctrl);
+ /* wait until module is enabled */
+ while (bus_space_read_4(prcm_iot, prcm_ioh, reg) & 0x30000)
+ ;
+ break;
+ default:
+ /* ??? */
+ break;
+ }
+}
+
/*
* OMAP35xx Power, Reset, and Clock Management Reference Guide
Index: dev/prcmvar.h
===================================================================
RCS file: /cvs/src/sys/arch/beagle/dev/prcmvar.h,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 prcmvar.h
--- dev/prcmvar.h 13 Feb 2010 06:03:37 -0000 1.4
+++ dev/prcmvar.h 26 Apr 2013 14:43:25 -0000
@@ -20,6 +20,35 @@ void prcm_setclock(int clock, int speed)
#define PRCM_CLK_SPEED_SYS 1
void prcm_enableclock(int bit);
+void prcm_enablemodule(uint32_t reg);
+
+#define AM335X_CLKCTRL_MODULEMODE_ENABLE 2
+#define AM335X_CLKCTRL_MODULEMODE_DISABLE 0
+#define AM335X_CLKCTRL_MODULEMODE_MASK 0x00000003
+
+#define AM335X_PRCM_CM_PER 0x0000
+#define AM335X_PRCM_CM_PER_MMC0_CLKCTRL 0x003c
+#define AM335X_PRCM_CM_PER_TIMER2_CLKCTRL 0x0080
+#define AM335X_PRCM_CM_PER_TIMER3_CLKCTRL 0x0084
+#define AM335X_PRCM_CM_WKUP 0x0400
+#define AM335X_PRCM_CM_WKUP_TIMER0_CLKCTRL 0x0410
+#define AM335X_PRCM_CM_DPLL 0x0500
+#define AM335X_PRCM_CM_DPLL_CLKSEL_TIMER2_CLK 0x0508
+#define AM335X_PRCM_CM_DPLL_CLKSEL_TIMER3_CLK 0x050c
+#define AM335X_PRCM_CM_MPU 0x0600
+#define AM335X_PRCM_CM_DEVICE 0x0700
+#define AM335X_PRCM_CM_RTC 0x0800
+#define AM335X_PRCM_CM_GFX 0x0900
+#define AM335X_PRCM_CM_CEFUSE 0x0a00
+
+#define AM335X_PRCM_PRM_IRQ 0x0b00
+#define AM335X_PRCM_PRM_PER 0x0c00
+#define AM335X_PRCM_PRM_WKUP 0x0d00
+#define AM335X_PRCM_PRM_MPU 0x0e00
+#define AM335X_PRCM_PRM_DEVICE 0x0f00
+#define AM335X_PRCM_PRM_RTC 0x1000
+#define AM335X_PRCM_PRM_GFX 0x1100
+#define AM335X_PRCM_PRM_CEFUSE 0x1200
#define CM_FCLKEN1_CORE 0x0a00
#define CM_FCLKEN1_CORE_MSK 0x41fffe00
Index: pmap.c
===================================================================
RCS file: /cvs/src/sys/arch/arm/arm/pmap.c,v
retrieving revision 1.38
diff -u -p -u -p -r1.38 pmap.c
--- pmap.c 5 Dec 2012 23:20:11 -0000 1.38
+++ pmap.c 26 Apr 2013 14:42:58 -0000
@@ -2607,7 +2607,6 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
* OK, at this point, we know we're doing write-protect operation.
* If the pmap is active, write-back the range.
*/
- pmap_dcache_wb_range(pm, sva, eva - sva, FALSE, FALSE);
flush = ((eva - sva) >= (PAGE_SIZE * 4)) ? 0 : -1;
flags = 0;
@@ -2629,6 +2628,9 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
if ((pte = *ptep) != 0 && (pte & L2_S_PROT_W) != 0) {
struct vm_page *pg;
u_int f;
+
+ pmap_dcache_wb_range(pm, sva, PAGE_SIZE, FALSE,
+ FALSE);
pg = PHYS_TO_VM_PAGE(l2pte_pa(pte));
pte &= ~L2_S_PROT_W;