int exiic_wait_state(struct exiic_softc *sc, uint32_t reg, uint32_t mask, uint32_t value) { uint32_t state; int timeout; state = HREAD4(sc, reg); for (timeout = 1000; timeout > 0; timeout--) { if (((state = HREAD4(sc, reg)) & mask) == value) return 0; delay(1000); } return ETIMEDOUT; }
static void pxaohci_disable(struct pxaohci_softc *sc) { uint32_t hr; /* Full host reset */ hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) | USBHC_HR_FHR); DELAY(USBHC_RST_WAIT); hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR)); }
static void obioohci_disable(struct obioohci_softc *sc) { #ifdef NOTYET uint32_t hr; /* Full host reset */ hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) | USBHC_HR_FHR); DELAY(USBHC_RST_WAIT); hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR)); #endif }
static void pxaohci_enable(struct pxaohci_softc *sc) { uint32_t hr; /* Full host reset */ hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) | USBHC_HR_FHR); DELAY(USBHC_RST_WAIT); hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR)); /* Force system bus interface reset */ hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) | USBHC_HR_FSBIR); while (HREAD4(sc, USBHC_HR) & USBHC_HR_FSBIR) DELAY(3); /* Enable the ports (physically only one, only enable that one?) */ hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSE)); hr = HREAD4(sc, USBHC_HR); HWRITE4(sc, USBHC_HR, (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSEP1 | USBHC_HR_SSEP2 | USBHC_HR_SSEP3)); HWRITE4(sc, USBHC_HIE, USBHC_HIE_RWIE | USBHC_HIE_UPRIE); hr = HREAD4(sc, USBHC_UHCRHDA); }
int exiic_xfer_wait(struct exiic_softc *sc) { if (!exiic_wait_state(sc, I2C_CON, I2C_CON_INTPENDING, I2C_CON_INTPENDING)) return (HREAD4(sc, I2C_STAT) & I2C_STAT_LAST_RVCD_BIT) ? I2C_NACK : I2C_ACK; else return I2C_TIMEOUT; }
void imxenet_stop(struct imxenet_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; /* Tell the stack that the interface is no longer active */ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ifp->if_timer = 0; /* reset the controller */ HSET4(sc, ENET_ECR, ENET_ECR_RESET); while(HREAD4(sc, ENET_ECR) & ENET_ECR_RESET); }
void imxenet_miibus_writereg(struct device *dev, int phy, int reg, int val) { struct imxenet_softc *sc = (struct imxenet_softc *)dev; HSET4(sc, ENET_EIR, ENET_EIR_MII); bus_space_write_4(sc->sc_iot, sc->sc_ioh, ENET_MMFR, ENET_MMFR_ST | ENET_MMFR_OP_WR | ENET_MMFR_TA | phy << ENET_MMFR_PA_SHIFT | reg << ENET_MMFR_RA_SHIFT | (val & 0xffff)); while(!(HREAD4(sc, ENET_EIR) & ENET_EIR_MII)); return; }
/* * MII * Interrupts need ENET_ECR_ETHEREN to be set, * so we just read the interrupt status registers. */ int imxenet_miibus_readreg(struct device *dev, int phy, int reg) { int r = 0; struct imxenet_softc *sc = (struct imxenet_softc *)dev; HSET4(sc, ENET_EIR, ENET_EIR_MII); bus_space_write_4(sc->sc_iot, sc->sc_ioh, ENET_MMFR, ENET_MMFR_ST | ENET_MMFR_OP_RD | ENET_MMFR_TA | phy << ENET_MMFR_PA_SHIFT | reg << ENET_MMFR_RA_SHIFT); while(!(HREAD4(sc, ENET_EIR) & ENET_EIR_MII)); r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ENET_MMFR); return (r & 0xffff); }
void imxenet_miibus_statchg(struct device *dev) { struct imxenet_softc *sc = (struct imxenet_softc *)dev; int ecr; ecr = HREAD4(sc, ENET_ECR); switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) { case IFM_1000_T: /* Gigabit */ ecr |= ENET_ECR_SPEED; break; default: ecr &= ~ENET_ECR_SPEED; break; } HWRITE4(sc, ENET_ECR, ecr); return; }
int exiic_intr(void *arg) { struct exiic_softc *sc = arg; u_int16_t status; int rc = 0; status = HREAD4(sc, I2C_CON); if (ISSET(status, I2C_CON_INTPENDING)) { /* we do not acknowledge the interrupt here */ rc = 1; sc->intr_status |= status; wakeup(&sc->intr_status); } return (rc); }
void bcmpm_wdog_set(struct bcmpm_softc *sc, uint32_t period) { uint32_t rstc, wdog; if (period == 0) { HWRITE4(sc, PM_RSTC, PM_RSTC_RESET | PM_PASSWORD); return; } rstc = HREAD4(sc, PM_RSTC) & PM_RSTC_CONFIGMASK; rstc |= PM_RSTC_FULL_RESET; rstc |= PM_PASSWORD; wdog = period & PM_WDOG_TIMEMASK; wdog |= PM_PASSWORD; HWRITE4(sc, PM_RSTC, wdog); HWRITE4(sc, PM_RSTC, rstc); }
/* * Established by attachment driver at interrupt priority IPL_NET. */ int imxenet_intr(void *arg) { struct imxenet_softc *sc = arg; struct ifnet *ifp = &sc->sc_ac.ac_if; u_int32_t status; /* Find out which interrupts are pending. */ status = HREAD4(sc, ENET_EIR); /* Acknowledge the interrupts we are about to handle. */ HWRITE4(sc, ENET_EIR, status); /* * Wake up the blocking process to service command * related interrupt(s). */ if (ISSET(status, ENET_EIR_MII)) { sc->intr_status |= status; wakeup(&sc->intr_status); } /* * Handle incoming packets. */ if (ISSET(status, ENET_EIR_RXF)) { if (ifp->if_flags & IFF_RUNNING) imxenet_recv(sc); } /* Try to transmit. */ if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd)) imxenet_start(ifp); return 1; }
void imxenet_init(struct imxenet_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; int speed = 0; uint32_t rate = clk_get_rate(clk_get("enet_ref")); /* reset the controller */ HWRITE4(sc, ENET_ECR, ENET_ECR_RESET); while(HREAD4(sc, ENET_ECR) & ENET_ECR_RESET); /* set hw address */ HWRITE4(sc, ENET_PALR, (sc->sc_ac.ac_enaddr[0] << 24) | (sc->sc_ac.ac_enaddr[1] << 16) | (sc->sc_ac.ac_enaddr[2] << 8) | sc->sc_ac.ac_enaddr[3]); HWRITE4(sc, ENET_PAUR, (sc->sc_ac.ac_enaddr[4] << 24) | (sc->sc_ac.ac_enaddr[5] << 16)); /* clear outstanding interrupts */ HWRITE4(sc, ENET_EIR, 0xffffffff); /* set address filter */ HWRITE4(sc, ENET_GAUR, 0); HWRITE4(sc, ENET_GALR, 0); /* set max receive buffer size, 3-0 bits always zero for alignment */ HWRITE4(sc, ENET_MRBR, ENET_MAX_PKT_SIZE); /* init descriptor */ imxenet_init_txd(sc); imxenet_init_rxd(sc); /* set descriptor */ HWRITE4(sc, ENET_TDSR, sc->txdma.dma_paddr); HWRITE4(sc, ENET_RDSR, sc->rxdma.dma_paddr); /* set it to full-duplex */ HWRITE4(sc, ENET_TCR, ENET_TCR_FDEN); /* * Set max frame length to 1518 or 1522 with VLANs, * pause frames and promisc mode. * XXX: RGMII mode - phy dependant */ HWRITE4(sc, ENET_RCR, ENET_RCR_MAX_FL(1522) | ENET_RCR_RGMII_MODE | ENET_RCR_MII_MODE | ENET_RCR_FCE); bus_space_write_4(sc->sc_iot, sc->sc_ioh, ENET_MSCR, (((rate + (ENET_MII_CLK << 2) - 1) / (ENET_MII_CLK << 2)) << 1) | 0x100); /* RX FIFO treshold and pause */ HWRITE4(sc, ENET_RSEM, 0x84); HWRITE4(sc, ENET_RSFL, 16); HWRITE4(sc, ENET_RAEM, 8); HWRITE4(sc, ENET_RAFL, 8); HWRITE4(sc, ENET_OPD, 0xFFF0); /* do store and forward, only i.MX6, needs to be set correctly else */ HWRITE4(sc, ENET_TFWR, ENET_TFWR_STRFWD); /* enable gigabit-ethernet and set it to support little-endian */ switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) { case IFM_1000_T: /* Gigabit */ speed |= ENET_ECR_SPEED; break; default: speed &= ~ENET_ECR_SPEED; break; } HWRITE4(sc, ENET_ECR, ENET_ECR_ETHEREN | speed | ENET_ECR_DBSWP); #ifdef ENET_ENHANCED_BD HSET4(sc, ENET_ECR, ENET_ECR_EN1588); #endif /* rx descriptors are ready */ HWRITE4(sc, ENET_RDAR, ENET_RDAR_RDAR); /* Indicate we are up and running. */ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; /* enable interrupts for tx/rx */ HWRITE4(sc, ENET_EIMR, ENET_EIR_TXF | ENET_EIR_RXF); HWRITE4(sc, ENET_EIMR, 0xffffffff); imxenet_start(ifp); }
void imxenet_attach(struct device *parent, struct device *self, void *args) { struct armv7_attach_args *aa = args; struct imxenet_softc *sc = (struct imxenet_softc *) self; struct mii_data *mii; struct ifnet *ifp; int tsize, rsize, tbsize, rbsize, s; sc->sc_iot = aa->aa_iot; if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) panic("imxenet_attach: bus_space_map failed!"); sc->sc_dma_tag = aa->aa_dmat; /* power it up */ clk_enable(clk_get("enet_ref")); clk_enable(clk_get("enet")); switch (board_id) { case BOARD_ID_IMX6_HUMMINGBOARD: imxgpio_set_dir(ENET_HUMMINGBOARD_PHY_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(ENET_HUMMINGBOARD_PHY_RST); delay(10); break; case BOARD_ID_IMX6_SABRELITE: /* SABRE Lite PHY reset */ imxgpio_set_dir(ENET_SABRELITE_PHY_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(ENET_SABRELITE_PHY_RST); delay(10); break; case BOARD_ID_IMX6_UDOO: // UDOO PHY reset imxgpio_set_dir(ENET_UDOO_PHY_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(ENET_UDOO_PHY_RST); delay(10); break; } /* reset the controller */ HWRITE4(sc, ENET_ECR, ENET_ECR_RESET); while(HREAD4(sc, ENET_ECR) & ENET_ECR_RESET); HWRITE4(sc, ENET_EIMR, 0); HWRITE4(sc, ENET_EIR, 0xffffffff); sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_NET, imxenet_intr, sc, sc->sc_dev.dv_xname); tsize = ENET_MAX_TXD * sizeof(struct imxenet_buf_desc); tsize = ENET_ROUNDUP(tsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, tsize, &sc->txdma)) { printf("%s: Unable to allocate tx_desc memory\n", sc->sc_dev.dv_xname); goto bad; } sc->tx_desc_base = (struct imxenet_buf_desc *)sc->txdma.dma_vaddr; rsize = ENET_MAX_RXD * sizeof(struct imxenet_buf_desc); rsize = ENET_ROUNDUP(rsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, rsize, &sc->rxdma)) { printf("%s: Unable to allocate rx_desc memory\n", sc->sc_dev.dv_xname); goto txdma; } sc->rx_desc_base = (struct imxenet_buf_desc *)sc->rxdma.dma_vaddr; tbsize = ENET_MAX_TXD * ENET_MAX_PKT_SIZE; tbsize = ENET_ROUNDUP(tbsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, tbsize, &sc->tbdma)) { printf("%s: Unable to allocate tx_buffer memory\n", sc->sc_dev.dv_xname); goto rxdma; } sc->tx_buffer_base = (struct imxenet_buffer *)sc->tbdma.dma_vaddr; rbsize = ENET_MAX_RXD * ENET_MAX_PKT_SIZE; rbsize = ENET_ROUNDUP(rbsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, rbsize, &sc->rbdma)) { printf("%s: Unable to allocate rx_buffer memory\n", sc->sc_dev.dv_xname); goto tbdma; } sc->rx_buffer_base = (struct imxenet_buffer *)sc->rbdma.dma_vaddr; sc->cur_tx = 0; sc->cur_rx = 0; printf("\n"); s = splnet(); ifp = &sc->sc_ac.ac_if; ifp->if_softc = sc; strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = imxenet_ioctl; ifp->if_start = imxenet_start; ifp->if_capabilities = IFCAP_VLAN_MTU; memset(sc->sc_ac.ac_enaddr, 0xff, ETHER_ADDR_LEN); imxocotp_get_ethernet_address(sc->sc_ac.ac_enaddr); printf("%s: address %s\n", sc->sc_dev.dv_xname, ether_sprintf(sc->sc_ac.ac_enaddr)); /* initialize the chip */ imxenet_chip_init(sc); IFQ_SET_READY(&ifp->if_snd); /* Initialize MII/media info. */ mii = &sc->sc_mii; mii->mii_ifp = ifp; mii->mii_readreg = imxenet_miibus_readreg; mii->mii_writereg = imxenet_miibus_writereg; mii->mii_statchg = imxenet_miibus_statchg; mii->mii_flags = MIIF_AUTOTSLEEP; ifmedia_init(&mii->mii_media, 0, imxenet_ifmedia_upd, imxenet_ifmedia_sts); mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&mii->mii_phys) == NULL) { ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); } else ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); splx(s); imxenet_sc = sc; return; tbdma: imxenet_dma_free(sc, &sc->tbdma); rxdma: imxenet_dma_free(sc, &sc->rxdma); txdma: imxenet_dma_free(sc, &sc->txdma); bad: bus_space_unmap(sc->sc_iot, sc->sc_ioh, aa->aa_dev->mem[0].size); }
int exiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t _addr, const void *cmdbuf, size_t cmdlen, void *databuf, size_t datalen, int flags) { struct exiic_softc *sc = cookie; uint32_t ret = 0; u_int8_t addr = 0; int i = 0; addr = (_addr & 0x7f) << 1; /* clock gating */ //exccm_enable_i2c(sc->unit); if (exiic_wait_state(sc, I2C_STAT, I2C_STAT_BUSY_SIGNAL, 0)) { printf("%s: busy\n", __func__); return (EIO); } /* acknowledge generation */ HSET4(sc, I2C_CON, I2C_CON_ACK); /* Send the slave-address */ HWRITE4(sc, I2C_DS, addr); if (!I2C_OP_READ_P(op) || (cmdbuf && cmdlen)) HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_TX | I2C_STAT_SERIAL_OUTPUT | I2C_STAT_BUSY_SIGNAL); else HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX | I2C_STAT_SERIAL_OUTPUT | I2C_STAT_BUSY_SIGNAL); ret = exiic_xfer_wait(sc); if (ret != I2C_ACK) goto fail; /* transmit commands */ if (cmdbuf && cmdlen) { for (i = 0; i < cmdlen; i++) { HWRITE4(sc, I2C_DS, ((uint8_t *)cmdbuf)[i]); exiic_xfer_start(sc); ret = exiic_xfer_wait(sc); if (ret != I2C_ACK) goto fail; } } if (I2C_OP_READ_P(op)) { if (cmdbuf && cmdlen) { /* write slave chip address again for actual read */ HWRITE4(sc, I2C_DS, addr); /* restart */ HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX | I2C_STAT_SERIAL_OUTPUT | I2C_STAT_BUSY_SIGNAL); exiic_xfer_start(sc); ret = exiic_xfer_wait(sc); if (ret != I2C_ACK) goto fail; } for (i = 0; i < datalen && ret == I2C_ACK; i++) { /* disable ACK for final read */ if (i == datalen - 1) HCLR4(sc, I2C_CON, I2C_CON_ACK); exiic_xfer_start(sc); ret = exiic_xfer_wait(sc); ((uint8_t *)databuf)[i] = HREAD4(sc, I2C_DS); } if (ret == I2C_NACK) ret = I2C_ACK; /* Normal terminated read. */ } else { for (i = 0; i < datalen && ret == I2C_ACK; i++) { HWRITE4(sc, I2C_DS, ((uint8_t *)databuf)[i]); exiic_xfer_start(sc); ret = exiic_xfer_wait(sc); } } fail: /* send STOP */ if (op & I2C_OP_READ_WITH_STOP) { HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX | I2C_STAT_SERIAL_OUTPUT); exiic_xfer_start(sc); } return ret; }