PERFORCE change 159118 for review
Arnar Mar Sig
antab at FreeBSD.org
Thu Mar 12 05:53:42 PDT 2009
http://perforce.freebsd.org/chv.cgi?CH=159118
Change 159118 by antab at antab_farm on 2009/03/12 12:52:35
- Add at32_tc to serve as bus to attach TC channels to. Each TC module has 3 channels.
- Add at32_tc_channel driver stub to test at32_tc.
- Add clock driver for system clock, attaches to at32_tc. This driver calls hardclock().
- Changes to intr code to make interrupts work.
- Rearrange NGW100 kernel config to match GENERIC on i386/amd64
Affected files ...
.. //depot/projects/avr32/src/sys/avr32/avr32/at32.c#6 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_tc.c#1 add
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_tc_channel.c#1 add
.. //depot/projects/avr32/src/sys/avr32/avr32/clock.c#5 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/exception.S#8 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/intr.c#5 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#14 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/stack_machdep.c#3 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/switch.S#8 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/vm_machdep.c#9 edit
.. //depot/projects/avr32/src/sys/avr32/conf/NGW100#13 edit
.. //depot/projects/avr32/src/sys/avr32/conf/cpu/at32ap700x.hints#2 edit
.. //depot/projects/avr32/src/sys/avr32/include/reg_tc.h#1 add
.. //depot/projects/avr32/src/sys/conf/files.avr32#13 edit
Differences ...
==== //depot/projects/avr32/src/sys/avr32/avr32/at32.c#6 (text+ko) ====
@@ -240,11 +240,11 @@
switch (type) {
case SYS_RES_IRQ:
rle->res = rman_reserve_resource(&sc->sc_irq_rman,
- start, end, count, flags, child);
+ start, end, count, flags, child);
break;
case SYS_RES_MEMORY:
rle->res = rman_reserve_resource(&sc->sc_mem_rman,
- start, end, count, flags, child);
+ start, end, count, flags, child);
if (rle->res != NULL) {
rman_set_bustag(rle->res, 0);
rman_set_bushandle(rle->res, start);
==== //depot/projects/avr32/src/sys/avr32/avr32/clock.c#5 (text+ko) ====
@@ -24,6 +24,12 @@
* SUCH DAMAGE.
*/
+/*
+ * System clock. We use one TC channel to implement it. The channel used
+ * depends on device hints and can be any of the TC channels. Clock select 0
+ * is wired to 32KHz osc on AT32AP700x
+ */
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: $");
@@ -40,29 +46,167 @@
#include <sys/time.h>
#include <sys/timetc.h>
#include <sys/cpu.h>
+#include <sys/devclk.h>
+#include <machine/bus.h>
#include <machine/clock.h>
+#include <machine/cpu.h>
#include <machine/reg.h>
#include <machine/reg_sys.h>
+#include <machine/reg_tc.h>
+#include <machine/trap.h>
#include <machine/debug.h>
+#define RD4(off) \
+ bus_space_read_4(sc->bst, sc->bsh, (off))
+#define WR4(off, val) \
+ bus_space_write_4(sc->bst, sc->bsh, (off), (val))
+
/* Prototypes */
-static unsigned count_get_timecount(struct timecounter *);
+static int clock_probe(device_t);
+static int clock_attach(device_t);
+static int clock_detach(device_t);
+static int clock_intr(void *arg);
+static unsigned clock_get_timecount(struct timecounter *);
/* Variable and private data */
-uint64_t clock_cpu_frequency; /* Finzd batter way for this */
+uint64_t clock_cpu_frequency; /* Find batter way for this */
static uint64_t cycles_per_usec;
static uint64_t cycles_per_hz;
-static struct timecounter count_timecounter = {
- count_get_timecount, /* get_timecount */
+static struct timecounter clock_timecounter = {
+ clock_get_timecount, /* get_timecount */
0, /* no poll_pps */
0xffffffffu, /* counter_mask */
- 0, /* frequency */
+ 32768, /* frequency */
"AVR32", /* name */
1000, /* quality (adjusted in code) */
};
+struct clock_softc {
+ struct resource *regs_res;
+ struct resource *irq_res;
+ void *intrhand;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ uint32_t ticks;
+} *clock_softc;
+static device_method_t clock_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, clock_probe),
+ DEVMETHOD(device_attach, clock_attach),
+ DEVMETHOD(device_detach, clock_detach),
+ {0, 0},
+};
+static driver_t clock_driver = {
+ "clock",
+ clock_methods,
+ sizeof(struct clock_softc),
+};
+static devclass_t clock_devclass;
+DRIVER_MODULE(clock, at32_tc, clock_driver, clock_devclass, 0, 0);
/* Code */
+static int
+clock_probe(device_t dev)
+{
+ if (device_get_unit(dev) != 0) {
+ panic("Can't attach more then one system clock");
+ }
+
+ device_set_desc(dev, "System clock");
+ return (0);
+}
+
+static int
+clock_attach(device_t dev)
+{
+ struct clock_softc *sc = device_get_softc(dev);
+ int rid, err = ENOMEM;
+
+ /* Make sure device clock is enabled before writing */
+ devclk_enable(dev);
+
+ /* Setup register space */
+ rid = 0;
+ sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->regs_res == NULL) {
+ goto errout;
+ }
+ sc->bsh = rman_get_bushandle(sc->regs_res);
+ sc->bst = rman_get_bustag(sc->regs_res);
+
+ /* Setup interrupt */
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->irq_res == NULL) {
+ goto errout;
+ }
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK, clock_intr, NULL,
+ NULL, &sc->intrhand);
+ if (err) {
+ goto errout;
+ }
+
+ clock_softc = sc;
+ return (0);
+
+errout:
+ clock_detach(dev);
+ return (err);
+}
+
+static int
+clock_detach(device_t dev)
+{
+ struct clock_softc *sc = device_get_softc(dev);
+
+ if (sc->intrhand != NULL) {
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = NULL;
+ }
+ if (sc->regs_res != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = NULL;
+ }
+ if (sc->regs_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->regs_res), sc->regs_res);
+ sc->regs_res = NULL;
+ }
+
+ /* Turn off device clock */
+ devclk_disable(dev);
+ return (0);
+}
+
+static int
+clock_intr(void *arg)
+{
+ struct trapframe *tf = arg;
+ struct clock_softc *sc = clock_softc;
+ register_t sr;
+ int ret = FILTER_STRAY;;
+
+ /*
+ * Clock interrupt is shared with other TC channels, check if this
+ * interrupt is for us, reading SR also clears any pending triggers
+ */
+
+ critical_enter();
+ sr = RD4(AT32_TC_SR);
+ if (bit_value(TC, SR, CPCS, sr)) {
+ sc->ticks += clock_timecounter.tc_frequency / hz;
+
+ hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf));
+ ret = FILTER_HANDLED;
+ }
+ critical_exit();
+
+ return (ret);
+}
+
void
cpu_startprofclock(void)
{
@@ -85,16 +229,52 @@
void
cpu_initclocks(void)
{
- count_timecounter.tc_frequency = clock_cpu_frequency;
+ struct clock_softc *sc = clock_softc;
+ uint32_t rel_value, new_hz;
+
+ if (clock_softc == NULL) {
+ panic("No system clock set");
+ }
+
+ /*
+ * Calculate Register C compare value.
+ */
+ rel_value = clock_timecounter.tc_frequency / hz;
+ if (rel_value < 1) {
+ rel_value = 1;
+ }
+ new_hz = clock_timecounter.tc_frequency / rel_value;
+ if (hz != new_hz) {
+ printf("Cannot get %d Hz clock; using %d Hz instead\n", hz, new_hz);
+ hz = new_hz;
+ tick = 1000000 / hz;
+ }
+
+ /* Set counter mode */
+ WR4(AT32_TC_CMR,
+ bit_offset(TC, CMR, WAVE) |
+ 2 << bit_shift(TC, CMR, WAVSEL));
+
+ /* RC value to interrupt on */
+ WR4(AT32_TC_RC, rel_value);
+
+ /* Enable interupt RC compare */
+ WR4(AT32_TC_IER, bit_offset(TC, IER, CPCS));
+
+ /* Enable clock and reset counter */
+ WR4(AT32_TC_CCR,
+ bit_offset(TC, CCR, CLKEN) |
+ bit_offset(TC, CCR, SWTRG));
+
cycles_per_hz = clock_cpu_frequency / hz;
cycles_per_usec = (clock_cpu_frequency / (1000 * 1000));
- tc_init(&count_timecounter);
+ tc_init(&clock_timecounter);
}
static unsigned
-count_get_timecount(struct timecounter *tc)
+clock_get_timecount(struct timecounter *tc)
{
- return sysreg_read(COUNT);
+ return (clock_softc->ticks);
}
/*
==== //depot/projects/avr32/src/sys/avr32/avr32/exception.S#8 (text+ko) ====
@@ -223,7 +223,6 @@
mov r12, AT32_SYS_ECR
mov r11, sp
csrf AT32_SYS_SR_EM
- csrf AT32_SYS_SR_GM
rcall trap_handle_breakpoint
POP_TRAPFRAME(DBG)
retd
==== //depot/projects/avr32/src/sys/avr32/avr32/intr.c#5 (text+ko) ====
@@ -46,6 +46,8 @@
/* Private data */
static struct intr_event *intr_event[IRQ_COUNT];
+static int intrcnt_tab[IRQ_COUNT];
+static int intrcnt_index = 0;
extern vm_offset_t _evba;
/* Code */
@@ -62,7 +64,10 @@
void
intr_restore(register_t s)
{
- __asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_GM));
+ register_t sr;
+
+ sr = sysreg_read(SR) & ~INTR_MASK;
+ sysreg_write(SR, sr | (s & INTR_MASK));
}
void
@@ -102,6 +107,7 @@
if (intr_event_handle(intr_event[irq], tf) != 0) {
panic("stray interrupt %d, priority %d\n", irq, pri);
}
+ intrcnt[intrcnt_tab[irq]]++;
}
void
@@ -141,11 +147,16 @@
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0, irq,
(mask_fn)avr32_mask_irq, (mask_fn)avr32_unmask_irq,
- NULL, NULL, "intr%d:", irq);
+ NULL, NULL, "irq%d:", irq);
if (error) {
return;
}
intr_event[irq] = event;
+ snprintf(intrnames + (MAXCOMLEN + 1) * intrcnt_index,
+ MAXCOMLEN + 1,
+ "irq%d: %-*s", irq, MAXCOMLEN, name);
+ intrcnt_tab[irq] = intrcnt_index;
+ intrcnt_index++;
}
intr_event_add_handler(event, name, filt, hand, arg,
intr_priority(flags), flags, cookiep);
==== //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#14 (text+ko) ====
@@ -1079,7 +1079,7 @@
pd_entry_t* pd = (pd_entry_t *)sysreg_read(PTBR);
struct thread *td = curthread;
pt_entry_t *ent;
- register_t mmucr, intr;
+ register_t mmucr;
ent = (pt_entry_t *)pd[pd_index_from_va(tlbear)];
if (ent) {
@@ -1092,7 +1092,6 @@
* hit memory needs tlb lookups from here one.
*/
__asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_EM));
- __asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_GM));
struct proc *p = curproc;
vm_prot_t ftype;
@@ -1156,9 +1155,6 @@
*ent |= PTE_DIRTY;
}
- /* XXX: Exceptions are enabled in the long path */
- intr = intr_disable();
-
mmucr = sysreg_read(MMUCR);
mmucr &= ~bit_mask(SYS, MMUCR, DRP);
mmucr |= tlb_at << bit_shift(SYS, MMUCR, DRP);
@@ -1180,9 +1176,6 @@
tlb_at = KSTACK_PAGES;
}
- /* XXX */
- intr_restore(intr);
-
out:
if (!TRAPF_USERMODE(tf)) {
return;
==== //depot/projects/avr32/src/sys/avr32/avr32/stack_machdep.c#3 (text+ko) ====
@@ -19,7 +19,7 @@
(KSTACK_PAGES * PAGE_SIZE)) {
break;
}
- if (frame->lr == NULL) {
+ if (frame->lr == 0) {
break;
}
==== //depot/projects/avr32/src/sys/avr32/avr32/switch.S#8 (text+ko) ====
@@ -58,6 +58,7 @@
/**
* r12: Pointer struct thread
* r11: Pmap
+ * r10: Saved SR
* NOTE: This code is messy and i need to find better way to do this.
*/
ENTRY(restorectx)
@@ -72,8 +73,11 @@
* r4: Misc
* r3: tlbehi save
* r2: Address of PCB
+ * r1: Saved SR
*/
+ mov r1, r10
+
/* Load PCB and PD address */
ld.w r2, r12[TD_PCB]
@@ -137,6 +141,7 @@
mtsr AT32_SYS_PTBR, r11 /* Point lookups to new pmap */
mtsr AT32_SYS_TLBEHI, r10 /* Set TLBEHI (ASID for new td) */
nop /* Wait for mtsr */
+ mtsr AT32_SYS_SR, r1 /* Restore saved SR */
ld.w r4, r2++ /* Load status register */
musfr r4 /* Set status register */
sub r2, -4 /* Skip PC */
==== //depot/projects/avr32/src/sys/avr32/avr32/vm_machdep.c#9 (text+ko) ====
@@ -50,7 +50,7 @@
#include <machine/pcb.h>
#include <machine/debug.h>
-void restorectx(struct thread *td, pmap_t pmap);
+void restorectx(struct thread *td, pmap_t pmap, register_t sr);
/*
* Finish a fork operation, with process p2 nearly set up.
@@ -209,11 +209,16 @@
void
cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx)
{
+ register_t sr;
pmap_t pmap;
+ /* Disable interrupts, they will get enabled in restorectx() */
+ sr = intr_disable();
+
if (!savectx(old->td_pcb)) {
old->td_lock = mtx;
PCPU_SET(curthread, new);
+ PCPU_SET(curpcb, curthread->td_pcb);
pmap = vmspace_pmap(new->td_proc->p_vmspace);
pmap_activate(new);
@@ -222,7 +227,7 @@
pmap, new->td_kstack,
new->td_kstack + (KSTACK_PAGES * PAGE_SIZE) - 1); */
- restorectx(new, pmap);
+ restorectx(new, pmap, sr);
/* We should not get here. */
panic("cpu_switch: restorectx() returned");
==== //depot/projects/avr32/src/sys/avr32/conf/NGW100#13 (text+ko) ====
@@ -9,48 +9,69 @@
hints "cpu/at32ap700x.hints" # Hints for all buildin devices
hints "cpu/at32ap7000.hints" # Hints for all buildin devices
hints "NGW100.hints"
+
+# Uncomment to boot from onboard flash
options ROOTDEVNAME=\"ufs:cfid0h1\"
+# Uncomment to boot from ethernet
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_COMPAT
+
makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
-#options VERBOSE_SYSINIT
-options DDB
-options KDB
-#options GDB
-options SCHED_4BSD #4BSD scheduler
-options INET #InterNETworking
-options NFSCLIENT #Network Filesystem Client
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
-options PSEUDOFS #Pseudo-filesystem framework
+options SCHED_4BSD # 4BSD scheduler
+#options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+#options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
-options SYSVSHM #SYSV-style shared memory
-options SYSVMSG #SYSV-style message queues
-options SYSVSEM #SYSV-style semaphores
+options MD_ROOT # MD is a potential root device
+options NFSCLIENT # Network Filesystem Client
+options NFSSERVER # Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+#options MSDOSFS # MSDOS Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+#options KTRACE # ktrace(1) support
+options STACK # stack(9) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+#options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+#options AUDIT # Security event auditing
+#options KDTRACE_HOOKS # Kernel DTrace hooks
# Debugging for use in -current
options DIAGNOSTIC
+options KDB # Enable kernel debugger support.
+options DDB # Support DDB
+#options GDB # Support remote GDB
options INVARIANTS #Enable calls of extra sanity checking
options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
options WITNESS #Enable checks to detect deadlocks and cycles
#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
-#options WITNESS_KDB
+
device at32_intc # Interrupt controller
device at32_hmatrix # HSB Bus Matrix
device at32_sdramc # SDRAM controller
device at32_smc # Static memory controller
device at32_pm # Power Manager
-device at32_rtc # Real Time Counter (System clock)
+device at32_rtc # Real Time Counter
device at32_pio # Peripheral IO
-#device mii # Requred for ate
-#device ate # MACB Ethernet driver
+device at32_tc # Timer/Counter (REQUIRED: Used for system clock)
+device at32_tc_channel # Timer/Counter channel
+device mii # Requred for ate
+device ate # MACB Ethernet driver
-#device gpio # GPIO framework
device uart # USART support
#device atmel_twi # TWI (I2C) support
#device atmel_ssc # Sync Serial controller
@@ -62,9 +83,13 @@
device geom_hints
# Pseudo devices.
-device loop
-device random
-device ether
-device md
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+#device tun # Packet tunnel.
+#device pty # BSD-style compatibility pseudo ttys
+#device md # Memory "disks"
+#device gif # IPv6 and IPv4 tunneling
+#device faith # IPv6-to-IPv4 relaying (translation)
#device mmc
#device mmcsd
==== //depot/projects/avr32/src/sys/avr32/conf/cpu/at32ap700x.hints#2 (text+ko) ====
@@ -122,11 +122,30 @@
hint.at32_tc.0.msize="0x400"
hint.at32_tc.0.irq="22"
+hint.at32_tc_channel.0.at="at32_tc0"
+hint.at32_tc_channel.0.offset="0x00"
+
+hint.at32_tc_channel.1.at="at32_tc0"
+hint.at32_tc_channel.1.offset="0x40"
+
+hint.at32_tc_channel.2.at="at32_tc0"
+hint.at32_tc_channel.2.offset="0x80"
+
hint.at32_tc.1.at="at32bus0"
hint.at32_tc.1.maddr="0xFFF01000"
hint.at32_tc.1.msize="0x400"
hint.at32_tc.1.irq="23"
+hint.at32_tc_channel.3.at="at32_tc1"
+hint.at32_tc_channel.3.offset="0x00"
+
+hint.at32_tc_channel.4.at="at32_tc1"
+hint.at32_tc_channel.4.offset="0x40"
+
+# Channel 3 on TC1 is used for system clock
+hint.clock.0.at="at32_tc1"
+hint.clock.0.offset="0x80"
+
hint.at32_pwm.0.at="at32bus0"
hint.at32_pwm.0.maddr="0xFFF01400"
hint.at32_pwm.0.msize="0x400"
==== //depot/projects/avr32/src/sys/conf/files.avr32#13 (text+ko) ====
@@ -28,13 +28,15 @@
avr32/avr32/stack_machdep.c optional ddb | stack
avr32/avr32/gdb_machdep.c optional gdb
+avr32/avr32/at32_hmatrix.c optional at32_hmatrix
avr32/avr32/at32_intc.c optional at32_intc
+avr32/avr32/at32_pio.c optional at32_pio
avr32/avr32/at32_pm.c optional at32_pm
-avr32/avr32/at32_hmatrix.c optional at32_hmatrix
avr32/avr32/at32_rtc.c optional at32_rtc
-avr32/avr32/at32_pio.c optional at32_pio
avr32/avr32/at32_sdramc.c optional at32_sdramc
avr32/avr32/at32_smc.c optional at32_smc
+avr32/avr32/at32_tc.c optional at32_tc
+avr32/avr32/at32_tc_channel.c optional at32_tc_channel
dev/mmc/atmel_mci.c optional atmel_mci
dev/spibus/atmel_spi.c optional atmel_spi
avr32/avr32/busdma_machdep.c optional at32_mci
@@ -53,6 +55,7 @@
libkern/qdivrem.c standard
#libkern/udivdi3.c standard
#libkern/umoddi3.c standard
+libkern/memset.c standard
avr32/avr32/in_cksum.c optional inet
More information about the p4-projects
mailing list