From owner-p4-projects@FreeBSD.ORG Thu Mar 12 12:53:35 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D1684106567F; Thu, 12 Mar 2009 12:53:34 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 359D3106567B for ; Thu, 12 Mar 2009 12:53:34 +0000 (UTC) (envelope-from antab@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 1D1EA8FC22 for ; Thu, 12 Mar 2009 12:53:34 +0000 (UTC) (envelope-from antab@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n2CCrX9s090729 for ; Thu, 12 Mar 2009 12:53:33 GMT (envelope-from antab@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n2CCrX1A090727 for perforce@freebsd.org; Thu, 12 Mar 2009 12:53:33 GMT (envelope-from antab@FreeBSD.org) Date: Thu, 12 Mar 2009 12:53:33 GMT Message-Id: <200903121253.n2CCrX1A090727@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to antab@FreeBSD.org using -f From: Arnar Mar Sig To: Perforce Change Reviews Cc: Subject: PERFORCE change 159118 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Mar 2009 12:53:42 -0000 http://perforce.freebsd.org/chv.cgi?CH=159118 Change 159118 by antab@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 __FBSDID("$FreeBSD: $"); @@ -40,29 +46,167 @@ #include #include #include +#include +#include #include +#include #include #include +#include +#include #include +#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 #include -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