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_cs(struct spi_device *spi, bool enable) { struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); u32 l; /* The controller handles the inverted chip selects * using the OMAP2_MCSPI_CHCONF_EPOL bit so revert * the inversion from the core spi_set_cs function. */ if (spi->mode & SPI_CS_HIGH) enable = !enable; if (spi->controller_state) { int err = pm_runtime_get_sync(mcspi->dev); if (err < 0) { pm_runtime_put_noidle(mcspi->dev); dev_err(mcspi->dev, "failed to get sync: %d\n", err); return; } l = mcspi_cached_chconf0(spi); if (enable) l &= ~OMAP2_MCSPI_CHCONF_FORCE; else l |= OMAP2_MCSPI_CHCONF_FORCE; mcspi_write_chconf0(spi, l); pm_runtime_mark_last_busy(mcspi->dev); pm_runtime_put_autosuspend(mcspi->dev); } }
static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) { u32 l; l = mcspi_cached_chconf0(spi); MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active); mcspi_write_chconf0(spi, l); }
static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) { u32 l; l = mcspi_cached_chconf0(spi); if (cs_active) l |= OMAP2_MCSPI_CHCONF_FORCE; else l &= ~OMAP2_MCSPI_CHCONF_FORCE; mcspi_write_chconf0(spi, l); }
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 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_set_dma_req(const struct spi_device *spi, int is_read, int enable) { u32 l, rw; l = mcspi_cached_chconf0(spi); if (is_read) /* 1 is read, 0 write */ rw = OMAP2_MCSPI_CHCONF_DMAR; else rw = OMAP2_MCSPI_CHCONF_DMAW; MOD_REG_BIT(l, rw, enable); mcspi_write_chconf0(spi, l); }
static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) { u32 l; struct omap2_mcspi* mcspi = spi_master_get_devdata(spi->master); /* allow GPIOs as chip select if defined */ if (mcspi->cs_gpios && mcspi->cs_gpios[spi->chip_select]) { int gpio = mcspi->cs_gpios[spi->chip_select]; gpio_set_value(gpio, !cs_active); /* low active */ } // TXS times out unless we force the CHCONF reg as well l = mcspi_cached_chconf0(spi); MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active); mcspi_write_chconf0(spi, l); }