diff options
author | grehan <grehan@FreeBSD.org> | 2013-07-19 03:27:04 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2013-07-19 03:27:04 +0000 |
commit | 749888363db1320e1cc3818fcd71e411c3a955ca (patch) | |
tree | e4dd80ba19e005ead5dfb35b03225d5fb4926884 /sys/arm | |
parent | c8195f5331ccad33ad4e265362523f51b96abd5c (diff) | |
parent | 61d6ee86f76db7ef69b0748be4d4b6e14ffc7109 (diff) | |
download | FreeBSD-src-749888363db1320e1cc3818fcd71e411c3a955ca.zip FreeBSD-src-749888363db1320e1cc3818fcd71e411c3a955ca.tar.gz |
IFC @ r253461
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/arm/db_trace.c | 4 | ||||
-rw-r--r-- | sys/arm/arm/elf_trampoline.c | 23 | ||||
-rw-r--r-- | sys/arm/arm/generic_timer.c | 56 | ||||
-rw-r--r-- | sys/arm/arm/pmap-v6.c | 2 | ||||
-rw-r--r-- | sys/arm/arm/trap.c | 12 | ||||
-rw-r--r-- | sys/arm/arm/vfp.c | 39 | ||||
-rw-r--r-- | sys/arm/arm/vm_machdep.c | 2 | ||||
-rw-r--r-- | sys/arm/broadcom/bcm2835/bcm2835_fb.c | 11 | ||||
-rw-r--r-- | sys/arm/broadcom/bcm2835/bcm2835_mbox.c | 102 | ||||
-rw-r--r-- | sys/arm/broadcom/bcm2835/bcm2835_mbox.h | 3 | ||||
-rw-r--r-- | sys/arm/broadcom/bcm2835/files.bcm2835 | 2 | ||||
-rw-r--r-- | sys/arm/broadcom/bcm2835/std.bcm2835 | 7 | ||||
-rw-r--r-- | sys/arm/broadcom/bcm2835/std.rpi | 12 | ||||
-rw-r--r-- | sys/arm/conf/BEAGLEBONE | 4 | ||||
-rw-r--r-- | sys/arm/conf/RPI-B | 13 | ||||
-rw-r--r-- | sys/arm/ti/am335x/am335x_pmic.c | 8 | ||||
-rw-r--r-- | sys/arm/ti/am335x/am335x_usbss.c | 481 | ||||
-rw-r--r-- | sys/arm/ti/am335x/files.am335x | 1 | ||||
-rw-r--r-- | sys/arm/ti/ti_mmchs.c | 17 | ||||
-rw-r--r-- | sys/arm/ti/ti_mmchs.h | 6 |
20 files changed, 674 insertions, 131 deletions
diff --git a/sys/arm/arm/db_trace.c b/sys/arm/arm/db_trace.c index 6b72cde..99c27fc 100644 --- a/sys/arm/arm/db_trace.c +++ b/sys/arm/arm/db_trace.c @@ -515,11 +515,11 @@ db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only) db_printsym(scp, DB_STGY_PROC); db_printf("\n"); #ifdef __PROG26 - db_printf("scp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV] & R15_PC); + db_printf("\tscp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV] & R15_PC); db_printsym(frame[FR_RLV] & R15_PC, DB_STGY_PROC); db_printf(")\n"); #else - db_printf("scp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV]); + db_printf("\tscp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV]); db_printsym(frame[FR_RLV], DB_STGY_PROC); db_printf(")\n"); #endif diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index fe03adf..87be924 100644 --- a/sys/arm/arm/elf_trampoline.c +++ b/sys/arm/arm/elf_trampoline.c @@ -49,42 +49,59 @@ void _start(void); void __start(void); void __startC(void); +extern unsigned int cpufunc_id(void); +extern void armv6_idcache_wbinv_all(void); +extern void armv7_idcache_wbinv_all(void); +extern void do_call(void *, void *, void *, int); + #define GZ_HEAD 0xa #ifdef CPU_ARM7TDMI #define cpu_idcache_wbinv_all arm7tdmi_cache_flushID +extern void arm7tdmi_cache_flushID(void); #elif defined(CPU_ARM8) #define cpu_idcache_wbinv_all arm8_cache_purgeID +extern void arm8_cache_purgeID(void); #elif defined(CPU_ARM9) #define cpu_idcache_wbinv_all arm9_idcache_wbinv_all +extern void arm9_idcache_wbinv_all(void); #elif defined(CPU_FA526) || defined(CPU_FA626TE) #define cpu_idcache_wbinv_all fa526_idcache_wbinv_all +extern void fa526_idcache_wbinv_all(void); #elif defined(CPU_ARM9E) #define cpu_idcache_wbinv_all armv5_ec_idcache_wbinv_all +extern void armv5_ec_idcache_wbinv_all(void); #elif defined(CPU_ARM10) #define cpu_idcache_wbinv_all arm10_idcache_wbinv_all +extern void arm10_idcache_wbinv_all(void); #elif defined(CPU_ARM1136) || defined(CPU_ARM1176) #define cpu_idcache_wbinv_all armv6_idcache_wbinv_all #elif defined(CPU_SA110) || defined(CPU_SA1110) || defined(CPU_SA1100) || \ defined(CPU_IXP12X0) #define cpu_idcache_wbinv_all sa1_cache_purgeID +extern void sa1_cache_purgeID(void); #elif defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_XSCALE_80219) #define cpu_idcache_wbinv_all xscale_cache_purgeID +extern void xscale_cache_purgeID(void); #elif defined(CPU_XSCALE_81342) #define cpu_idcache_wbinv_all xscalec3_cache_purgeID +extern void xscalec3_cache_purgeID(void); #elif defined(CPU_MV_PJ4B) #if !defined(SOC_MV_ARMADAXP) #define cpu_idcache_wbinv_all armv6_idcache_wbinv_all +extern void armv6_idcache_wbinv_all(void); #else #define cpu_idcache_wbinv_all() armadaxp_idcache_wbinv_all #endif #endif /* CPU_MV_PJ4B */ #ifdef CPU_XSCALE_81342 #define cpu_l2cache_wbinv_all xscalec3_l2cache_purge +extern void xscalec3_l2cache_purge(void); #elif defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY) #define cpu_l2cache_wbinv_all sheeva_l2cache_wbinv_all +extern void sheeva_l2cache_wbinv_all(void); #elif defined(CPU_CORTEXA) #define cpu_idcache_wbinv_all armv7_idcache_wbinv_all #define cpu_l2cache_wbinv_all() @@ -434,11 +451,11 @@ static void * inflate_kernel(void *kernel, void *startaddr) { struct inflate infl; - char slide[GZ_WSIZE]; + unsigned char slide[GZ_WSIZE]; orig_input = kernel; memcnt = memtot = 0; - i_input = (char *)kernel + GZ_HEAD; + i_input = (unsigned char *)kernel + GZ_HEAD; if (((char *)kernel)[3] & 0x18) { while (*i_input) i_input++; @@ -590,6 +607,8 @@ load_kernel(unsigned int kstart, unsigned int curaddr,unsigned int func_end, __asm __volatile(".globl func_end\n" "func_end:"); + /* NOTREACHED */ + return NULL; } extern char func_end[]; diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index 48d92ae..7517b24 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -60,28 +60,21 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/fdt.h> -#define GENERIC_TIMER_CTRL_ENABLE (1 << 0) -#define GENERIC_TIMER_CTRL_INT_MASK (1 << 1) -#define GENERIC_TIMER_CTRL_INT_STAT (1 << 2) -#define GENERIC_TIMER_REG_CTRL 0 -#define GENERIC_TIMER_REG_TVAL 1 - -#define GENERIC_TIMER_CNTKCTL_PL0PTEN (1 << 9) /* Physical timer registers - access from PL0 */ -#define GENERIC_TIMER_CNTKCTL_PL0VTEN (1 << 8) /* Virtual timer registers - access from PL0 */ -#define GENERIC_TIMER_CNTKCTL_EVNTI (1 << 4) /* Virtual counter - event bits */ -#define GENERIC_TIMER_CNTKCTL_EVNTDIR (1 << 3) /* Virtual counter - event transition */ -#define GENERIC_TIMER_CNTKCTL_EVNTEN (1 << 2) /* Enables events from - the virtual counter */ -#define GENERIC_TIMER_CNTKCTL_PL0VCTEN (1 << 1) /* CNTVCT and CNTFRQ - access from PL0 */ -#define GENERIC_TIMER_CNTKCTL_PL0PCTEN (1 << 0) /* CNTPCT and CNTFRQ - access from PL0 */ - -#define GENERIC_TIMER_CNTPSIRQ 29 +#define GT_CTRL_ENABLE (1 << 0) +#define GT_CTRL_INT_MASK (1 << 1) +#define GT_CTRL_INT_STAT (1 << 2) +#define GT_REG_CTRL 0 +#define GT_REG_TVAL 1 + +#define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */ +#define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */ +#define GT_CNTKCTL_EVNTI (1 << 4) /* Virtual counter event bits */ +#define GT_CNTKCTL_EVNTDIR (1 << 3) /* Virtual counter event transition */ +#define GT_CNTKCTL_EVNTEN (1 << 2) /* Enables virtual counter events */ +#define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */ +#define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */ + +#define GT_CNTPSIRQ 29 struct arm_tmr_softc { struct resource *irq_res; @@ -182,11 +175,8 @@ disable_user_access(void) uint32_t cntkctl; __asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl)); - cntkctl &= ~(GENERIC_TIMER_CNTKCTL_PL0PTEN | - GENERIC_TIMER_CNTKCTL_PL0VTEN | - GENERIC_TIMER_CNTKCTL_EVNTEN | - GENERIC_TIMER_CNTKCTL_PL0VCTEN | - GENERIC_TIMER_CNTKCTL_PL0PCTEN); + cntkctl &= ~(GT_CNTKCTL_PL0PTEN | GT_CNTKCTL_PL0VTEN | + GT_CNTKCTL_EVNTEN | GT_CNTKCTL_PL0VCTEN | GT_CNTKCTL_PL0PCTEN); __asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); isb(); } @@ -209,8 +199,8 @@ arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period) if (first != 0) { counts = ((uint32_t)et->et_frequency * first) >> 32; ctrl = get_ctrl(); - ctrl &= ~GENERIC_TIMER_CTRL_INT_MASK; - ctrl |= GENERIC_TIMER_CTRL_ENABLE; + ctrl &= ~GT_CTRL_INT_MASK; + ctrl |= GT_CTRL_ENABLE; set_tval(counts); set_ctrl(ctrl); return (0); @@ -226,7 +216,7 @@ arm_tmr_stop(struct eventtimer *et) int ctrl; ctrl = get_ctrl(); - ctrl &= GENERIC_TIMER_CTRL_ENABLE; + ctrl &= GT_CTRL_ENABLE; set_ctrl(ctrl); return (0); @@ -240,8 +230,8 @@ arm_tmr_intr(void *arg) sc = (struct arm_tmr_softc *)arg; ctrl = get_ctrl(); - if (ctrl & GENERIC_TIMER_CTRL_INT_STAT) { - ctrl |= GENERIC_TIMER_CTRL_INT_MASK; + if (ctrl & GT_CTRL_INT_STAT) { + ctrl |= GT_CTRL_INT_MASK; set_ctrl(ctrl); } @@ -289,7 +279,7 @@ arm_tmr_attach(device_t dev) rid = 0; sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, - GENERIC_TIMER_CNTPSIRQ, GENERIC_TIMER_CNTPSIRQ, + GT_CNTPSIRQ, GT_CNTPSIRQ, 1, RF_SHAREABLE | RF_ACTIVE); arm_tmr_sc = sc; diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index c0f4c2c..73b899c 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -3336,7 +3336,7 @@ pmap_pv_reclaim(pmap_t locked_pmap) m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep)); KASSERT((vm_offset_t)m >= KERNBASE, ("Trying to access non-existent page " - "va %x pte %x in %s", va, *ptep)); + "va %x pte %x", va, *ptep)); *ptep = 0; PTE_SYNC(ptep); pmap_nuke_pv(m, pmap, pv); diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c index 08b4396..761169c 100644 --- a/sys/arm/arm/trap.c +++ b/sys/arm/arm/trap.c @@ -238,7 +238,7 @@ data_abort_handler(trapframe_t *tf) int error = 0; struct ksig ksig; struct proc *p; - + /* Grab FAR/FSR before enabling interrupts */ far = cpu_faultaddress(); @@ -262,10 +262,10 @@ data_abort_handler(trapframe_t *tf) if (user) { td->td_pticks = 0; - td->td_frame = tf; + td->td_frame = tf; if (td->td_ucred != td->td_proc->p_ucred) cred_update_thread(td); - + } /* Grab the current pcb */ pcb = td->td_pcb; @@ -276,7 +276,7 @@ data_abort_handler(trapframe_t *tf) if (__predict_true(tf->tf_spsr & F32_bit) == 0) enable_interrupts(F32_bit); } - + /* Invoke the appropriate handler, if necessary */ if (__predict_false(data_aborts[fsr & FAULT_TYPE_MASK].func != NULL)) { @@ -720,7 +720,7 @@ prefetch_abort_handler(trapframe_t *tf) printf("prefetch abort handler: %p %p\n", (void*)tf->tf_pc, (void*)tf->tf_usr_lr); #endif - + td = curthread; p = td->td_proc; PCPU_INC(cnt.v_trap); @@ -937,7 +937,7 @@ swi_handler(trapframe_t *frame) struct thread *td = curthread; td->td_frame = frame; - + td->td_pticks = 0; /* * Make sure the program counter is correctly aligned so we diff --git a/sys/arm/arm/vfp.c b/sys/arm/arm/vfp.c index d341176..b9dce13 100644 --- a/sys/arm/arm/vfp.c +++ b/sys/arm/arm/vfp.c @@ -195,15 +195,27 @@ vfp_restore(struct vfp_state *vfpsave) { u_int vfpscr = 0; + /* + * Work around an issue with GCC where the asm it generates is + * not unified syntax and fails to assemble because it expects + * the ldcleq instruction in the form ldc<c>l, not in the UAL + * form ldcl<c>, and similar for stcleq. + */ +#ifdef __clang__ +#define ldclne "ldclne" +#define stclne "stclne" +#else +#define ldclne "ldcnel" +#define stclne "stcnel" +#endif if (vfpsave) { - __asm __volatile("ldc p10, c0, [%0], #128\n" /* d0-d15 */ - "cmp %0, 0\n" /* -D16 or -D32? */ - "ldcleq p11, c0, [%0], #128\n" /* d16-d31 */ - "addne %0, %0, #128\n" /* skip missing regs */ - "ldr %1, [%0]\n" /* set old vfpscr */ - "mcr p10, 7, %1, cr1, c0, 0\n" - :: "r" (vfpsave), "r" (vfpscr), "r" (is_d32) - : "cc"); + __asm __volatile("ldc p10, c0, [%1], #128\n" /* d0-d15 */ + "cmp %2, #0\n" /* -D16 or -D32? */ + ldclne" p11, c0, [%1], #128\n" /* d16-d31 */ + "addeq %1, %1, #128\n" /* skip missing regs */ + "ldr %0, [%1]\n" /* set old vfpscr */ + "mcr p10, 7, %0, cr1, c0, 0\n" + : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); PCPU_SET(vfpcthread, PCPU_GET(curthread)); } } @@ -225,13 +237,16 @@ vfp_store(struct vfp_state *vfpsave) tmp = fmrx(VFPEXC); /* Is the vfp enabled? */ if (vfpsave && tmp & VFPEXC_EN) { __asm __volatile("stc p11, c0, [%1], #128\n" /* d0-d15 */ - "cmp %0, 0\n" /* -D16 or -D32? */ - "stcleq p11, c0, [%1], #128\n" /* d16-d31 */ - "addne %1, %1, #128\n" /* skip missing regs */ + "cmp %2, #0\n" /* -D16 or -D32? */ + stclne" p11, c0, [%1], #128\n" /* d16-d31 */ + "addeq %1, %1, #128\n" /* skip missing regs */ "mrc p10, 7, %0, cr1, c0, 0\n" /* fmxr(VFPSCR) */ "str %0, [%1]\n" /* save vfpscr */ - : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); + : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); } +#undef ldcleq +#undef stcleq + #ifndef SMP /* eventually we will use this information for UP also */ PCPU_SET(vfpcthread, 0); diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c index 29a213f..3bb76e2 100644 --- a/sys/arm/arm/vm_machdep.c +++ b/sys/arm/arm/vm_machdep.c @@ -251,7 +251,7 @@ sf_buf_alloc(struct vm_page *m, int flags) if (flags & SFB_NOWAIT) goto done; sf_buf_alloc_want++; - mbstat.sf_allocwait++; + SFSTAT_INC(sf_allocwait); error = msleep(&sf_buf_freelist, &sf_buf_lock, (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); sf_buf_alloc_want--; diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c index 0f1e81c..879f278 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c @@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$"); #include <arm/broadcom/bcm2835/bcm2835_mbox.h> #include <arm/broadcom/bcm2835/bcm2835_vcbus.h> +#include "mbox_if.h" + #define BCMFB_FONT_HEIGHT 16 struct argb { @@ -173,6 +175,7 @@ bcm_fb_init(void *arg) volatile struct bcm_fb_config* fb_config = sc->fb_config; phandle_t node; pcell_t cell; + device_t mbox; node = ofw_bus_get_node(sc->dev); @@ -205,8 +208,12 @@ bcm_fb_init(void *arg) bus_dmamap_sync(sc->dma_tag, sc->dma_map, BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - bcm_mbox_write(BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); - bcm_mbox_read(BCM2835_MBOX_CHAN_FB, &err); + + mbox = devclass_get_device(devclass_find("mbox"), 0); + if (mbox) { + MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); + MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err); + } bus_dmamap_sync(sc->dma_tag, sc->dma_map, BUS_DMASYNC_POSTREAD); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c index f18102b..4278742 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c @@ -49,8 +49,11 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/fdt.h> + #include <arm/broadcom/bcm2835/bcm2835_mbox.h> +#include "mbox_if.h" + #define REG_READ 0x00 #define REG_POL 0x10 #define REG_SENDER 0x14 @@ -65,12 +68,12 @@ __FBSDID("$FreeBSD$"); #define MBOX_CHAN(msg) ((msg) & 0xf) #define MBOX_DATA(msg) ((msg) & ~0xf) -#define MBOX_LOCK do { \ - mtx_lock(&bcm_mbox_sc->lock); \ +#define MBOX_LOCK(sc) do { \ + mtx_lock(&(sc)->lock); \ } while(0) -#define MBOX_UNLOCK do { \ - mtx_unlock(&bcm_mbox_sc->lock); \ +#define MBOX_UNLOCK(sc) do { \ + mtx_unlock(&(sc)->lock); \ } while(0) #ifdef DEBUG @@ -90,12 +93,10 @@ struct bcm_mbox_softc { int msg[BCM2835_MBOX_CHANS]; }; -static struct bcm_mbox_softc *bcm_mbox_sc = NULL; - -#define mbox_read_4(reg) \ - bus_space_read_4(bcm_mbox_sc->bst, bcm_mbox_sc->bsh, reg) -#define mbox_write_4(reg, val) \ - bus_space_write_4(bcm_mbox_sc->bst, bcm_mbox_sc->bsh, reg, val) +#define mbox_read_4(sc, reg) \ + bus_space_read_4((sc)->bst, (sc)->bsh, reg) +#define mbox_write_4(sc, reg, val) \ + bus_space_write_4((sc)->bst, (sc)->bsh, reg, val) static void bcm_mbox_intr(void *arg) @@ -105,9 +106,9 @@ bcm_mbox_intr(void *arg) uint32_t data; uint32_t msg; - MBOX_LOCK; - while (!(mbox_read_4(REG_STATUS) & STATUS_EMPTY)) { - msg = mbox_read_4(REG_READ); + MBOX_LOCK(sc); + while (!(mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY)) { + msg = mbox_read_4(sc, REG_READ); dprintf("bcm_mbox_intr: raw data %08x\n", msg); chan = MBOX_CHAN(msg); data = MBOX_DATA(msg); @@ -121,7 +122,7 @@ bcm_mbox_intr(void *arg) wakeup(&sc->msg[chan]); } - MBOX_UNLOCK; + MBOX_UNLOCK(sc); } static int @@ -143,9 +144,6 @@ bcm_mbox_attach(device_t dev) int i; int rid = 0; - if (bcm_mbox_sc != NULL) - return (EINVAL); - sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { device_printf(dev, "could not allocate memory resource\n"); @@ -176,72 +174,76 @@ bcm_mbox_attach(device_t dev) sc->msg[0] = 0; } - bcm_mbox_sc = sc; /* Read all pending messages */ bcm_mbox_intr(sc); - /* Should be called after bcm_mbox_sc initialization */ - mbox_write_4(REG_CONFIG, CONFIG_DATA_IRQ); + mbox_write_4(sc, REG_CONFIG, CONFIG_DATA_IRQ); return (0); } -static device_method_t bcm_mbox_methods[] = { - DEVMETHOD(device_probe, bcm_mbox_probe), - DEVMETHOD(device_attach, bcm_mbox_attach), - { 0, 0 } -}; - -static driver_t bcm_mbox_driver = { - "mbox", - bcm_mbox_methods, - sizeof(struct bcm_mbox_softc), -}; - -static devclass_t bcm_mbox_devclass; - -DRIVER_MODULE(mbox, simplebus, bcm_mbox_driver, bcm_mbox_devclass, 0, 0); - /* * Mailbox API */ -int -bcm_mbox_write(int chan, uint32_t data) +static int +bcm_mbox_write(device_t dev, int chan, uint32_t data) { int limit = 20000; + struct bcm_mbox_softc *sc = device_get_softc(dev); dprintf("bcm_mbox_write: chan %d, data %08x\n", chan, data); - MBOX_LOCK; + MBOX_LOCK(sc); - while ((mbox_read_4(REG_STATUS) & STATUS_FULL) && limit--) { + while ((mbox_read_4(sc, REG_STATUS) & STATUS_FULL) && limit--) { DELAY(2); } if (limit == 0) { printf("bcm_mbox_write: STATUS_FULL stuck"); - MBOX_UNLOCK; + MBOX_UNLOCK(sc); return (EAGAIN); } - mbox_write_4(REG_WRITE, MBOX_MSG(chan, data)); + mbox_write_4(sc, REG_WRITE, MBOX_MSG(chan, data)); - MBOX_UNLOCK; + MBOX_UNLOCK(sc); return (0); } -int -bcm_mbox_read(int chan, uint32_t *data) +static int +bcm_mbox_read(device_t dev, int chan, uint32_t *data) { - struct bcm_mbox_softc *sc = bcm_mbox_sc; + struct bcm_mbox_softc *sc = device_get_softc(dev); dprintf("bcm_mbox_read: chan %d\n", chan); - MBOX_LOCK; + MBOX_LOCK(sc); while (!sc->valid[chan]) msleep(&sc->msg[chan], &sc->lock, PZERO, "vcio mbox read", 0); - *data = bcm_mbox_sc->msg[chan]; - bcm_mbox_sc->valid[chan] = 0; - MBOX_UNLOCK; + *data = sc->msg[chan]; + sc->valid[chan] = 0; + MBOX_UNLOCK(sc); dprintf("bcm_mbox_read: chan %d, data %08x\n", chan, *data); return (0); } + +static device_method_t bcm_mbox_methods[] = { + DEVMETHOD(device_probe, bcm_mbox_probe), + DEVMETHOD(device_attach, bcm_mbox_attach), + + DEVMETHOD(mbox_read, bcm_mbox_read), + DEVMETHOD(mbox_write, bcm_mbox_write), + + DEVMETHOD_END +}; + +static driver_t bcm_mbox_driver = { + "mbox", + bcm_mbox_methods, + sizeof(struct bcm_mbox_softc), +}; + +static devclass_t bcm_mbox_devclass; + +DRIVER_MODULE(mbox, simplebus, bcm_mbox_driver, bcm_mbox_devclass, 0, 0); + diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.h b/sys/arm/broadcom/bcm2835/bcm2835_mbox.h index edb9d5b..52f48e4 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.h @@ -38,7 +38,4 @@ #define BCM2835_MBOX_CHAN_TS 6 #define BCM2835_MBOX_CHANS 7 -int bcm_mbox_write(int chan, uint32_t data); -int bcm_mbox_read(int chan, uint32_t *data); - #endif /* _BCM2835_MBOX_H_ */ diff --git a/sys/arm/broadcom/bcm2835/files.bcm2835 b/sys/arm/broadcom/bcm2835/files.bcm2835 index aa1af40..9c0ff05 100644 --- a/sys/arm/broadcom/bcm2835/files.bcm2835 +++ b/sys/arm/broadcom/bcm2835/files.bcm2835 @@ -22,3 +22,5 @@ arm/arm/cpufunc_asm_armv6.S standard arm/arm/irq_dispatch.S standard kern/kern_clocksource.c standard + +dev/mbox/mbox_if.m standard diff --git a/sys/arm/broadcom/bcm2835/std.bcm2835 b/sys/arm/broadcom/bcm2835/std.bcm2835 new file mode 100644 index 0000000..ebc1fb0 --- /dev/null +++ b/sys/arm/broadcom/bcm2835/std.bcm2835 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +machine arm armv6 +cpu CPU_ARM1176 + +files "../broadcom/bcm2835/files.bcm2835" + diff --git a/sys/arm/broadcom/bcm2835/std.rpi b/sys/arm/broadcom/bcm2835/std.rpi new file mode 100644 index 0000000..8bb62c8 --- /dev/null +++ b/sys/arm/broadcom/bcm2835/std.rpi @@ -0,0 +1,12 @@ +# $FreeBSD$ + +include "../broadcom/bcm2835/std.bcm2835" + +options KERNVIRTADDR=0xc0100000 +makeoptions KERNVIRTADDR=0xc0100000 +options KERNPHYSADDR=0x00100000 +makeoptions KERNPHYSADDR=0x00100000 +options PHYSADDR=0x00000000 +options STARTUP_PAGETABLE_ADDR=0x01000000 +options FREEBSD_BOOT_LOADER +options LINUX_BOOT_ABI diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE index 1304868..f6fe35e 100644 --- a/sys/arm/conf/BEAGLEBONE +++ b/sys/arm/conf/BEAGLEBONE @@ -123,6 +123,10 @@ device bpf device miibus device axe # ASIX Electronics USB Ethernet +# Device mode support and USFS template +device usb_template # Control of the gadget +device usfs + # Flattened Device Tree options FDT options FDT_DTB_STATIC diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B index 38db5dd..474f6a9 100644 --- a/sys/arm/conf/RPI-B +++ b/sys/arm/conf/RPI-B @@ -18,21 +18,10 @@ # $FreeBSD$ ident RPI-B -machine arm armv6 -cpu CPU_ARM1176 -files "../broadcom/bcm2835/files.bcm2835" +include "../broadcom/bcm2835/std.rpi" makeoptions MODULES_OVERRIDE="" -options KERNVIRTADDR=0xc0100000 -makeoptions KERNVIRTADDR=0xc0100000 -options KERNPHYSADDR=0x00100000 -makeoptions KERNPHYSADDR=0x00100000 -options PHYSADDR=0x00000000 -options STARTUP_PAGETABLE_ADDR=0x01000000 -options FREEBSD_BOOT_LOADER -options LINUX_BOOT_ABI - makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols options HZ=100 diff --git a/sys/arm/ti/am335x/am335x_pmic.c b/sys/arm/ti/am335x/am335x_pmic.c index eab400a..462a2b8 100644 --- a/sys/arm/ti/am335x/am335x_pmic.c +++ b/sys/arm/ti/am335x/am335x_pmic.c @@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$"); #define TPS65217A 0x7 #define TPS65217B 0xF +#define TPS65217C 0xE +#define TPS65217D 0x6 /* TPS65217 Reisters */ #define TPS65217_CHIPID_REG 0x00 @@ -131,6 +133,12 @@ am335x_pmic_start(void *xdev) case TPS65217B: sprintf(name, "TPS65217B ver 1.%u", reg & 0xF); break; + case TPS65217C: + sprintf(name, "TPS65217C ver 1.%u", reg & 0xF); + break; + case TPS65217D: + sprintf(name, "TPS65217D ver 1.%u", reg & 0xF); + break; default: sprintf(name, "Unknown PMIC"); } diff --git a/sys/arm/ti/am335x/am335x_usbss.c b/sys/arm/ti/am335x/am335x_usbss.c new file mode 100644 index 0000000..75b92ba --- /dev/null +++ b/sys/arm/ti/am335x/am335x_usbss.c @@ -0,0 +1,481 @@ +/*- + * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/stdint.h> +#include <sys/stddef.h> +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/bus.h> +#include <sys/module.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/condvar.h> +#include <sys/sysctl.h> +#include <sys/sx.h> +#include <sys/unistd.h> +#include <sys/callout.h> +#include <sys/malloc.h> +#include <sys/priv.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> + +#include <dev/usb/usb_core.h> +#include <dev/usb/usb_busdma.h> +#include <dev/usb/usb_process.h> +#include <dev/usb/usb_util.h> + +#define USB_DEBUG_VAR usbssdebug + +#include <dev/usb/usb_controller.h> +#include <dev/usb/usb_bus.h> +#include <dev/usb/controller/musb_otg.h> +#include <dev/usb/usb_debug.h> + +#include <sys/rman.h> + +#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_scm.h> +#include <arm/ti/am335x/am335x_scm.h> + +#define AM335X_USB_PORTS 2 + +#define USBSS_REVREG 0x00 +#define USBSS_SYSCONFIG 0x10 +#define USBSS_SYSCONFIG_SRESET 1 + +#define USBCTRL_REV 0x00 +#define USBCTRL_CTRL 0x14 +#define USBCTRL_STAT 0x18 +#define USBCTRL_IRQ_STAT0 0x30 +#define IRQ_STAT0_RXSHIFT 16 +#define IRQ_STAT0_TXSHIFT 0 +#define USBCTRL_IRQ_STAT1 0x34 +#define IRQ_STAT1_DRVVBUS (1 << 8) +#define USBCTRL_INTEN_SET0 0x38 +#define USBCTRL_INTEN_SET1 0x3C +#define USBCTRL_INTEN_USB_ALL 0x1ff +#define USBCTRL_INTEN_USB_SOF (1 << 3) +#define USBCTRL_INTEN_CLR0 0x40 +#define USBCTRL_INTEN_CLR1 0x44 +#define USBCTRL_UTMI 0xE0 +#define USBCTRL_UTMI_FSDATAEXT (1 << 1) +#define USBCTRL_MODE 0xE8 +#define USBCTRL_MODE_IDDIG (1 << 8) +#define USBCTRL_MODE_IDDIGMUX (1 << 7) + +/* USBSS resource + 2 MUSB ports */ + +#define RES_USBSS 0 +#define RES_USBCTRL(i) (3*i+1) +#define RES_USBPHY(i) (3*i+2) +#define RES_USBCORE(i) (3*i+3) + +#define USB_WRITE4(sc, idx, reg, val) do { \ + bus_write_4((sc)->sc_mem_res[idx], (reg), (val)); \ +} while (0) + +#define USB_READ4(sc, idx, reg) bus_read_4((sc)->sc_mem_res[idx], (reg)) + +#define USBSS_WRITE4(sc, reg, val) \ + USB_WRITE4((sc), RES_USBSS, (reg), (val)) +#define USBSS_READ4(sc, reg) \ + USB_READ4((sc), RES_USBSS, (reg)) +#define USBCTRL_WRITE4(sc, unit, reg, val) \ + USB_WRITE4((sc), RES_USBCTRL(unit), (reg), (val)) +#define USBCTRL_READ4(sc, unit, reg) \ + USB_READ4((sc), RES_USBCTRL(unit), (reg)) +#define USBPHY_WRITE4(sc, unit, reg, val) \ + USB_WRITE4((sc), RES_USBPHY(unit), (reg), (val)) +#define USBPHY_READ4(sc, unit, reg) \ + USB_READ4((sc), RES_USBPHY(unit), (reg)) + +static struct resource_spec am335x_musbotg_mem_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_MEMORY, 1, RF_ACTIVE }, + { SYS_RES_MEMORY, 2, RF_ACTIVE }, + { SYS_RES_MEMORY, 3, RF_ACTIVE }, + { SYS_RES_MEMORY, 4, RF_ACTIVE }, + { SYS_RES_MEMORY, 5, RF_ACTIVE }, + { SYS_RES_MEMORY, 6, RF_ACTIVE }, + { -1, 0, 0 } +}; + +static struct resource_spec am335x_musbotg_irq_spec[] = { + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { SYS_RES_IRQ, 2, RF_ACTIVE }, + { -1, 0, 0 } +}; + +#ifdef USB_DEBUG +static int usbssdebug = 0; + +static SYSCTL_NODE(_hw_usb, OID_AUTO, am335x_usbss, CTLFLAG_RW, 0, "AM335x USBSS"); +SYSCTL_INT(_hw_usb_am335x_usbss, OID_AUTO, debug, CTLFLAG_RW, + &usbssdebug, 0, "Debug level"); +#endif + +static device_probe_t musbotg_probe; +static device_attach_t musbotg_attach; +static device_detach_t musbotg_detach; + +struct musbotg_super_softc { + struct musbotg_softc sc_otg[AM335X_USB_PORTS]; + struct resource *sc_mem_res[AM335X_USB_PORTS*3+1]; + struct resource *sc_irq_res[AM335X_USB_PORTS+1]; + void *sc_intr_hdl; +}; + +static void +musbotg_vbus_poll(struct musbotg_super_softc *sc, int port) +{ + uint32_t stat; + + if (sc->sc_otg[port].sc_mode == MUSB2_DEVICE_MODE) + musbotg_vbus_interrupt(&sc->sc_otg[port], 1); + else { + stat = USBCTRL_READ4(sc, port, USBCTRL_STAT); + musbotg_vbus_interrupt(&sc->sc_otg[port], stat & 1); + } +} + +/* + * Arg to musbotg_clocks_on and musbot_clocks_off is + * a uint32_t * pointing to the SCM register offset. + */ +static uint32_t USB_CTRL[] = {SCM_USB_CTRL0, SCM_USB_CTRL1}; + +static void +musbotg_clocks_on(void *arg) +{ + uint32_t c, reg = *(uint32_t *)arg; + + ti_scm_reg_read_4(reg, &c); + c &= ~3; /* Enable power */ + c |= 1 << 19; /* VBUS detect enable */ + c |= 1 << 20; /* Session end enable */ + ti_scm_reg_write_4(reg, c); +} + +static void +musbotg_clocks_off(void *arg) +{ + uint32_t c, reg = *(uint32_t *)arg; + + /* Disable power to PHY */ + ti_scm_reg_read_4(reg, &c); + ti_scm_reg_write_4(reg, c | 3); +} + +static void +musbotg_ep_int_set(struct musbotg_softc *sc, int ep, int on) +{ + struct musbotg_super_softc *ssc = sc->sc_platform_data; + uint32_t epmask; + + epmask = ((1 << ep) << IRQ_STAT0_RXSHIFT); + epmask |= ((1 << ep) << IRQ_STAT0_TXSHIFT); + if (on) + USBCTRL_WRITE4(ssc, sc->sc_id, + USBCTRL_INTEN_SET0, epmask); + else + USBCTRL_WRITE4(ssc, sc->sc_id, + USBCTRL_INTEN_CLR0, epmask); +} + +static void +musbotg_usbss_interrupt(void *arg) +{ + panic("USBSS real interrupt"); +} + +static void +musbotg_wrapper_interrupt(void *arg) +{ + struct musbotg_softc *sc = arg; + struct musbotg_super_softc *ssc = sc->sc_platform_data; + uint32_t stat, stat0, stat1; + stat = USBCTRL_READ4(ssc, sc->sc_id, USBCTRL_STAT); + stat0 = USBCTRL_READ4(ssc, sc->sc_id, USBCTRL_IRQ_STAT0); + stat1 = USBCTRL_READ4(ssc, sc->sc_id, USBCTRL_IRQ_STAT1); + if (stat0) + USBCTRL_WRITE4(ssc, sc->sc_id, USBCTRL_IRQ_STAT0, stat0); + if (stat1) + USBCTRL_WRITE4(ssc, sc->sc_id, USBCTRL_IRQ_STAT1, stat1); + + DPRINTFN(4, "port%d: stat0=%08x stat1=%08x, stat=%08x\n", + sc->sc_id, stat0, stat1, stat); + + if (stat1 & IRQ_STAT1_DRVVBUS) + musbotg_vbus_interrupt(sc, stat & 1); + + musbotg_interrupt(arg, ((stat0 >> 16) & 0xffff), + stat0 & 0xffff, stat1 & 0xff); +} + +static int +musbotg_probe(device_t dev) +{ + if (!ofw_bus_is_compatible(dev, "ti,musb-am33xx")) + return (ENXIO); + + device_set_desc(dev, "TI AM33xx integrated USB OTG controller"); + + return (BUS_PROBE_DEFAULT); +} + +static int +musbotg_attach(device_t dev) +{ + struct musbotg_super_softc *sc = device_get_softc(dev); + int err; + int i; + uint32_t rev, reg; + + /* Request the memory resources */ + err = bus_alloc_resources(dev, am335x_musbotg_mem_spec, + sc->sc_mem_res); + if (err) { + device_printf(dev, + "Error: could not allocate mem resources\n"); + return (ENXIO); + } + + /* Request the IRQ resources */ + err = bus_alloc_resources(dev, am335x_musbotg_irq_spec, + sc->sc_irq_res); + if (err) { + device_printf(dev, + "Error: could not allocate irq resources\n"); + return (ENXIO); + } + + /* + * Reset USBSS, USB0 and USB1 + */ + rev = USBSS_READ4(sc, USBSS_REVREG); + device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n", + (rev >> 8) & 7, (rev >> 6) & 3, rev & 63); + + ti_prcm_clk_enable(MUSB0_CLK); + + USBSS_WRITE4(sc, USBSS_SYSCONFIG, + USBSS_SYSCONFIG_SRESET); + while (USBSS_READ4(sc, USBSS_SYSCONFIG) & + USBSS_SYSCONFIG_SRESET) + ; + + err = bus_setup_intr(dev, sc->sc_irq_res[0], + INTR_TYPE_BIO | INTR_MPSAFE, + NULL, (driver_intr_t *)musbotg_usbss_interrupt, sc, + &sc->sc_intr_hdl); + + if (err) { + sc->sc_intr_hdl = NULL; + device_printf(dev, "Failed to setup USBSS interrupt\n"); + goto error; + } + + for (i = 0; i < AM335X_USB_PORTS; i++) { + /* setup MUSB OTG USB controller interface softc */ + sc->sc_otg[i].sc_clocks_on = &musbotg_clocks_on; + sc->sc_otg[i].sc_clocks_off = &musbotg_clocks_off; + sc->sc_otg[i].sc_clocks_arg = &USB_CTRL[i]; + + sc->sc_otg[i].sc_ep_int_set = musbotg_ep_int_set; + + /* initialise some bus fields */ + sc->sc_otg[i].sc_bus.parent = dev; + sc->sc_otg[i].sc_bus.devices = sc->sc_otg[i].sc_devices; + sc->sc_otg[i].sc_bus.devices_max = MUSB2_MAX_DEVICES; + + /* get all DMA memory */ + if (usb_bus_mem_alloc_all(&sc->sc_otg[i].sc_bus, + USB_GET_DMA_TAG(dev), NULL)) { + device_printf(dev, + "Failed allocate bus mem for musb%d\n", i); + return (ENOMEM); + } + sc->sc_otg[i].sc_io_res = sc->sc_mem_res[RES_USBCORE(i)]; + sc->sc_otg[i].sc_io_tag = + rman_get_bustag(sc->sc_otg[i].sc_io_res); + sc->sc_otg[i].sc_io_hdl = + rman_get_bushandle(sc->sc_otg[i].sc_io_res); + sc->sc_otg[i].sc_io_size = + rman_get_size(sc->sc_otg[i].sc_io_res); + + sc->sc_otg[i].sc_irq_res = sc->sc_irq_res[i+1]; + + sc->sc_otg[i].sc_bus.bdev = device_add_child(dev, "usbus", -1); + if (!(sc->sc_otg[i].sc_bus.bdev)) { + device_printf(dev, "No busdev for musb%d\n", i); + goto error; + } + device_set_ivars(sc->sc_otg[i].sc_bus.bdev, + &sc->sc_otg[i].sc_bus); + + err = bus_setup_intr(dev, sc->sc_otg[i].sc_irq_res, + INTR_TYPE_BIO | INTR_MPSAFE, + NULL, (driver_intr_t *)musbotg_wrapper_interrupt, + &sc->sc_otg[i], &sc->sc_otg[i].sc_intr_hdl); + if (err) { + sc->sc_otg[i].sc_intr_hdl = NULL; + device_printf(dev, + "Failed to setup interrupt for musb%d\n", i); + goto error; + } + + sc->sc_otg[i].sc_id = i; + sc->sc_otg[i].sc_platform_data = sc; + if (i == 0) + sc->sc_otg[i].sc_mode = MUSB2_DEVICE_MODE; + else + sc->sc_otg[i].sc_mode = MUSB2_HOST_MODE; + + /* + * software-controlled function + */ + + if (sc->sc_otg[i].sc_mode == MUSB2_HOST_MODE) { + reg = USBCTRL_READ4(sc, i, USBCTRL_MODE); + reg |= USBCTRL_MODE_IDDIGMUX; + reg &= ~USBCTRL_MODE_IDDIG; + USBCTRL_WRITE4(sc, i, USBCTRL_MODE, reg); + USBCTRL_WRITE4(sc, i, USBCTRL_UTMI, + USBCTRL_UTMI_FSDATAEXT); + } else { + reg = USBCTRL_READ4(sc, i, USBCTRL_MODE); + reg |= USBCTRL_MODE_IDDIGMUX; + reg |= USBCTRL_MODE_IDDIG; + USBCTRL_WRITE4(sc, i, USBCTRL_MODE, reg); + } + + reg = USBCTRL_INTEN_USB_ALL & ~USBCTRL_INTEN_USB_SOF; + USBCTRL_WRITE4(sc, i, USBCTRL_INTEN_SET1, reg); + USBCTRL_WRITE4(sc, i, USBCTRL_INTEN_CLR0, 0xffffffff); + + err = musbotg_init(&sc->sc_otg[i]); + if (!err) + err = device_probe_and_attach(sc->sc_otg[i].sc_bus.bdev); + + if (err) + goto error; + + /* poll VBUS one time */ + musbotg_vbus_poll(sc, i); + } + + return (0); + +error: + musbotg_detach(dev); + return (ENXIO); +} + +static int +musbotg_detach(device_t dev) +{ + struct musbotg_super_softc *sc = device_get_softc(dev); + device_t bdev; + int err; + int i; + + for (i = 0; i < AM335X_USB_PORTS; i++) { + if (sc->sc_otg[i].sc_bus.bdev) { + bdev = sc->sc_otg[i].sc_bus.bdev; + device_detach(bdev); + device_delete_child(dev, bdev); + } + + if (sc->sc_otg[i].sc_irq_res && sc->sc_otg[i].sc_intr_hdl) { + /* + * only call musbotg_uninit() after musbotg_init() + */ + musbotg_uninit(&sc->sc_otg[i]); + + err = bus_teardown_intr(dev, sc->sc_otg[i].sc_irq_res, + sc->sc_otg[i].sc_intr_hdl); + sc->sc_otg[i].sc_intr_hdl = NULL; + } + + usb_bus_mem_free_all(&sc->sc_otg[i].sc_bus, NULL); + } + + if (sc->sc_intr_hdl) { + bus_teardown_intr(dev, sc->sc_irq_res[0], + sc->sc_intr_hdl); + sc->sc_intr_hdl = NULL; + } + + + /* Free resources if any */ + if (sc->sc_mem_res[0]) + bus_release_resources(dev, am335x_musbotg_mem_spec, + sc->sc_mem_res); + + if (sc->sc_irq_res[0]) + bus_release_resources(dev, am335x_musbotg_irq_spec, + sc->sc_irq_res); + + /* during module unload there are lots of children leftover */ + device_delete_children(dev); + + return (0); +} + +static device_method_t musbotg_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, musbotg_probe), + DEVMETHOD(device_attach, musbotg_attach), + DEVMETHOD(device_detach, musbotg_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + DEVMETHOD_END +}; + +static driver_t musbotg_driver = { + .name = "musbotg", + .methods = musbotg_methods, + .size = sizeof(struct musbotg_super_softc), +}; + +static devclass_t musbotg_devclass; + +DRIVER_MODULE(musbotg, simplebus, musbotg_driver, musbotg_devclass, 0, 0); +MODULE_DEPEND(musbotg, usb, 1, 1, 1); diff --git a/sys/arm/ti/am335x/files.am335x b/sys/arm/ti/am335x/files.am335x index a275341..70e0e26 100644 --- a/sys/arm/ti/am335x/files.am335x +++ b/sys/arm/ti/am335x/files.am335x @@ -7,6 +7,7 @@ arm/ti/am335x/am335x_scm_padconf.c standard arm/ti/am335x/am335x_lcd.c optional sc arm/ti/am335x/am335x_lcd_syscons.c optional sc arm/ti/am335x/am335x_pwm.c standard +arm/ti/am335x/am335x_usbss.c optional musb fdt arm/ti/ti_edma3.c standard arm/ti/ti_mmchs.c optional mmc arm/ti/cpsw/if_cpsw.c optional cpsw diff --git a/sys/arm/ti/ti_mmchs.c b/sys/arm/ti/ti_mmchs.c index 76ecc58..25c7d06 100644 --- a/sys/arm/ti/ti_mmchs.c +++ b/sys/arm/ti/ti_mmchs.c @@ -212,11 +212,12 @@ ti_mmchs_reset_controller(struct ti_mmchs_softc *sc, uint32_t bit) sysctl = ti_mmchs_read_4(sc, MMCHS_SYSCTL); ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl | bit); - - if ((ti_chip() == CHIP_OMAP_4) && (ti_revision() > OMAP4430_REV_ES1_0)) { - /* OMAP4 ES2 and greater has an updated reset logic. - * Monitor a 0->1 transition first - */ + /* + * AM335x and OMAP4 >= ES2 have an updated reset logic. + * Monitor a 0->1 transition first. + */ + if ((ti_chip() == CHIP_AM335X) || + ((ti_chip() == CHIP_OMAP_4) && (ti_revision() > OMAP4430_REV_ES1_0))) { attempts = 10000; while (!(ti_mmchs_read_4(sc, MMCHS_SYSCTL) & bit) && (attempts-- > 0)) continue; @@ -1327,7 +1328,7 @@ ti_mmchs_hw_init(device_t dev) unsigned long timeout; uint32_t sysctl; uint32_t capa; - uint32_t con; + uint32_t con, sysconfig; /* 1: Enable the controller and interface/functional clocks */ clk = MMC0_CLK + sc->device_id; @@ -1344,7 +1345,9 @@ ti_mmchs_hw_init(device_t dev) } /* 2: Issue a softreset to the controller */ - ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, 0x0002); + sysconfig = ti_mmchs_read_4(sc, MMCHS_SYSCONFIG); + sysconfig |= MMCHS_SYSCONFIG_SRST; + ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, sysconfig); timeout = 100; while ((ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & 0x01) == 0x0) { DELAY(1000); diff --git a/sys/arm/ti/ti_mmchs.h b/sys/arm/ti/ti_mmchs.h index 5a7f3f4..175c0c6 100644 --- a/sys/arm/ti/ti_mmchs.h +++ b/sys/arm/ti/ti_mmchs.h @@ -67,6 +67,12 @@ #define AM335X_MMCHS_REG_OFFSET 0x100 /* Register bit settings */ +#define MMCHS_SYSCONFIG_CLK_FUN (2 << 8) +#define MMCHS_SYSCONFIG_CLK_IFC (1 << 8) +#define MMCHS_SYSCONFIG_SIDL (2 << 3) +#define MMCHS_SYSCONFIG_ENW (1 << 2) +#define MMCHS_SYSCONFIG_SRST (1 << 1) +#define MMCHS_SYSCONFIG_AIDL (1 << 0) #define MMCHS_STAT_BADA (1UL << 29) #define MMCHS_STAT_CERR (1UL << 28) #define MMCHS_STAT_ACE (1UL << 24) |