int nanospin(const struct timespec *rqtp) { if(rqtp->tv_sec > 0) { return E2BIG; } return nanospin_ns(rqtp->tv_nsec); }
static int _hsmci_wait_stat (SIM_HBA *hba, mmc_cmd_t *cmd) { SIM_MMC_EXT *ext; hsmci_ext_t *hsmci; uintptr_t base; uint32_t mask = CMDRDY; ext = (SIM_MMC_EXT *)hba->ext; hsmci = (hsmci_ext_t *)ext->handle; base = hsmci->base; if (cmd->eflags & MMC_CMD_DATA) { mask |= NOTBUSY | XFRDONE; } int timeout = TIMEOUT_LOOPS/100; while (((READ32(MCI_SR) & mask) != mask) && timeout--) nanospin_ns(100); if (timeout <= 0) { slogf (_SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: timeout on waiting for MCI_SR: 0x%x for CMD%d, mask: 0x%x", READ32(MCI_SR), cmd->opcode, mask); return MMC_FAILURE; } return MMC_SUCCESS; }
static void seromap_enable(DEV_OMAP *dev, int enable) { uintptr_t *port = dev->port; write_omap(port[OMAP_UART_LCR], 0x80); if (!enable) { atomic_set(&dev->pwm_flag, SEROMAP_PWM_PAGED); // If HW flow control is ON, assert the RTS line if (dev->tty.c_cflag & IHFLOW) set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR|OMAP_MCR_RTS, 0); while (!(read_omap(port[OMAP_UART_LSR]) & OMAP_LSR_TSRE)) ; nanospin_ns(1000000); // pause for 1ms write_omap(port[OMAP_UART_MDR1], 0x07); write_omap(port[OMAP_UART_DLL], 0xFF); write_omap(port[OMAP_UART_DLH], 0xFF); } else { write_omap(port[OMAP_UART_DLL], dev->brd); write_omap(port[OMAP_UART_DLH], (dev->brd >> 8) & 0xff); write_omap(port[OMAP_UART_MDR1], 0x00); // If HW flow control is ON, de-assert the RTS line if(dev->tty.c_cflag & IHFLOW) set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR|OMAP_MCR_RTS, OMAP_MCR_DTR|OMAP_MCR_RTS); // Allow data transmission to resume atomic_clr(&dev->pwm_flag, SEROMAP_PWM_PAGED); } write_omap(port[OMAP_UART_LCR], dev->lcr); }
static int omap_pio_done( SIM_HBA *hba, char *buf, int len, int dir ) { SIM_MMC_EXT *ext; omap_ext_t *oext; uintptr_t base; int cnt; int nbytes; uint32_t *pbuf; ext = (SIM_MMC_EXT *)hba->ext; oext = (omap_ext_t *)ext->handle; base = oext->mmc_base; pbuf = (uint32_t *)buf; cnt = nbytes = len < MMCHS_FIFO_SIZE ? len : MMCHS_FIFO_SIZE; if( dir == MMC_DIR_IN ) { if( !( in32( base + OMAP_MMCHS_PSTATE ) & PSTATE_BRE ) ) { out32( base + OMAP_MMCHS_IE, INTR_BRR ); return( 0 ); } for( ; nbytes > 0; nbytes -= 4 ) { *pbuf++ = in32( base + OMAP_MMCHS_DATA ); } if( len < MMCHS_FIFO_SIZE ) { int cnt; for( cnt = 2000; cnt; cnt-- ) { if( !( in32( base + OMAP_MMCHS_PSTATE ) & PSTATE_RTA ) ) { break; } nanospin_ns( 1000 ); } } } else { if( !( in32( base + OMAP_MMCHS_PSTATE ) & PSTATE_BWE ) ) { out32( base + OMAP_MMCHS_IE, INTR_BWR ); return( 0 ); } for( ; nbytes > 0; nbytes -= 4 ) { out32( base + OMAP_MMCHS_DATA, *pbuf++ ); } if( len == cnt ) { out32( base + OMAP_MMCHS_IE, INTR_TC ); } } return( cnt ); }
static int mpc5125_set_clock (mpc5125_ext_t *ext, int divisor) { mpc5125_mmc_reg *mmc = (mpc5125_mmc_reg *) ext->mmc_base; int to; if (mmc->sd_status & 0x100) { mmc->sd_str_stp_clk = 1; for (to = MPC5125_MMC_TMOUT; to > 0; to--) { if ((mmc->sd_status & 0x100) == 0) break; nanospin_ns(100);; } if (to == 0) { slogf (_SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: mpc5125_set_clock(): timeout to get SD clock stopped"); return -1; } } if (divisor < 8) { divisor = 0x80; } mmc->sd_clk_rate = divisor; mmc->sd_str_stp_clk = 2; for (to = MPC5125_MMC_TMOUT; to > 0; to--) { if (mmc->sd_status & 0x100) { return (MMC_SUCCESS); } nanospin_ns(100);; } return (-1); }
int nand_wait_busy(struct chipio *cio, uint32_t usec) { /* * Wait for NAND * Wait pins start at bit 8 of GPMC status register * WAITxSTATUS Is a copy of input pin WAITx. (Reset value is WAITx input R xpin sampled at IC reset) * 0x0: WAITx asserted (inactive state) * 0x1: WAITx de-asserted */ while (usec--){ if(OMAP_READ_GPMC_STATUS() & (OMAP_GPMC_WAITPIN0<<cio->wp)) return 0; else nanospin_ns(1000); } return (-1); }
int esdhc_prsstat( SIM_HBA *hba, uint32_t value, uint32_t mask, uint32_t timeo ) { SIM_MMC_EXT *ext; esdhc_ext_t *esdhc; uintptr_t base; uint32_t prsstat; ext = (SIM_MMC_EXT *)hba->ext; esdhc = (esdhc_ext_t *)ext->handle; base = esdhc->base; for( ; timeo && ( ( prsstat = in32( base + ESDHC_PRSSTAT ) ) & mask ) != value; timeo-- ) { nanospin_ns( 100 ); } return( timeo ? MMC_SUCCESS : MMC_FAILURE ); }
int omap_waitmask( SIM_HBA *hba, uint32_t reg, uint32_t mask, uint32_t val, uint32_t usec ) { SIM_MMC_EXT *ext; omap_ext_t *oext; uintptr_t base; uint32_t cnt; int stat; int rval; uint32_t iter; ext = (SIM_MMC_EXT *)hba->ext; oext = (omap_ext_t *)ext->handle; base = oext->mmc_base; stat = MMC_FAILURE; rval = MMC_SUCCESS; // fast poll for 1ms - 1us intervals for( cnt = min( usec, 1000 ); cnt; cnt-- ) { if( ( ( rval = in32( base + reg ) ) & mask ) == val ) { stat = MMC_SUCCESS; break; } nanospin_ns( 1000L ); } if( usec > 1000 && stat ) { iter = usec / 1000L; for( cnt = iter; cnt; cnt-- ) { if( ( ( rval = in32( base + reg ) ) & mask ) == val ) { stat = MMC_SUCCESS; break; } delay( 1 ); } } #ifdef OMAP_DEBUG if( !cnt ) { mmc_slogf( hba, _SLOGC_SIM_MMC, _SLOG_ERROR, 3, "%s: reg %x, mask %x, val %x, rval %x", __FUNCTION__, reg, mask, val, in32( base + reg ) ); } #endif return( stat ); }
static int omap3_interrupt(SIM_HBA *hba, int irq, int resp_type, uint32_t *resp) { SIM_MMC_EXT *ext; omap3_ext_t *omap3; uint32_t sts; int intr = 0; uintptr_t base; ext = (SIM_MMC_EXT *)hba->ext; omap3 = (omap3_ext_t *)ext->handle; base = omap3->mmc_base; sts = in32(base + OMAP3_MMCHS_STAT); sts &= in32(base + OMAP3_MMCHS_IE) | INTR_ERRI; out32(base + OMAP3_MMCHS_STAT, sts); if (sts & INTR_ERRI) { // Any errors ? slogf(_SLOGC_SIM_MMC, _SLOG_ERROR, "OMAP3 interrupt error = %x", sts); intr |= MMC_INTR_ERROR | MMC_INTR_COMMAND; if (sts & INTR_DTO) { intr |= MMC_ERR_DATA_TO; out32(base + OMAP3_MMCHS_SYSCTL, in32(base + OMAP3_MMCHS_SYSCTL) | SYSCTL_SRD); while (in32(base + OMAP3_MMCHS_SYSCTL) & SYSCTL_SRD); } if (sts & INTR_DCRC) intr |= MMC_ERR_DATA_CRC; if (sts & INTR_DEB) intr |= MMC_ERR_DATA_END; if (sts & INTR_CTO) { intr |= MMC_ERR_CMD_TO; out32(base + OMAP3_MMCHS_SYSCTL, in32(base + OMAP3_MMCHS_SYSCTL) | SYSCTL_SRC); while (in32(base + OMAP3_MMCHS_SYSCTL) & SYSCTL_SRC); } if (sts & INTR_CCRC) intr |= MMC_ERR_CMD_CRC; if (sts & INTR_CEB) intr |= MMC_ERR_CMD_END; if (sts & INTR_CIE) intr |= MMC_ERR_CMD_IDX; } else { if (sts & INTR_CC) { intr |= MMC_INTR_COMMAND; if (resp) { if (resp_type & MMC_RSP_136) { resp[3] = in32(base + OMAP3_MMCHS_RSP76); resp[2] = in32(base + OMAP3_MMCHS_RSP54); resp[1] = in32(base + OMAP3_MMCHS_RSP32); resp[0] = in32(base + OMAP3_MMCHS_RSP10); } else if (resp_type & MMC_RSP_PRESENT) resp[0] = in32(base + OMAP3_MMCHS_RSP10); } // Busy check? if (resp_type & MMC_RSP_BUSY) { int i; for (i = 1024 * 256; i > 0; i--) { if (in32(base + OMAP3_MMCHS_PSTATE) & PSTATE_DLA) { nanospin_ns(1024); continue; } break; } if (i <= 0) { intr |= MMC_ERR_CMD_TO | MMC_INTR_ERROR; slogf(_SLOGC_SIM_MMC, _SLOG_ERROR, "OMAP3 busy check time out"); } } } if (sts & (INTR_TC | INTR_BWR | INTR_BRR)) { if (sts & INTR_TC) intr |= MMC_INTR_DATA; if (sts & INTR_BRR) intr |= MMC_INTR_RBRDY; if (sts & INTR_BWR) intr |= MMC_INTR_WBRDY; } } if (intr) out32(base + OMAP3_MMCHS_IE, 0); return intr; }
DEV_OMAP * create_device(TTYINIT_OMAP *dip, unsigned unit, unsigned maxim_xcvr_kick) { DEV_OMAP *dev; unsigned i; uintptr_t port; unsigned char msr; unsigned char tlr = 0, tcr = 0; #ifdef PWR_MAN clk_enable_t clk_cfg = clk_enable_none; #endif // Get a device entry and the input/output buffers for it. if ((dev = malloc(sizeof(*dev))) == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of device entry failed (%d)", errno); return (dev); } memset(dev, 0, sizeof(*dev)); // Get buffers. dev->tty.ibuf.head = dev->tty.ibuf.tail = dev->tty.ibuf.buff = malloc(dev->tty.ibuf.size = dip->tty.isize); if (dev->tty.ibuf.buff == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of input buffer failed (%d)", errno); free(dev); return (NULL); } dev->tty.obuf.head = dev->tty.obuf.tail = dev->tty.obuf.buff = malloc(dev->tty.obuf.size = dip->tty.osize); if (dev->tty.obuf.buff == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of output buffer failed (%d)", errno); free(dev->tty.ibuf.buff); free(dev); return (NULL); } dev->tty.cbuf.head = dev->tty.cbuf.tail = dev->tty.cbuf.buff = malloc(dev->tty.cbuf.size = dip->tty.csize); if (dev->tty.cbuf.buff == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of canonical buffer failed (%d)", errno); free(dev->tty.ibuf.buff); free(dev->tty.obuf.buff); free(dev); return (NULL); } if (dip->tty.highwater) dev->tty.highwater = dip->tty.highwater; else dev->tty.highwater = dev->tty.ibuf.size - (FIFO_SIZE * 2); strcpy(dev->tty.name, dip->tty.name); dev->tty.baud = dip->tty.baud; dev->tty.fifo = dip->tty.fifo; dev->tty.verbose = dip->tty.verbose; port = mmap_device_io(OMAP_UART_SIZE, dip->tty.port); for (i = 0; i < OMAP_UART_SIZE; i += 4) dev->port[i] = port + i; dev->intr = dip->tty.intr; dev->clk = dip->tty.clk; dev->div = dip->tty.div; dev->tty.flags = EDIT_INSERT | LOSES_TX_INTR; dev->tty.c_cflag = dip->tty.c_cflag; dev->tty.c_iflag = dip->tty.c_iflag; dev->tty.c_lflag = dip->tty.c_lflag; dev->tty.c_oflag = dip->tty.c_oflag; dev->tty.lflags = dip->tty.lflags; if (dip->tty.logging_path[0] != NULL) dev->tty.logging_path = strdup(dip->tty.logging_path); #ifdef PWR_MAN dev->physbase = dip->tty.port; if (omap_clock_toggle_init(dev) != EOK) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Fail to initialize clocks for PM!"); free(dev->tty.ibuf.buff); free(dev->tty.obuf.buff); free(dev); return (NULL); } #ifdef WINBT clk_cfg = clk_enable_smart_wkup; if (omap_force_rts_init(dev) != EOK) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Fail to initialize force_rts for PM!"); free(dev->tty.ibuf.buff); free(dev->tty.obuf.buff); free(dev); return (NULL); } #endif omap_clock_enable(dev, clk_cfg); #ifdef WINBT bt_ctrl_init(); #endif #endif /* Set auto_rts mode */ dev->auto_rts_enable = dip->auto_rts_enable; // Do not enable MSR interrupt dev->no_msr_int = dip->no_msr_int; // Initialize termios cc codes to an ANSI terminal. ttc(TTC_INIT_CC, &dev->tty, 0); // Initialize the device's name. // Assume that the basename is set in device name. This will attach // to the path assigned by the unit number/minor number combination unit = SET_NAME_NUMBER(unit) | NUMBER_DEV_FROM_USER; ttc(TTC_INIT_TTYNAME, &dev->tty, unit); // see if we have a maxim rs-232 transceiver that needs to be // kicked after it goes to sleep dev->kick_maxim = maxim_xcvr_kick; // Only setup IRQ handler for non-pcmcia devices. // Pcmcia devices will have this done later when card is inserted. if (dip->tty.port != 0 && dip->tty.intr != _NTO_INTR_SPARE) { #ifdef OMAP5910 /* * Don't change default mode set in the very distant past. Even though * MODE_SELECT should be DISABLE before changing DLH, DLL. */ // enable the UART write_omap(dev->port[OMAP_UART_MDR1], OMAP_MDR1_MODE_16X); #else /* * TRM states: Before initializing or modifying clock parameter controls * (DLH, DLL), MODE_SELECT must be set to 0x7 (DISABLE). Failure to observe * this rule can result in unpredictable module behavior. */ write_omap(dev->port[OMAP_UART_MDR1], OMAP_MDR1_MODE_DISABLE); #endif /* Work around for silicon errata i202 states: */ /* Need a delay = 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) */ nanospin_ns(200); /* Clear FIFOs */ set_port(dev->port[OMAP_UART_FCR], OMAP_FCR_RXCLR | OMAP_FCR_TXCLR, OMAP_FCR_RXCLR | OMAP_FCR_TXCLR); /* Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and TX_FIFO_E bit is 1 */ i = 5; while ((read_omap(dev->port[OMAP_UART_LSR]) & (OMAP_UART_LSR_THRE | OMAP_UART_LSR_DR)) != OMAP_UART_LSR_THRE) { nanospin_ns(200); if (--i == 0) { break; /* No need to do anything drastic if FIFO is still not empty */ } } // enable access to divisor registers write_omap(dev->port[OMAP_UART_LCR], OMAP_LCR_DLAB); write_omap(dev->port[OMAP_UART_DLL], 0); write_omap(dev->port[OMAP_UART_DLH], 0); /* Switch to config mode B to get access to EFR Register */ write_omap(dev->port[OMAP_UART_LCR], 0xBF); /* Enable access to TLR register */ set_port(dev->port[OMAP_UART_EFR], OMAP_EFR_ENHANCED, OMAP_EFR_ENHANCED); /* Switch to operational mode to get acces to MCR register */ write_omap(dev->port[OMAP_UART_LCR], 0x00); /* set MCR bit 6 to enable access to TCR and TLR registers */ set_port(dev->port[OMAP_UART_MCR], OMAP_MCR_TCRTLR, OMAP_MCR_TCRTLR); write_omap(dev->port[OMAP_UART_FCR], OMAP_FCR_ENABLE|OMAP_FCR_RXCLR|OMAP_FCR_TXCLR); tcr = 0x0e; /* set auto-rts assert at 56 bytes, restore at 0 bytes */ if (dev->tty.fifo) { /* Set RX fifo trigger level */ switch (dev->tty.fifo >> 4) { case FIFO_TRIG_8: default: tlr = 0x20; break; case FIFO_TRIG_16: tlr = 0x40; break; case FIFO_TRIG_32: tlr = 0x80; break; case FIFO_TRIG_56: tlr = 0xe0; break; case FIFO_TRIG_60: tlr = 0xf0; tcr = 0x0f; /* Ensure auto-rts trigger is not less the RX trigger */ break; } /* Set TX fifo trigger level */ switch (dev->tty.fifo & 0x0f) { case FIFO_TRIG_8: default: tlr |= 0x02; break; case FIFO_TRIG_16: tlr |= 0x04; break; case FIFO_TRIG_32: tlr |= 0x08; break; case FIFO_TRIG_56: tlr |= 0x0e; break; case FIFO_TRIG_60: tlr |= 0x0f; break; } } write_omap(dev->port[OMAP_UART_TCR], tcr); write_omap(dev->port[OMAP_UART_TLR], tlr); #ifdef PWR_MAN write_omap(dev->port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN); #else write_omap(dev->port[OMAP_UART_SCR], 0x00); #endif /* Switch back to Config mode B to gain access to EFR again */ write_omap(dev->port[OMAP_UART_LCR], 0xBF); /* remove access to TLR register */ set_port(dev->port[OMAP_UART_EFR], OMAP_EFR_ENHANCED, 0); /* Switch to operational mode to get acces to MCR register */ write_omap(dev->port[OMAP_UART_LCR], 0x00); /* clr MCR bit 6 to remove access to TCR and TLR registers */ set_port(dev->port[OMAP_UART_MCR], OMAP_MCR_TCRTLR, 0); ser_stty(dev); ser_attach_intr(dev); }
void *omap3_xfer(void *hdl, uint32_t device, uint8_t *buf, int *len) { omap3_spi_t *dev = hdl; uintptr_t base = dev->vbase; uint32_t id; int i; int timeout, expected; uint32_t reg_value = 0; id = device & SPI_DEV_ID_MASK; if (id >=dev->num_cs) { *len = -1; return buf; } dev->xlen = *len; // Cannot set more than 64KB of data at one time if(dev->xlen>(64 * 1024)) { *len = -1; return buf; } dev->rlen = 0; dev->tlen = min(OMAP3_SPI_FIFOLEN, dev->xlen); dev->pbuf = buf; dev->dlen = ((devlist[id].cfg.mode & SPI_MODE_CHAR_LEN_MASK) + 7) >> 3; // Estimate transfer time in us... The calculated dtime is only used for // the timeout, so it doesn't have to be that accurate. At higher clock // rates, a calcuated dtime of 0 would mess-up the timeout calculation, so // round up to 1 us dev->dtime = dev->dlen * 1000 * 1000 / devlist[id].cfg.clock_rate; if (dev->dtime == 0) dev->dtime = 1; omap3_setup(dev, device); /* force CS */ set_port((base + OMAP3_MCSPI_CH1_CONFIG_OFFSET + 0x14*id),OMAP3_MCSPI_FORCE_MODE_ONE, OMAP3_MCSPI_FORCE_MODE_ONE); /*set FIFO */ set_port((base + OMAP3_MCSPI_CH1_CONFIG_OFFSET + 0x14*id), OMAP3_MCSPI_FFER | OMAP3_MCSPI_FFEW , OMAP3_MCSPI_FFER | OMAP3_MCSPI_FFEW ); out32(base + OMAP3_MCSPI_XFERLEVEL_OFFSET , (dev->xlen<<16) | 0xF<<8 | 0xF); /* set transfer levels :MCBSP_FIFO_THRESHOLD= 16-1*/ /* Configue the SPI control register to enable the corresponding channel of the SPI */ set_port(base + OMAP3_MCSPI_CH1_CTRL_OFFSET+0x14*id, OMAP3_MCSPI_CHANNEL_ENABLE, OMAP3_MCSPI_CHANNEL_ENABLE); // Clear any pending interrupts out32(base + OMAP3_MCSPI_IRQ_STATUS_OFFSET, 0xF ); /* start the data transmit.....this happens by writing data to * the corresponding transmit register. This module has been * designed for Transmit/Recieve Mode. This part will change * according to the design. */ for(i=0; i<dev->tlen; i++){ out32(base + OMAP3_MCSPI_CH1_TX_BUFFER_OFFSET + 0x14*id, dev->pbuf[i]); } /* Enable Interrupts */ out32(base + OMAP3_MCSPI_IRQ_ENABLE_OFFSET, INTR_TYPE_EOWKE + (INTR_TYPE_RX0_FULL << (id * OMAP3_INTERRUPT_BITS_PER_SPI_CHANNEL)) ); /* * Wait for exchange to finish */ if (omap3_wait(dev, dev->xlen * 10)) { fprintf(stderr, "OMAP3 SPI: XFER Timeout!!!\n"); dev->rlen = -1; } // Read the last spi words if(dev->rlen < dev->xlen && dev->rlen != -1) { reg_value = in32(base + OMAP3_MCSPI_CH1_STATUS_OFFSET + (OMAP3_SPI_DEVICE_OFFSET * id)); timeout = 1000; while( timeout-- && ((reg_value & OMAP3_MCSPI_CH_RX_REG_FULL) == 0) ) { nanospin_ns(100); reg_value = in32(base + OMAP3_MCSPI_CH1_STATUS_OFFSET + (OMAP3_SPI_DEVICE_OFFSET * id)); } if(timeout <= 0) { dev->rlen = -1; } else { // last words to read from buffer expected = dev->tlen - dev->rlen; for(i = 0; i < expected; i++) { dev->pbuf[dev->rlen++] = in32(base + OMAP3_MCSPI_CH1_RX_BUFFER_OFFSET + (OMAP3_SPI_DEVICE_OFFSET * id)); } } } //disable interrupts out32(base + OMAP3_MCSPI_IRQ_ENABLE_OFFSET, 0); /*un-force CS */ set_port((base + OMAP3_MCSPI_CH1_CONFIG_OFFSET + 0x14*id),OMAP3_MCSPI_FORCE_MODE_ONE, 0); set_port(base + OMAP3_MCSPI_CH1_CTRL_OFFSET + 0x14*id, OMAP3_MCSPI_CHANNEL_ENABLE, 0); set_port(base + OMAP3_MCSPI_CH1_CONFIG_OFFSET + 0x14*id, OMAP3_MCSPI_FFER|OMAP3_MCSPI_FFEW, 0); out32(base + OMAP3_MCSPI_XFERLEVEL_OFFSET , 0); *len = dev->rlen; return buf; }
void *omap3_init(void *hdl, char *options) { omap3_spi_t *dev; uintptr_t base; int i; uint32_t reg; dev = calloc(1, sizeof(omap3_spi_t)); if (dev == NULL) return NULL; //Set defaults dev->pbase = OMAP3_SPI1_BASE; dev->irq_spi = OMAP3_SPI_SPI1_INTR; dev->clock = OMAP3_SPI_INPUT_CLOCK; dev->channel_num = 1; dev->force = 0; dev->edmapbase = DM816x_EDMA_BASE; dev->irq_edma = 0; /* We use interrupt of receive channel */ dev->edma = 0; dev->num_cs = 1; dev->cs_delay = 0; dev->edma_tx_chid = dev->edma_rx_chid = -1; if (omap3_options(dev, options)) goto fail0; /* * Map in SPI registers */ if ((base = mmap_device_io(OMAP3_SPI_REGLEN, dev->pbase)) == (uintptr_t)MAP_FAILED) goto fail0; dev->vbase = base; /* Reset the SPI interface * and wait for the reset to complete */ set_port(base + OMAP3_MCSPI_SYS_CONFIG, OMAP3_MCSPI_CONFIG_SOFT_RESET, OMAP3_MCSPI_CONFIG_SOFT_RESET); while ( !(in32(base + OMAP3_MCSPI_SYS_CONFIG) & 1)) { nanospin_ns(20); } /*Set Master mode -- single channel mode*/ out32((base + OMAP3_MCSPI_MODCTRL_OFFSET), (in32(base + OMAP3_MCSPI_MODCTRL_OFFSET) & OMAP3_MCSPI_MODCTRL_MASTER_SEL)|OMAP3_MCSPI_MODCTRL_MULTI_CH_SEL); /* * Calculate all device configuration here */ for (i = 0; i < dev->num_cs; i++){ //we have just one device defined in the driver till now.... devctrl[i] = omap3_cfg(dev, &devlist[i].cfg); if(dev->force){ /* if we need to set the default CSx level to other than defaul low, we need to kick it*/ out32((base + OMAP3_MCSPI_CH1_CONFIG_OFFSET + 0x14 * i), devctrl[i]|SPI_COMM_TX_RX <<12); set_port(base + OMAP3_MCSPI_CH1_CTRL_OFFSET+0x14*i, OMAP3_MCSPI_CHANNEL_ENABLE, OMAP3_MCSPI_CHANNEL_ENABLE); /* force CS */ set_port((base + OMAP3_MCSPI_CH1_CONFIG_OFFSET + 0x14*i),OMAP3_MCSPI_FORCE_MODE_ONE, OMAP3_MCSPI_FORCE_MODE_ONE); delay(1); /*un force CS */ set_port((base + OMAP3_MCSPI_CH1_CONFIG_OFFSET + 0x14*i),OMAP3_MCSPI_FORCE_MODE_ONE, 0); set_port(base + OMAP3_MCSPI_CH1_CTRL_OFFSET+0x14*i, OMAP3_MCSPI_CHANNEL_ENABLE, 0); } } /* * Attach SPI interrupt */ if (omap3_attach_intr(dev)) goto fail1; dev->spi.hdl = hdl; /* Clear the appropriate Interrupts if any*/ reg= in32(base + OMAP3_MCSPI_IRQ_STATUS_OFFSET) ; out32((base + OMAP3_MCSPI_IRQ_STATUS_OFFSET), reg); if (dev->edma) { if (omap3_init_edma(dev)) dev->edma=0; /* * Attach SDMA interrupt */ if (omap3_edma_attach_intr(dev)){ printf("%s(%d): omap3_edma_attach_intr failed\n", __func__, __LINE__); goto fail2; } } return dev; fail2: munmap_device_memory ((void *)dev->edmavbase, DM6446_EDMA_SIZE); fail1: munmap_device_io(dev->vbase, OMAP3_SPI_REGLEN); fail0: free(dev); return NULL; }