From 9f2205a3f58014a4998e56731f66354b9e99f86d Mon Sep 17 00:00:00 2001 From: Kevin Kirspel Date: Mon, 30 Jan 2017 11:58:16 -0500 Subject: Port LPC32XX Ethernet and USB OHCI to RTEMS --- freebsd/sys/arm/lpc/if_lpe.c | 178 ++++++++ freebsd/sys/arm/lpc/lpc_pwr.c | 8 + freebsd/sys/dev/mii/icsphy.c | 3 + freebsd/sys/dev/usb/controller/ohci.h | 2 - libbsd.py | 6 + libbsd_waf.py | 5 +- rtemsbsd/include/bsp/nexus-devices.h | 12 + rtemsbsd/include/machine/rtems-bsd-nexus-bus.h | 75 ++++ rtemsbsd/include/rtems/bsd/local/miidevs.h | 2 + rtemsbsd/sys/dev/usb/controller/ohci_lpc.c | 93 +--- rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c | 499 +++++++++++++++++++++ rtemsbsd/sys/dev/usb/usb_otg_transceiver.h | 1 + .../include/rtems/bsd/test/network-config.h.in | 2 + 13 files changed, 792 insertions(+), 94 deletions(-) mode change 100644 => 100755 freebsd/sys/arm/lpc/if_lpe.c mode change 100644 => 100755 freebsd/sys/arm/lpc/lpc_pwr.c mode change 100644 => 100755 freebsd/sys/dev/mii/icsphy.c mode change 100644 => 100755 freebsd/sys/dev/usb/controller/ohci.h mode change 100644 => 100755 rtemsbsd/include/bsp/nexus-devices.h mode change 100644 => 100755 rtemsbsd/include/machine/rtems-bsd-nexus-bus.h mode change 100644 => 100755 rtemsbsd/include/rtems/bsd/local/miidevs.h mode change 100644 => 100755 rtemsbsd/sys/dev/usb/controller/ohci_lpc.c create mode 100755 rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c mode change 100644 => 100755 rtemsbsd/sys/dev/usb/usb_otg_transceiver.h mode change 100644 => 100755 testsuite/include/rtems/bsd/test/network-config.h.in diff --git a/freebsd/sys/arm/lpc/if_lpe.c b/freebsd/sys/arm/lpc/if_lpe.c old mode 100644 new mode 100755 index 76b794fb..69e24ae9 --- a/freebsd/sys/arm/lpc/if_lpe.c +++ b/freebsd/sys/arm/lpc/if_lpe.c @@ -43,7 +43,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifndef __rtems__ #include +#endif /* __rtems__ */ #include #include @@ -55,8 +57,10 @@ __FBSDID("$FreeBSD$"); #include +#ifndef __rtems__ #include #include +#endif /* __rtems__ */ #include #include @@ -66,6 +70,9 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #ifdef DEBUG #define debugf(fmt, args...) do { printf("%s(): ", __func__); \ @@ -80,13 +87,17 @@ struct lpe_dmamap_arg { struct lpe_rxdesc { struct mbuf * lpe_rxdesc_mbuf; +#ifndef __rtems__ bus_dmamap_t lpe_rxdesc_dmamap; +#endif /* __rtems__ */ }; struct lpe_txdesc { int lpe_txdesc_first; struct mbuf * lpe_txdesc_mbuf; +#ifndef __rtems__ bus_dmamap_t lpe_txdesc_dmamap; +#endif /* __rtems__ */ }; struct lpe_chain_data { @@ -122,7 +133,9 @@ struct lpe_ring_data { struct lpe_softc { struct ifnet * lpe_ifp; struct mtx lpe_mtx; +#ifndef __rtems__ phandle_t lpe_ofw; +#endif /* __rtems__ */ device_t lpe_dev; device_t lpe_miibus; uint8_t lpe_enaddr[6]; @@ -192,11 +205,13 @@ static int lpe_probe(device_t dev) { +#ifndef __rtems__ if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "lpc,ethernet")) return (ENXIO); +#endif /* __rtems__ */ device_set_desc(dev, "LPC32x0 10/100 Ethernet"); return (BUS_PROBE_DEFAULT); @@ -211,6 +226,7 @@ lpe_attach(device_t dev) uint32_t val; sc->lpe_dev = dev; +#ifndef __rtems__ sc->lpe_ofw = ofw_bus_get_node(dev); i = OF_getprop(sc->lpe_ofw, "local-mac-address", (void *)&sc->lpe_enaddr, 6); @@ -222,6 +238,9 @@ lpe_attach(device_t dev) sc->lpe_enaddr[4] = 0x44; sc->lpe_enaddr[5] = 0x55; } +#else /* __rtems__ */ + rtems_bsd_get_mac_address(device_get_name(sc->lpe_dev), device_get_unit(sc->lpe_dev), &sc->lpe_enaddr); +#endif /* __rtems__ */ mtx_init(&sc->lpe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); @@ -275,16 +294,33 @@ lpe_attach(device_t dev) } /* Enable Ethernet clock */ +#ifndef __rtems__ lpc_pwr_write(dev, LPC_CLKPWR_MACCLK_CTRL, LPC_CLKPWR_MACCLK_CTRL_REG | LPC_CLKPWR_MACCLK_CTRL_SLAVE | LPC_CLKPWR_MACCLK_CTRL_MASTER | LPC_CLKPWR_MACCLK_CTRL_HDWINF(3)); +#else /* __rtems__ */ +#ifdef LPC32XX_ETHERNET_RMII + lpc_pwr_write(dev, LPC_CLKPWR_MACCLK_CTRL, + LPC_CLKPWR_MACCLK_CTRL_REG | + LPC_CLKPWR_MACCLK_CTRL_SLAVE | + LPC_CLKPWR_MACCLK_CTRL_MASTER | + LPC_CLKPWR_MACCLK_CTRL_HDWINF(3)); +#else + lpc_pwr_write(dev, LPC_CLKPWR_MACCLK_CTRL, + LPC_CLKPWR_MACCLK_CTRL_REG | + LPC_CLKPWR_MACCLK_CTRL_SLAVE | + LPC_CLKPWR_MACCLK_CTRL_MASTER | + LPC_CLKPWR_MACCLK_CTRL_HDWINF(1)); +#endif +#endif /* __rtems__ */ /* Reset chip */ lpe_reset(sc); /* Initialize MII */ +#ifndef __rtems__ val = lpe_read_4(sc, LPE_COMMAND); lpe_write_4(sc, LPE_COMMAND, val | LPE_COMMAND_RMII); @@ -294,6 +330,14 @@ lpe_attach(device_t dev) device_printf(dev, "cannot find PHY\n"); goto fail; } +#else /* __rtems__ */ + if (mii_attach(dev, &sc->lpe_miibus, ifp, lpe_ifmedia_upd, + lpe_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, + MII_OFFSET_ANY, 0)) { + device_printf(dev, "cannot find PHY\n"); + goto fail; + } +#endif /* __rtems__ */ lpe_dma_alloc(sc); @@ -388,7 +432,9 @@ lpe_miibus_statchg(device_t dev) struct lpe_softc *sc = device_get_softc(dev); struct mii_data *mii = device_get_softc(sc->lpe_miibus); +#ifndef __rtems__ lpe_lock(sc); +#endif /* __rtems__ */ if ((mii->mii_media_status & IFM_ACTIVE) && (mii->mii_media_status & IFM_AVALID)) @@ -396,7 +442,9 @@ lpe_miibus_statchg(device_t dev) else sc->lpe_flags &= ~LPE_FLAG_LINK; +#ifndef __rtems__ lpe_unlock(sc); +#endif /* __rtems__ */ } static void @@ -404,6 +452,7 @@ lpe_reset(struct lpe_softc *sc) { uint32_t mac1; +#ifndef __rtems__ /* Enter soft reset mode */ mac1 = lpe_read_4(sc, LPE_MAC1); lpe_write_4(sc, LPE_MAC1, mac1 | LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | @@ -422,6 +471,43 @@ lpe_reset(struct lpe_softc *sc) mac1 = lpe_read_4(sc, LPE_MAC1); lpe_write_4(sc, LPE_MAC1, mac1 & ~(LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX)); +#else /* __rtems__ */ + /* Reset registers, Tx path and Rx path */ + lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_REGRESET | LPE_COMMAND_TXRESET | LPE_COMMAND_RXRESET); + + /* Enter soft reset mode */ + mac1 = lpe_read_4(sc, LPE_MAC1); + lpe_write_4(sc, LPE_MAC1, mac1 | LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | + LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX); + + /* Leave soft reset mode */ + mac1 = lpe_read_4(sc, LPE_MAC1); + lpe_write_4(sc, LPE_MAC1, mac1 & ~(LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | + LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX)); + + /* Reinitialize registers */ + lpe_write_4(sc, LPE_MCFG, LPE_MCFG_CLKSEL(0x7)); + lpe_write_4(sc, LPE_MAC2, LPE_MAC2_PADCRCENABLE | LPE_MAC2_CRCENABLE | LPE_MAC2_FULLDUPLEX); + lpe_write_4(sc, LPE_IPGT, 0x15); + lpe_write_4(sc, LPE_IPGR, 0x12); + lpe_write_4(sc, LPE_CLRT, 0x370f); + lpe_write_4(sc, LPE_MAXF, 0x0600); + lpe_write_4(sc, LPE_SUPP, LPE_SUPP_SPEED); + lpe_write_4(sc, LPE_TEST, 0x0); +#ifdef LPC32XX_ETHERNET_RMII + lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_FULLDUPLEX | LPE_COMMAND_RMII); +#else + lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_FULLDUPLEX); +#endif + lpe_write_4(sc, LPE_INTENABLE, 0x0); + lpe_write_4(sc, LPE_INTCLEAR, 0x30ff); + lpe_write_4(sc, LPE_POWERDOWN, 0x0); + + /* Set station address */ + lpe_write_4(sc, LPE_SA2, sc->lpe_enaddr[1] << 8 | sc->lpe_enaddr[0]); + lpe_write_4(sc, LPE_SA1, sc->lpe_enaddr[3] << 8 | sc->lpe_enaddr[2]); + lpe_write_4(sc, LPE_SA0, sc->lpe_enaddr[5] << 8 | sc->lpe_enaddr[4]); +#endif /* __rtems__ */ } static void @@ -533,6 +619,31 @@ lpe_start_locked(struct ifnet *ifp) } +#ifdef __rtems__ +static int +lpe_get_segs_for_tx(struct mbuf *m, bus_dma_segment_t segs[LPE_MAXFRAGS], + int *nsegs) +{ + int i = 0; + + do { + if (m->m_len > 0) { + segs[i].ds_addr = mtod(m, bus_addr_t); + segs[i].ds_len = m->m_len; +#ifdef CPU_DATA_CACHE_ALIGNMENT + rtems_cache_flush_multiple_data_lines(m->m_data, m->m_len); +#endif + ++i; + } + m = m->m_next; + if (m == NULL) { + *nsegs = i; + return (0); + } + } while (i < LPE_MAXFRAGS); + return (EFBIG); +} +#endif /* __rtems__ */ static int lpe_encap(struct lpe_softc *sc, struct mbuf **m_head) { @@ -549,8 +660,12 @@ lpe_encap(struct lpe_softc *sc, struct mbuf **m_head) debugf("starting with prod=%d\n", prod); +#ifndef __rtems__ err = bus_dmamap_load_mbuf_sg(sc->lpe_cdata.lpe_tx_buf_tag, txd->lpe_txdesc_dmamap, *m_head, segs, &nsegs, BUS_DMA_NOWAIT); +#else /* __rtems__ */ + err = lpe_get_segs_for_tx(*m_head, segs, &nsegs); +#endif /* __rtems__ */ if (err) return (err); @@ -561,8 +676,10 @@ lpe_encap(struct lpe_softc *sc, struct mbuf **m_head) return (EIO); } +#ifndef __rtems__ bus_dmamap_sync(sc->lpe_cdata.lpe_tx_buf_tag, txd->lpe_txdesc_dmamap, BUS_DMASYNC_PREREAD); +#endif /* __rtems__ */ bus_dmamap_sync(sc->lpe_cdata.lpe_tx_ring_tag, sc->lpe_cdata.lpe_tx_ring_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); @@ -581,6 +698,11 @@ lpe_encap(struct lpe_softc *sc, struct mbuf **m_head) hwd->lhr_control |= LPE_HWDESC_PAD; } +#ifdef __rtems__ +#ifdef CPU_DATA_CACHE_ALIGNMENT + rtems_cache_flush_multiple_data_lines(hwd, sizeof(*hwd)); +#endif +#endif /* __rtems__ */ LPE_INC(prod, LPE_TXDESC_NUM); } @@ -724,9 +846,19 @@ lpe_intr(void *arg) if (intstatus & LPE_INT_RXDONE) lpe_rxintr(sc); +#ifndef __rtems__ if (intstatus & LPE_INT_TXDONE) lpe_txintr(sc); +#else /* __rtems__ */ + if (intstatus & LPE_INT_TXUNDERRUN) { + if_inc_counter(sc->lpe_ifp, IFCOUNTER_OERRORS, 1); + lpe_stop_locked(sc); + lpe_init_locked(sc); + } + else if (intstatus & (LPE_INT_TXERROR | LPE_INT_TXFINISH | LPE_INT_TXDONE)) + lpe_txintr(sc); +#endif /* __rtems__ */ lpe_write_4(sc, LPE_INTCLEAR, 0xffff); } @@ -753,6 +885,13 @@ lpe_rxintr(struct lpe_softc *sc) rxd = &sc->lpe_cdata.lpe_rx_desc[cons]; hwd = &sc->lpe_rdata.lpe_rx_ring[cons]; hws = &sc->lpe_rdata.lpe_rx_status[cons]; +#ifdef __rtems__ +#ifdef CPU_DATA_CACHE_ALIGNMENT + rtems_cache_invalidate_multiple_data_lines(rxd, sizeof(*rxd)); + rtems_cache_invalidate_multiple_data_lines(hwd, sizeof(*hwd)); + rtems_cache_invalidate_multiple_data_lines(hws, sizeof(*hws)); +#endif +#endif /* __rtems__ */ /* Check received frame for errors */ if (hws->lhs_info & LPE_HWDESC_RXERRS) { @@ -763,6 +902,11 @@ lpe_rxintr(struct lpe_softc *sc) } m = rxd->lpe_rxdesc_mbuf; +#ifdef __rtems__ +#ifdef CPU_DATA_CACHE_ALIGNMENT + rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len); +#endif +#endif /* __rtems__ */ m->m_pkthdr.rcvif = ifp; m->m_data += 2; @@ -799,8 +943,16 @@ lpe_txintr(struct lpe_softc *sc) hwd = &sc->lpe_rdata.lpe_tx_ring[last]; hws = &sc->lpe_rdata.lpe_tx_status[last]; +#ifndef __rtems__ bus_dmamap_sync(sc->lpe_cdata.lpe_tx_buf_tag, txd->lpe_txdesc_dmamap, BUS_DMASYNC_POSTWRITE); +#else /* __rtems__ */ +#ifdef CPU_DATA_CACHE_ALIGNMENT + rtems_cache_invalidate_multiple_data_lines(txd, sizeof(*txd)); + rtems_cache_invalidate_multiple_data_lines(hwd, sizeof(*hwd)); + rtems_cache_invalidate_multiple_data_lines(hws, sizeof(*hws)); +#endif +#endif /* __rtems__ */ if_inc_counter(ifp, IFCOUNTER_COLLISIONS, LPE_HWDESC_COLLISIONS(hws->lhs_info)); @@ -810,8 +962,10 @@ lpe_txintr(struct lpe_softc *sc) if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); if (txd->lpe_txdesc_first) { +#ifndef __rtems__ bus_dmamap_unload(sc->lpe_cdata.lpe_tx_buf_tag, txd->lpe_txdesc_dmamap); +#endif /* __rtems__ */ m_freem(txd->lpe_txdesc_mbuf); txd->lpe_txdesc_mbuf = NULL; @@ -979,6 +1133,7 @@ lpe_dma_alloc_rx(struct lpe_softc *sc) for (i = 0; i < LPE_RXDESC_NUM; i++) { rxd = &sc->lpe_cdata.lpe_rx_desc[i]; rxd->lpe_rxdesc_mbuf = NULL; +#ifndef __rtems__ rxd->lpe_rxdesc_dmamap = NULL; err = bus_dmamap_create(sc->lpe_cdata.lpe_rx_buf_tag, 0, @@ -988,6 +1143,7 @@ lpe_dma_alloc_rx(struct lpe_softc *sc) device_printf(sc->lpe_dev, "cannot create Rx DMA map\n"); return (err); } +#endif /* __rtems__ */ } return (0); @@ -1081,11 +1237,15 @@ lpe_dma_alloc_tx(struct lpe_softc *sc) for (i = 0; i < LPE_TXDESC_NUM; i++) { txd = &sc->lpe_cdata.lpe_tx_desc[i]; txd->lpe_txdesc_mbuf = NULL; +#ifndef __rtems__ txd->lpe_txdesc_dmamap = NULL; +#endif /* __rtems__ */ txd->lpe_txdesc_first = 0; +#ifndef __rtems__ err = bus_dmamap_create(sc->lpe_cdata.lpe_tx_buf_tag, 0, &txd->lpe_txdesc_dmamap); +#endif /* __rtems__ */ if (err) { device_printf(sc->lpe_dev, "cannot create Tx DMA map\n"); @@ -1134,6 +1294,7 @@ lpe_init_rxbuf(struct lpe_softc *sc, int n) m->m_len = m->m_pkthdr.len = MCLBYTES; +#ifndef __rtems__ bus_dmamap_unload(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap); if (bus_dmamap_load_mbuf_sg(sc->lpe_cdata.lpe_rx_buf_tag, @@ -1144,10 +1305,21 @@ lpe_init_rxbuf(struct lpe_softc *sc, int n) bus_dmamap_sync(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap, BUS_DMASYNC_PREREAD); +#else /* __rtems__ */ +#ifdef CPU_DATA_CACHE_ALIGNMENT + rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len); +#endif + segs[0].ds_addr = mtod(m, bus_addr_t); +#endif /* __rtems__ */ rxd->lpe_rxdesc_mbuf = m; hwd->lhr_data = segs[0].ds_addr + 2; hwd->lhr_control = (segs[0].ds_len - 1) | LPE_HWDESC_INTERRUPT; +#ifdef __rtems__ +#ifdef CPU_DATA_CACHE_ALIGNMENT + rtems_cache_flush_multiple_data_lines(hwd, sizeof(*hwd)); +#endif +#endif /* __rtems__ */ return (0); } @@ -1161,7 +1333,9 @@ lpe_discard_rxbuf(struct lpe_softc *sc, int n) rxd = &sc->lpe_cdata.lpe_rx_desc[n]; hwd = &sc->lpe_rdata.lpe_rx_ring[n]; +#ifndef __rtems__ bus_dmamap_unload(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap); +#endif /* __rtems__ */ hwd->lhr_data = 0; hwd->lhr_control = 0; @@ -1227,7 +1401,11 @@ static driver_t lpe_driver = { static devclass_t lpe_devclass; +#ifndef __rtems__ DRIVER_MODULE(lpe, simplebus, lpe_driver, lpe_devclass, 0, 0); +#else /* __rtems__ */ +DRIVER_MODULE(lpe, nexus, lpe_driver, lpe_devclass, 0, 0); +#endif /* __rtems__ */ DRIVER_MODULE(miibus, lpe, miibus_driver, miibus_devclass, 0, 0); MODULE_DEPEND(lpe, obio, 1, 1, 1); MODULE_DEPEND(lpe, miibus, 1, 1, 1); diff --git a/freebsd/sys/arm/lpc/lpc_pwr.c b/freebsd/sys/arm/lpc/lpc_pwr.c old mode 100644 new mode 100755 index 0ea8c6a2..231024d4 --- a/freebsd/sys/arm/lpc/lpc_pwr.c +++ b/freebsd/sys/arm/lpc/lpc_pwr.c @@ -38,10 +38,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifndef __rtems__ #include #include #include +#endif /* __rtems__ */ #include #include @@ -67,11 +69,13 @@ static int lpc_pwr_probe(device_t dev) { +#ifndef __rtems__ if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "lpc,pwr")) return (ENXIO); +#endif /* __rtems__ */ device_set_desc(dev, "LPC32x0 Power Controller"); return (BUS_PROBE_DEFAULT); @@ -128,4 +132,8 @@ static driver_t lpc_pwr_driver = { sizeof(struct lpc_pwr_softc), }; +#ifndef __rtems__ DRIVER_MODULE(pwr, simplebus, lpc_pwr_driver, lpc_pwr_devclass, 0, 0); +#else /* __rtems__ */ +DRIVER_MODULE(pwr, nexus, lpc_pwr_driver, lpc_pwr_devclass, 0, 0); +#endif /* __rtems__ */ diff --git a/freebsd/sys/dev/mii/icsphy.c b/freebsd/sys/dev/mii/icsphy.c old mode 100644 new mode 100755 index 29444f38..a51b899f --- a/freebsd/sys/dev/mii/icsphy.c +++ b/freebsd/sys/dev/mii/icsphy.c @@ -113,6 +113,9 @@ static const struct mii_phydesc icsphys[] = { MII_PHY_DESC(ICS, 1890), MII_PHY_DESC(ICS, 1892), MII_PHY_DESC(ICS, 1893), +#ifdef __rtems__ + MII_PHY_DESC(ICS, 1893C), +#endif /* __rtems__ */ MII_PHY_END }; diff --git a/freebsd/sys/dev/usb/controller/ohci.h b/freebsd/sys/dev/usb/controller/ohci.h old mode 100644 new mode 100755 index d020d998..a650ce15 --- a/freebsd/sys/dev/usb/controller/ohci.h +++ b/freebsd/sys/dev/usb/controller/ohci.h @@ -234,9 +234,7 @@ typedef struct ohci_softc { struct ohci_ed *sc_bulk_p_last; struct ohci_ed *sc_isoc_p_last; struct ohci_ed *sc_intr_p_last[OHCI_NO_EDS]; -#ifndef __rtems__ void *sc_intr_hdl; -#endif /* __rtems__ */ device_t sc_dev; bus_size_t sc_io_size; bus_space_tag_t sc_io_tag; diff --git a/libbsd.py b/libbsd.py index 7264ac4a..43107ee6 100755 --- a/libbsd.py +++ b/libbsd.py @@ -148,6 +148,7 @@ def rtems(mm): 'pppd/utils.c', 'sys/dev/usb/controller/ehci_mpc83xx.c', 'sys/dev/usb/controller/ohci_lpc.c', + 'sys/dev/usb/controller/ohci_lpc32xx.c', 'sys/dev/usb/controller/dwc_otg_nexus.c', 'sys/dev/usb/controller/usb_otg_transceiver.c', 'sys/dev/usb/controller/usb_otg_transceiver_dump.c', @@ -1083,6 +1084,9 @@ def dev_net(mm): 'sys/dev/dwc/if_dwc.h', 'sys/dev/dwc/if_dwcvar.h', 'sys/arm/xilinx/zy7_slcr.h', + 'sys/arm/lpc/if_lpereg.h', + 'sys/arm/lpc/lpcreg.h', + 'sys/arm/lpc/lpcvar.h', ] ) mod.addKernelSpaceSourceFiles( @@ -1101,6 +1105,8 @@ def dev_net(mm): 'sys/dev/cadence/if_cgem.c', 'sys/dev/dwc/if_dwc.c', 'sys/arm/xilinx/zy7_slcr.c', + 'sys/arm/lpc/lpc_pwr.c', + 'sys/arm/lpc/if_lpe.c', ], mm.generator['source']() ) diff --git a/libbsd_waf.py b/libbsd_waf.py index ecd87af7..ef3150b1 100644 --- a/libbsd_waf.py +++ b/libbsd_waf.py @@ -722,7 +722,9 @@ def build(bld): source = objs07_source) libbsd_use += ["objs07"] - source = ['freebsd/sys/arm/xilinx/zy7_slcr.c', + source = ['freebsd/sys/arm/lpc/if_lpe.c', + 'freebsd/sys/arm/lpc/lpc_pwr.c', + 'freebsd/sys/arm/xilinx/zy7_slcr.c', 'freebsd/sys/cam/cam.c', 'freebsd/sys/cam/scsi/scsi_all.c', 'freebsd/sys/crypto/blowfish/bf_ecb.c', @@ -1325,6 +1327,7 @@ def build(bld): 'rtemsbsd/sys/dev/usb/controller/dwc_otg_nexus.c', 'rtemsbsd/sys/dev/usb/controller/ehci_mpc83xx.c', 'rtemsbsd/sys/dev/usb/controller/ohci_lpc.c', + 'rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c', 'rtemsbsd/sys/dev/usb/controller/usb_otg_transceiver.c', 'rtemsbsd/sys/dev/usb/controller/usb_otg_transceiver_dump.c', 'rtemsbsd/sys/fs/devfs/devfs_devs.c', diff --git a/rtemsbsd/include/bsp/nexus-devices.h b/rtemsbsd/include/bsp/nexus-devices.h old mode 100644 new mode 100755 index 0b4ec62b..b6814347 --- a/rtemsbsd/include/bsp/nexus-devices.h +++ b/rtemsbsd/include/bsp/nexus-devices.h @@ -46,6 +46,18 @@ RTEMS_BSD_DRIVER_SMC0(0x4e000000, RVPBXA9_IRQ_ETHERNET); +#elif defined(LIBBSP_ARM_LPC32XX_BSP_H) + +#include + +RTEMS_BSD_DRIVER_LPC32XX_PWR; +RTEMS_BSD_DRIVER_LPC32XX_LPE; +RTEMS_BSD_DRIVER_ICSPHY; +RTEMS_BSD_DRIVER_LPC32XX_OHCI; +SYSINIT_DRIVER_REFERENCE(usbus, ohci); +RTEMS_BSD_DRIVER_USB; +RTEMS_BSD_DRIVER_USB_MASS; + #elif defined(LIBBSP_M68K_GENMCF548X_BSP_H) RTEMS_BSD_DRIVER_FEC; diff --git a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h old mode 100644 new mode 100755 index a408c172..299221c7 --- a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h +++ b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h @@ -38,6 +38,7 @@ * * Devices: * RTEMS_BSD_DRIVER_XILINX_ZYNQ_SLCR + * RTEMS_BSD_DRIVER_LPC32XX_PWR * * Buses: * RTEMS_BSD_DRIVER_PC_LEGACY @@ -46,6 +47,7 @@ * RTEMS_BSD_DRIVER_DWCOTG0 * RTEMS_BSD_DRIVER_DWCOTG0_BASE_ADDR * RTEMS_BSD_DRIVER_DWCOTG0_IRQ + * RTEMS_BSD_DRIVER_LPC32XX_OHCI * RTEMS_BSD_DRIVER_DWC_MMC * RTEMS_BSD_DRIVER_MMC * RTEMS_BSD_DRIVER_USB @@ -55,6 +57,7 @@ * RTEMS_BSD_DRIVER_SMC0 * RTEMS_BSD_DRIVER_SMC0_BASE_ADDR * RTEMS_BSD_DRIVER_SMC0_IRQ + * RTEMS_BSD_DRIVER_LPC32XX_LPE * RTEMS_BSD_DRIVER_FEC * RTEMS_BSD_DRIVER_XILINX_ZYNQ_CGEM0 * RTEMS_BSD_DRIVER_CGEM0_IRQ @@ -73,6 +76,7 @@ * * MMI PHY: * RTEMS_BSD_DRIVER_E1000PHY + * RTEMS_BSD_DRIVER_ICSPHY * RTEMS_BSD_DRIVER_REPHY * RTEMS_BSD_DRIVER_MIPHY */ @@ -115,6 +119,23 @@ extern "C" { &zy7_slcr_res[0]) #endif /* RTEMS_BSD_DRIVER_XILINX_ZYNQ_SLCR */ +/* + * LPC32XX Power Control (PWR). + */ +#if !defined(RTEMS_BSD_DRIVER_LPC32XX_PWR) + #define RTEMS_BSD_DRIVER_LPC32XX_PWR \ + static const rtems_bsd_device_resource lpc_pwr0_res[] = { \ + { \ + .type = RTEMS_BSD_RES_MEMORY, \ + .start_request = 0, \ + .start_actual = LPC32XX_BASE_SYSCON \ + } \ + }; \ + RTEMS_BSD_DEFINE_NEXUS_DEVICE_ORDERED(pwr, 0, RTEMS_SYSINIT_ORDER_FIRST, \ + RTEMS_ARRAY_SIZE(lpc_pwr0_res), \ + &lpc_pwr0_res[0]) +#endif /* RTEMS_BSD_DRIVER_LPC32XX_PWR */ + /** ** Physical Buses **/ @@ -154,6 +175,31 @@ extern "C" { &dwcotg0_res[0]) #endif /* RTEMS_BSD_DRIVER_DWCOTG0 */ +/* + * LPC32XX OHCI. + */ +#if !defined(RTEMS_BSD_DRIVER_LPC32XX_OHCI) + #define RTEMS_BSD_DRIVER_LPC32XX_OHCI \ + static const rtems_bsd_device_resource lpc_ohci0_res[] = { \ + { \ + .type = RTEMS_BSD_RES_MEMORY, \ + .start_request = 0, \ + .start_actual = LPC32XX_BASE_USB \ + }, { \ + .type = RTEMS_BSD_RES_MEMORY, \ + .start_request = 0, \ + .start_actual = (unsigned long)(&LPC32XX_I2C_RX) \ + }, { \ + .type = RTEMS_BSD_RES_IRQ, \ + .start_request = 0, \ + .start_actual = LPC32XX_IRQ_USB_HOST \ + } \ + }; \ + RTEMS_BSD_DEFINE_NEXUS_DEVICE(ohci, 0, \ + RTEMS_ARRAY_SIZE(lpc_ohci0_res), \ + &lpc_ohci0_res[0]) +#endif /* RTEMS_BSD_DRIVER_LPC32XX_OHCI */ + /* * Designware/Synopsys MMC. */ @@ -213,6 +259,27 @@ extern "C" { &smc0_res[0]) #endif /* RTEMS_BSD_DRIVER_SMC */ +/* + * LPC32XX LPE driver + */ +#if !defined(RTEMS_BSD_DRIVER_LPC32XX_LPE) + #define RTEMS_BSD_DRIVER_LPC32XX_LPE \ + static const rtems_bsd_device_resource lpc_lpe0_res[] = { \ + { \ + .type = RTEMS_BSD_RES_MEMORY, \ + .start_request = 0, \ + .start_actual = LPC32XX_BASE_ETHERNET \ + }, { \ + .type = RTEMS_BSD_RES_IRQ, \ + .start_request = 0, \ + .start_actual = LPC32XX_IRQ_ETHERNET \ + } \ + }; \ + RTEMS_BSD_DEFINE_NEXUS_DEVICE(lpe, 0, \ + RTEMS_ARRAY_SIZE(lpc_lpe0_res), \ + &lpc_lpe0_res[0]) +#endif /* RTEMS_BSD_DRIVER_LPC32XX_LPE */ + /* * Coldfire Fast Ethernet Controller (FEC) driver. */ @@ -344,6 +411,14 @@ extern "C" { SYSINIT_DRIVER_REFERENCE(e1000phy, miibus); #endif /* RTEMS_BSD_DRIVER_E1000PHY */ +/* + * ICS PHY + */ +#if !defined(RTEMS_BSD_DRIVER_ICSPHY) + #define RTEMS_BSD_DRIVER_ICSPHY \ + SYSINIT_DRIVER_REFERENCE(icsphy, miibus); +#endif /* RTEMS_BSD_DRIVER_ICSPHY */ + /* * Reltek PHY */ diff --git a/rtemsbsd/include/rtems/bsd/local/miidevs.h b/rtemsbsd/include/rtems/bsd/local/miidevs.h old mode 100644 new mode 100755 index 2199229d..18931b27 --- a/rtemsbsd/include/rtems/bsd/local/miidevs.h +++ b/rtemsbsd/include/rtems/bsd/local/miidevs.h @@ -318,6 +318,8 @@ #define MII_STR_ICS_1892 "ICS1892 10/100 media interface" #define MII_MODEL_ICS_1893 0x0004 #define MII_STR_ICS_1893 "ICS1893 10/100 media interface" +#define MII_MODEL_ICS_1893C 0x0005 +#define MII_STR_ICS_1893C "ICS1893C 10/100 media interface" /* Intel Corporation PHYs */ #define MII_MODEL_xxINTEL_I82553 0x0000 diff --git a/rtemsbsd/sys/dev/usb/controller/ohci_lpc.c b/rtemsbsd/sys/dev/usb/controller/ohci_lpc.c old mode 100644 new mode 100755 index a0314c54..de5bf2d2 --- a/rtemsbsd/sys/dev/usb/controller/ohci_lpc.c +++ b/rtemsbsd/sys/dev/usb/controller/ohci_lpc.c @@ -36,12 +36,9 @@ #include -#if defined(LIBBSP_ARM_LPC24XX_BSP_H) || defined(LIBBSP_ARM_LPC32XX_BSP_H) +#if defined(LIBBSP_ARM_LPC24XX_BSP_H) #include - -#ifdef LIBBSP_ARM_LPC24XX_BSP_H - #include #include @@ -101,92 +98,6 @@ static void lpc_otg_status_and_control(void) OTG_STAT_CTRL = 0x3; } -#endif /* LIBBSP_ARM_LPC24XX_BSP_H */ - -#ifdef LIBBSP_ARM_LPC32XX_BSP_H - -#include - -#define LPC_USB_OHCI_BASE LPC32XX_BASE_USB - -#define LPC_USB_I2C_BASE (&LPC32XX_I2C_RX) - -#define LPC_OTG_CLK_CTRL LPC32XX_OTG_CLK_CTRL - -#define LPC_OTG_CLK_STAT LPC32XX_OTG_CLK_STAT - -#define LPC_USB_OHCI_IRQ LPC32XX_IRQ_USB_HOST - -#define USB_CTRL_SLAVE_HCLK_EN (1U << 24) -#define USB_CTRL_I2C_EN (1U << 23) -#define USB_CTRL_DEV_NEED_CLK_EN (1U << 22) -#define USB_CTRL_HOST_NEED_CLK_EN (1U << 21) -#define USB_CTRL_PC_MASK (0x3U << 19) -#define USB_CTRL_PC_PULL_UP (0x0U << 19) -#define USB_CTRL_PC_BUS_KEEPER (0x1U << 19) -#define USB_CTRL_PC_NONE (0x2U << 19) -#define USB_CTRL_PC_PULL_DOWN (0x3U << 19) -#define USB_CTRL_CLKEN2 (1U << 18) -#define USB_CTRL_CLKEN1 (1U << 17) -#define USB_CTRL_POWER_UP (1U << 16) -#define USB_CTRL_BYPASS (1U << 15) -#define USB_CTRL_DIRECT (1U << 14) -#define USB_CTRL_FEEDBACK (1U << 13) -#define USB_CTRL_P_SHIFT 11 -#define USB_CTRL_P_MASK (0x3U << USB_CTRL_P_SHIFT) -#define USB_CTRL_P_1 (0x0U << USB_CTRL_P_SHIFT) -#define USB_CTRL_P_2 (0x1U << USB_CTRL_P_SHIFT) -#define USB_CTRL_P_4 (0x2U << USB_CTRL_P_SHIFT) -#define USB_CTRL_P_8 (0x3U << USB_CTRL_P_SHIFT) -#define USB_CTRL_N_SHIFT 9 -#define USB_CTRL_N_MASK (0x3U << USB_CTRL_N_SHIFT) -#define USB_CTRL_N_1 (0x0U << USB_CTRL_N_SHIFT) -#define USB_CTRL_N_2 (0x1U << USB_CTRL_N_SHIFT) -#define USB_CTRL_N_3 (0x2U << USB_CTRL_N_SHIFT) -#define USB_CTRL_N_4 (0x3U << USB_CTRL_N_SHIFT) -#define USB_CTRL_M_SHIFT 1 -#define USB_CTRL_M_MASK (0xffU << USB_CTRL_M_SHIFT) -#define USB_CTRL_PLL_LOCK (1U << 0) - -static void lpc_usb_module_enable(void) -{ - LPC32XX_USB_DIV = 0xc; - LPC32XX_USB_CTRL = USB_CTRL_SLAVE_HCLK_EN - | USB_CTRL_PC_BUS_KEEPER - | USB_CTRL_CLKEN1 - | USB_CTRL_POWER_UP - | USB_CTRL_P_2 - | USB_CTRL_N_1 - | (191U << USB_CTRL_M_SHIFT); - while ((LPC32XX_USB_CTRL & USB_CTRL_PLL_LOCK) == 0) { - /* Wait */ - } - LPC32XX_USB_CTRL |= USB_CTRL_CLKEN2; -} - -static void lpc_usb_module_disable(void) -{ - LPC32XX_OTG_CLK_CTRL = 0; - LPC32XX_USB_CTRL = USB_CTRL_PC_BUS_KEEPER; -} - -static void lpc_usb_pin_config(void) -{ - /* Nothing to do */ -} - -static void lpc_usb_host_clock_enable(void) -{ - LPC32XX_USB_CTRL |= USB_CTRL_HOST_NEED_CLK_EN; -} - -static void lpc_otg_status_and_control(void) -{ - LPC32XX_OTG_STAT_CTRL = 0x1; -} - -#endif /* LIBBSP_ARM_LPC32XX_BSP_H */ - static rtems_interval lpc_usb_timeout_init(void) { return rtems_clock_get_ticks_since_boot(); @@ -639,4 +550,4 @@ static devclass_t ohci_devclass; DRIVER_MODULE(ohci, nexus, ohci_driver, ohci_devclass, 0, 0); MODULE_DEPEND(ohci, usb, 1, 1, 1); -#endif /* defined(LIBBSP_ARM_LPC24XX_BSP_H) || defined(LIBBSP_ARM_LPC32XX_BSP_H) */ +#endif /* defined(LIBBSP_ARM_LPC24XX_BSP_H) */ diff --git a/rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c b/rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c new file mode 100755 index 00000000..eaa0f5f9 --- /dev/null +++ b/rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c @@ -0,0 +1,499 @@ +/*- + * Copyright (c) 2011 Jakub Wojciech Klama + * All rights reserved. + * + * 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 + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#if defined(LIBBSP_ARM_LPC32XX_BSP_H) + +#ifdef BSP_USB_OTG_TRANSCEIVER_I2C_ADDR +#include +#endif /* BSP_USB_OTG_TRANSCEIVER_I2C_ADDR */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define I2C_START_BIT (1 << 8) +#define I2C_STOP_BIT (1 << 9) +#define I2C_READ 0x01 +#define I2C_WRITE 0x00 +#define DUMMY_BYTE 0x55 + +#define lpc_otg_read_4(_sc, _reg) \ + bus_space_read_4(_sc->sc_io_tag, _sc->sc_io_hdl, _reg) +#define lpc_otg_write_4(_sc, _reg, _value) \ + bus_space_write_4(_sc->sc_io_tag, _sc->sc_io_hdl, _reg, _value) +#define lpc_otg_wait_write_4(_sc, _wreg, _sreg, _value) \ + do { \ + lpc_otg_write_4(_sc, _wreg, _value); \ + while ((lpc_otg_read_4(_sc, _sreg) & _value) != _value); \ + } while (0); + +static int lpc_ohci_probe(device_t dev); +static int lpc_ohci_attach(device_t dev); +static int lpc_ohci_detach(device_t dev); + +static void lpc_usb_module_enable(device_t dev, struct ohci_softc *); +static void lpc_usb_module_disable(device_t dev, struct ohci_softc *); +static void lpc_usb_pin_config(device_t dev, struct ohci_softc *); +static void lpc_usb_host_clock_enable(device_t dev, struct ohci_softc *); +static void lpc_otg_status_and_control(device_t dev, struct ohci_softc *); +static rtems_interval lpc_usb_timeout_init(void); +static bool lpc_usb_timeout_not_expired(rtems_interval start); +static int lpc_otg_clk_ctrl(device_t dev, struct ohci_softc *sc, uint32_t otg_clk_ctrl); +static int lpc_otg_i2c_wait_for_receive_fifo_not_empty(struct ohci_softc *sc); +static int lpc_otg_i2c_wait_for_transaction_done(struct ohci_softc *sc); +static int lpc_otg_i2c_read(const struct usb_otg_transceiver *self, uint8_t reg_addr, uint8_t *value); +static int lpc_otg_i2c_write(const struct usb_otg_transceiver *self, uint8_t reg_addr, uint8_t value); + +static int +lpc_ohci_probe(device_t dev) +{ + + device_set_desc(dev, "LPC32x0 USB OHCI controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +lpc_ohci_attach(device_t dev) +{ + struct ohci_softc *sc = device_get_softc(dev); + int err; + int eno; + int rid; + int i = 0; + uint32_t usbctrl; + uint32_t otgstatus; + + sc->sc_bus.parent = dev; + sc->sc_bus.devices = sc->sc_devices; + sc->sc_bus.devices_max = OHCI_MAX_DEVICES; + sc->sc_bus.dma_bits = 32; + + if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev), + &ohci_iterate_hw_softc)) + return (ENOMEM); + + rid = 0; + sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (!sc->sc_io_res) { + device_printf(dev, "cannot map OHCI register space\n"); + goto fail; + } + + sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); + sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); + sc->sc_io_size = rman_get_size(sc->sc_io_res); + + rid = 0; + sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); + if (sc->sc_irq_res == NULL) { + device_printf(dev, "cannot allocate interrupt\n"); + goto fail; + } + + sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); + if (!(sc->sc_bus.bdev)) + goto fail; + + device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); + strlcpy(sc->sc_vendor, "NXP", sizeof(sc->sc_vendor)); + + err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, + NULL, (void *)ohci_interrupt, sc, &sc->sc_intr_hdl); + if (err) { + sc->sc_intr_hdl = NULL; + goto fail; + } + + lpc_usb_module_enable(dev, sc); + + eno = lpc_otg_clk_ctrl(dev, sc, LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_I2C_EN); + if (eno != 0) { + goto fail; + } + + lpc_usb_pin_config(dev, sc); + +#ifdef BSP_USB_OTG_TRANSCEIVER_I2C_ADDR + sc->sc_otg_trans.read = lpc_otg_i2c_read; + sc->sc_otg_trans.write = lpc_otg_i2c_write; + sc->sc_otg_trans.i2c_addr = BSP_USB_OTG_TRANSCEIVER_I2C_ADDR; + sc->sc_otg_trans.softc = sc; + eno = usb_otg_transceiver_init(&sc->sc_otg_trans); + if (eno != 0) { + goto fail; + } + +#ifdef BSP_USB_OTG_TRANSCEIVER_DUMP + usb_otg_transceiver_dump(&sc->sc_otg_trans); +#endif /* BSP_USB_OTG_TRANSCEIVER_DUMP */ + + eno = usb_otg_transceiver_resume(&sc->sc_otg_trans); + if (eno != 0) { + goto fail; + } +#endif /* BSP_USB_OTG_TRANSCEIVER_I2C_ADDR */ + + lpc_usb_host_clock_enable(dev, sc); + + eno = lpc_otg_clk_ctrl( dev, sc, + LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_HOST_EN + | LPC_OTG_CLOCK_CTRL_I2C_EN | LPC_OTG_CLOCK_CTRL_OTG_EN + ); + if (eno != 0) { + goto fail; + } + + lpc_otg_status_and_control(dev, sc); + +#if defined(BSP_USB_OTG_TRANSCEIVER_I2C_ADDR) \ + && defined(BSP_USB_OTG_TRANSCEIVER_VBUS) + eno = usb_otg_transceiver_set_vbus( + &sc->sc_otg_trans, + BSP_USB_OTG_TRANSCEIVER_VBUS + ); + if (eno != 0) { + goto fail; + } +#endif /* defined(BSP_USB_OTG_TRANSCEIVER_I2C_ADDR) + && defined(BSP_USB_OTG_TRANSCEIVER_VBUS) */ + +#if defined(BSP_USB_OTG_TRANSCEIVER_I2C_ADDR) \ + && defined(BSP_USB_OTG_TRANSCEIVER_DUMP) + usb_otg_transceiver_dump(&sc->sc_otg_trans); +#endif /* defined(BSP_USB_OTG_TRANSCEIVER_I2C_ADDR) + && defined(BSP_USB_OTG_TRANSCEIVER_DUMP) */ + + eno = lpc_otg_clk_ctrl(dev, sc, LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_HOST_EN); + if (eno != 0) { + goto fail; + } + + err = ohci_init(sc); + if (err) + goto fail; + + err = device_probe_and_attach(sc->sc_bus.bdev); + if (err) + goto fail; + + return (0); + +fail: + if (sc->sc_intr_hdl) + bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr_hdl); + if (sc->sc_irq_res) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); + if (sc->sc_io_res) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_io_res); + + return (ENXIO); +} + +static int +lpc_ohci_detach(device_t dev) +{ + return (0); +} + +static void lpc_usb_module_enable(device_t dev, struct ohci_softc *sc) +{ + uint32_t usbctrl; + + lpc_pwr_write(dev, LPC_CLKPWR_USBDIV_CTRL, 0xc); + lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, + LPC_CLKPWR_USB_CTRL_SLAVE_HCLK | + LPC_CLKPWR_USB_CTRL_BUSKEEPER | + LPC_CLKPWR_USB_CTRL_CLK_EN1 | + LPC_CLKPWR_USB_CTRL_PLL_PDOWN | + LPC_CLKPWR_USB_CTRL_POSTDIV(1) | + LPC_CLKPWR_USB_CTRL_PREDIV(0) | + LPC_CLKPWR_USB_CTRL_FDBKDIV(192)); + do { + usbctrl = lpc_pwr_read(dev, LPC_CLKPWR_USB_CTRL); + } while ((usbctrl & LPC_CLKPWR_USB_CTRL_PLL_LOCK) == 0); + + usbctrl = lpc_pwr_read(dev, LPC_CLKPWR_USB_CTRL); + usbctrl |= LPC_CLKPWR_USB_CTRL_CLK_EN2; + lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, usbctrl); +} + +static void lpc_usb_module_disable(device_t dev, struct ohci_softc *sc) +{ + lpc_otg_write_4(sc, LPC_OTG_CLOCK_CTRL, 0x0); + lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, LPC_CLKPWR_USB_CTRL_BUSKEEPER); +} + +static void lpc_usb_pin_config(device_t dev, struct ohci_softc *sc) +{ +} + +static void lpc_usb_host_clock_enable(device_t dev, struct ohci_softc *sc) +{ + uint32_t usbctrl; + + usbctrl = lpc_pwr_read(dev, LPC_CLKPWR_USB_CTRL); + usbctrl |= LPC_CLKPWR_USB_CTRL_HOST_NEED_CLK_EN; + lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, usbctrl); +} + +static void lpc_otg_status_and_control(device_t dev, struct ohci_softc *sc) +{ + lpc_otg_write_4(sc, LPC_OTG_STATUS, 0x1); +} + +static rtems_interval lpc_usb_timeout_init(void) +{ + return rtems_clock_get_ticks_since_boot(); +} + +static bool lpc_usb_timeout_not_expired(rtems_interval start) +{ + rtems_interval elapsed = rtems_clock_get_ticks_since_boot() - start; + + return elapsed < (rtems_clock_get_ticks_per_second() / 10); +} + +static int lpc_otg_clk_ctrl(device_t dev, struct ohci_softc *sc, uint32_t otg_clk_ctrl) +{ + rtems_interval start; + bool not_ok; + + lpc_otg_write_4(sc, LPC_OTG_CLOCK_CTRL, otg_clk_ctrl); + + start = lpc_usb_timeout_init(); + while ( + (not_ok = (lpc_otg_read_4(sc, LPC_OTG_CLOCK_STATUS) & otg_clk_ctrl) != otg_clk_ctrl) + && lpc_usb_timeout_not_expired(start) + ) { + /* Wait */ + } + + return not_ok ? EIO : 0; +} + +static int lpc_otg_i2c_wait_for_receive_fifo_not_empty(struct ohci_softc *sc) +{ + rtems_interval start; + bool not_ok; + + start = lpc_usb_timeout_init(); + while ( + (not_ok = (lpc_otg_read_4(sc, LPC_OTG_I2C_STATUS) & LPC_OTG_I2C_STATUS_RFE) != 0) + && lpc_usb_timeout_not_expired(start) + ) { + /* Wait */ + } + + return not_ok ? EIO : 0; +} + +static int lpc_otg_i2c_wait_for_transaction_done(struct ohci_softc *sc) +{ + rtems_interval start; + bool not_ok; + + start = lpc_usb_timeout_init(); + while ( + (not_ok = (lpc_otg_read_4(sc, LPC_OTG_I2C_STATUS) & LPC_OTG_I2C_STATUS_TDI) == 0) + && lpc_usb_timeout_not_expired(start) + ) { + /* Wait */ + } + + return not_ok ? EIO : 0; +} + +static int lpc_otg_i2c_read(const struct usb_otg_transceiver *self, uint8_t reg_addr, uint8_t *value) +{ + struct ohci_softc *sc = (struct ohci_softc *)self->softc; + int eno; + + lpc_otg_write_4(sc, LPC_OTG_I2C_CTRL, LPC_OTG_I2C_CTRL_SRST); + lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, self->i2c_addr | I2C_START_BIT); + lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, reg_addr); + lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, self->i2c_addr | I2C_START_BIT | I2C_READ); + lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, I2C_STOP_BIT); + + eno = lpc_otg_i2c_wait_for_receive_fifo_not_empty(sc); + + if (eno == 0) { + *value = (uint8_t)lpc_otg_read_4(sc, LPC_OTG_I2C_TXRX); + } + + return eno; +} + +static int lpc_otg_i2c_write(const struct usb_otg_transceiver *self, uint8_t reg_addr, uint8_t value) +{ + struct ohci_softc *sc = (struct ohci_softc *)self->softc; + int eno; + + lpc_otg_write_4(sc, LPC_OTG_I2C_CTRL, LPC_OTG_I2C_CTRL_SRST); + lpc_otg_write_4(sc, LPC_OTG_I2C_STATUS, LPC_OTG_I2C_STATUS_TDI); + lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, self->i2c_addr | I2C_START_BIT); + lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, reg_addr); + lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, value | I2C_STOP_BIT); + + eno = lpc_otg_i2c_wait_for_transaction_done(sc); + + return eno; +} + +static int ohci_lpc_otg_transceiver_suspend(device_t dev, struct ohci_softc *sc) +{ + int eno = 0; + +#ifdef BSP_USB_OTG_TRANSCEIVER_I2C_ADDR + if (eno == 0) { + eno = lpc_otg_clk_ctrl( dev, sc, + LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_HOST_EN | LPC_OTG_CLOCK_CTRL_I2C_EN + ); + } + + if (eno == 0) { + eno = usb_otg_transceiver_suspend(&sc->sc_otg_trans); + } + +#ifdef BSP_USB_OTG_TRANSCEIVER_DUMP + usb_otg_transceiver_dump(&sc->sc_otg_trans); +#endif /* BSP_USB_OTG_TRANSCEIVER_DUMP */ + + if (eno == 0) { + eno = lpc_otg_clk_ctrl(dev, sc, LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_HOST_EN); + } +#endif /* BSP_USB_OTG_TRANSCEIVER_I2C_ADDR */ + + return eno; +} + +static int +lpc_ohci_resume(device_t dev) +{ + struct ohci_softc *sc = device_get_softc(dev); + int eno = 0; + +#ifdef BSP_USB_OTG_TRANSCEIVER_I2C_ADDR + if (eno == 0) { + eno = lpc_otg_clk_ctrl( dev, sc, + LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_HOST_EN | LPC_OTG_CLOCK_CTRL_I2C_EN + ); + } + + if (eno == 0) { + eno = usb_otg_transceiver_resume(&sc->sc_otg_trans); + } + +#ifdef BSP_USB_OTG_TRANSCEIVER_VBUS + if (eno == 0) { + eno = usb_otg_transceiver_set_vbus( + &sc->sc_otg_trans, + BSP_USB_OTG_TRANSCEIVER_VBUS + ); + } +#endif /* BSP_USB_OTG_TRANSCEIVER_VBUS */ + +#ifdef BSP_USB_OTG_TRANSCEIVER_DUMP + usb_otg_transceiver_dump(&sc->sc_otg_trans); +#endif /* BSP_USB_OTG_TRANSCEIVER_DUMP */ + + if (eno == 0) { + eno = lpc_otg_clk_ctrl(dev, sc, LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_HOST_EN); + } +#endif /* BSP_USB_OTG_TRANSCEIVER_I2C_ADDR */ + + if (eno == 0) { + eno = bus_generic_resume(dev); + } + + return (eno); +} + +static device_method_t lpc_ohci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, lpc_ohci_probe), + DEVMETHOD(device_attach, lpc_ohci_attach), + DEVMETHOD(device_detach, lpc_ohci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, lpc_ohci_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + { 0, 0 } +}; + +static driver_t lpc_ohci_driver = { + "ohci", + lpc_ohci_methods, + sizeof(struct ohci_softc), +}; + +static devclass_t lpc_ohci_devclass; + +DRIVER_MODULE(ohci, nexus, lpc_ohci_driver, lpc_ohci_devclass, 0, 0); +MODULE_DEPEND(ohci, usb, 1, 1, 1); + +#endif /* defined(LIBBSP_ARM_LPC32XX_BSP_H) */ diff --git a/rtemsbsd/sys/dev/usb/usb_otg_transceiver.h b/rtemsbsd/sys/dev/usb/usb_otg_transceiver.h old mode 100644 new mode 100755 index 1e6b738d..0ed7c7b1 --- a/rtemsbsd/sys/dev/usb/usb_otg_transceiver.h +++ b/rtemsbsd/sys/dev/usb/usb_otg_transceiver.h @@ -88,6 +88,7 @@ struct usb_otg_transceiver { uint16_t vendor_id; uint16_t product_id; uint8_t i2c_addr; + void *softc; }; int usb_otg_transceiver_read( diff --git a/testsuite/include/rtems/bsd/test/network-config.h.in b/testsuite/include/rtems/bsd/test/network-config.h.in old mode 100644 new mode 100755 index c652e74c..c20a735c --- a/testsuite/include/rtems/bsd/test/network-config.h.in +++ b/testsuite/include/rtems/bsd/test/network-config.h.in @@ -42,6 +42,8 @@ #define NET_CFG_INTERFACE_0 "cgem0" #elif defined(LIBBSP_M68K_GENMCF548X_BSP_H) #define NET_CFG_INTERFACE_0 "fec0" +#elif defined(LIBBSP_ARM_LPC32XX_BSP_H) + #define NET_CFG_INTERFACE_0 "lpe0" #else #define NET_CFG_INTERFACE_0 "lo0" #endif -- cgit v1.2.3