static int omap2_mcspi_set_rxfifo(const struct spi_device *spi, int buf_size, int enable, int bytes_per_wl ) { u32 l, rw, s; unsigned short revert = 0; struct spi_master *master = spi->master; struct omap2_mcspi *mcspi = spi_master_get_devdata(master); buf_size = buf_size/bytes_per_wl; // l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); l = mcspi_cached_chconf0(spi); s = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); if (enable == 1) { /* FIFO cannot be enabled for both TX and RX * simultaneously */ // if (l & OMAP2_MCSPI_CHCONF_FFET) // return -EPERM; /* Channel needs to be disabled and enabled * for FIFO setting to take affect */ if (s & OMAP2_MCSPI_CHCTRL_EN) { omap2_mcspi_set_enable(spi, 0); revert = 1; } if (buf_size < mcspi->fifo_depth) mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, ((buf_size << 16) | (buf_size - 1) << 8)); else mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, ((buf_size << 16) | //(mcspi->fifo_depth - 1) << 8)); ((mcspi->fifo_depth - 1) << 8) | ((mcspi->fifo_depth - 1) << 0) )); } rw = OMAP2_MCSPI_CHCONF_FFER; MOD_REG_BIT(l, rw, enable); // mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l); mcspi_write_chconf0(spi,l); if (revert) omap2_mcspi_set_enable(spi, 1); return 0; }
static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) { struct spi_master *spi_cntrl = mcspi->master; struct omap2_mcspi_regs *ctx = &mcspi->ctx; struct omap2_mcspi_cs *cs; /* McSPI: context restore */ mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl); mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable); list_for_each_entry(cs, &ctx->cs, node) writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); }
static int omap2_mcspi_set_rxfifo(const struct spi_device *spi, int buf_size, int wl_bytes, int enable) { u32 l, rw, s, xfer_ael; unsigned short revert = 0; struct spi_master *master = spi->master; struct omap2_mcspi *mcspi = spi_master_get_devdata(master); u32 wcnt = buf_size/wl_bytes; l = mcspi_cached_chconf0(spi); s = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); /* Read settings for TX FIFO */ xfer_ael = mcspi_read_reg(master, OMAP2_MCSPI_XFERLEVEL) & 0xff; if (enable == 1) { /* Channel needs to be disabled and enabled * for FIFO setting to take affect */ if (s & OMAP2_MCSPI_CHCTRL_EN) { omap2_mcspi_set_enable(spi, 0); revert = 1; } if (buf_size < mcspi->fifo_depth) mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, ((wcnt << 16) | (buf_size - 1) << 8) | xfer_ael); else mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, ((wcnt << 16) | (mcspi->fifo_depth - 1) << 8) | xfer_ael); } else { /* Reset register value for disable case */ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xfer_ael); } rw = OMAP2_MCSPI_CHCONF_FFER; MOD_REG_BIT(l, rw, enable); mcspi_write_chconf0(spi, l); if (revert) omap2_mcspi_set_enable(spi, 1); return 0; }
static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) { struct spi_master *spi_cntrl; spi_cntrl = mcspi->master; /*McSPI : context restore */ mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl); mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG, mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig); mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_CHCONF0, mcspi_ctx[spi_cntrl->bus_num - 1].chconf0); if (spi_cntrl->bus_num != 4) mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_CHCONF0 + 0x14, mcspi_ctx[spi_cntrl->bus_num - 1].chconf1); }
static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) { struct spi_master *spi_cntrl; struct omap2_mcspi_cs *cs; spi_cntrl = mcspi->master; /* McSPI: context restore */ mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl); mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable); list_for_each_entry(cs, &omap2_mcspi_ctx[spi_cntrl->bus_num - 1].cs, node) __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); }
static void omap2_mcspi_set_fifo(const struct spi_device *spi, struct spi_transfer *t, int enable) { struct spi_master *master = spi->master; struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi *mcspi; unsigned int wcnt; int max_fifo_depth, fifo_depth, bytes_per_word; u32 chconf, xferlevel; mcspi = spi_master_get_devdata(master); chconf = mcspi_cached_chconf0(spi); if (enable) { bytes_per_word = mcspi_bytes_per_word(cs->word_len); if (t->len % bytes_per_word != 0) goto disable_fifo; if (t->rx_buf != NULL && t->tx_buf != NULL) max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2; else max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH; fifo_depth = gcd(t->len, max_fifo_depth); if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0) goto disable_fifo; wcnt = t->len / bytes_per_word; if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT) goto disable_fifo; xferlevel = wcnt << 16; if (t->rx_buf != NULL) { chconf |= OMAP2_MCSPI_CHCONF_FFER; xferlevel |= (fifo_depth - 1) << 8; } if (t->tx_buf != NULL) { chconf |= OMAP2_MCSPI_CHCONF_FFET; xferlevel |= fifo_depth - 1; } mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel); mcspi_write_chconf0(spi, chconf); mcspi->fifo_depth = fifo_depth; return; } disable_fifo: if (t->rx_buf != NULL) chconf &= ~OMAP2_MCSPI_CHCONF_FFER; if (t->tx_buf != NULL) chconf &= ~OMAP2_MCSPI_CHCONF_FFET; mcspi_write_chconf0(spi, chconf); mcspi->fifo_depth = 0; }
static void omap2_mcspi_set_slave_mode(struct spi_master *master) { u32 l; l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 1); mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l; }
static void omap2_mcspi_set_master_mode(struct spi_device *spi, int single_channel) { u32 l; /* Need reset when switching from slave mode */ l = mcspi_read_reg(spi->master, OMAP2_MCSPI_MODULCTRL); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, single_channel); mcspi_write_reg(spi->master, OMAP2_MCSPI_MODULCTRL, l); }
static void omap2_mcspi_set_master_mode(struct spi_master *master) { u32 l; /* setup when switching from (reset default) slave mode * to single-channel master mode */ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); }
static void omap2_mcspi_set_master_mode(struct spi_master *master) { struct omap2_mcspi *mcspi = spi_master_get_devdata(master); struct omap2_mcspi_regs *ctx = &mcspi->ctx; u32 l; /* * Setup when switching from (reset default) slave mode * to single-channel master mode */ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); l &= ~(OMAP2_MCSPI_MODULCTRL_STEST | OMAP2_MCSPI_MODULCTRL_MS); l |= OMAP2_MCSPI_MODULCTRL_SINGLE; mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); ctx->modulctrl = l; }
static void omap2_mcspi_set_master_mode(struct spi_master *master) { u32 l; /* setup when switching from (reset default) slave mode * to single-channel master mode */ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); #ifdef CONFIG_SPI_SW_CS MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); #else MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 0); #endif mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l; }
static void omap2_mcspi_set_master_mode(struct spi_master *master) { u32 l; struct omap2_mcspi *mcspi = spi_master_get_devdata(master); /* setup when switching from (reset default) slave mode * to single-channel master mode based on config value */ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); if (mcspi->force_cs_mode) MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l; }
static irqreturn_t mcspi_isr(int irq, void *data) { struct omap2_mcspi *mcspi; u32 irqstatus; mcspi = data; /* Save and clear the status register to ack the IRQ */ irqstatus = mcspi_read_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS); irqstatus &= mcspi_read_reg(mcspi->master, OMAP2_MCSPI_IRQENABLE); mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS, irqstatus); mcspi->irq_status = irqstatus; irqstatus = mcspi_read_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS); complete(&mcspi->irq_completion); return IRQ_HANDLED; }
static void omap2_mcspi_set_mode(struct spi_master *master) { struct omap2_mcspi *mcspi = spi_master_get_devdata(master); struct omap2_mcspi_regs *ctx = &mcspi->ctx; u32 l; /* * Choose master or slave mode */ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); l &= ~(OMAP2_MCSPI_MODULCTRL_STEST); if (spi_controller_is_slave(master)) { l |= (OMAP2_MCSPI_MODULCTRL_MS); } else { l &= ~(OMAP2_MCSPI_MODULCTRL_MS); l |= OMAP2_MCSPI_MODULCTRL_SINGLE; } mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); ctx->modulctrl = l; }