static void altera_spi_chipsel(struct spi_device *spi, int value) { struct altera_spi *hw = altera_spi_to_hw(spi); if (spi->mode & SPI_CS_HIGH) { switch (value) { case BITBANG_CS_INACTIVE: writel(1 << spi->chip_select, hw->base + ALTERA_SPI_SLAVE_SEL); hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK; writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); break; case BITBANG_CS_ACTIVE: hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK; writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); writel(0, hw->base + ALTERA_SPI_SLAVE_SEL); break; } } else { switch (value) { case BITBANG_CS_INACTIVE: hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK; writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); break; case BITBANG_CS_ACTIVE: writel(1 << spi->chip_select, hw->base + ALTERA_SPI_SLAVE_SEL); hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK; writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); break; } } }
static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) { struct altera_spi *hw = altera_spi_to_hw(spi); hw->tx = t->tx_buf; hw->rx = t->rx_buf; hw->count = 0; hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8; hw->len = t->len / hw->bytes_per_word; if (hw->irq >= 0) { /* enable receive interrupt */ hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK; writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); /* send the first byte */ writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA); wait_for_completion(&hw->done); /* disable receive interrupt */ hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK; writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); } else { /* send the first byte */ writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA); while (1) { unsigned int rxd; while (!(readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK)) cpu_relax(); rxd = readl(hw->base + ALTERA_SPI_RXDATA); if (hw->rx) { switch (hw->bytes_per_word) { case 1: hw->rx[hw->count] = rxd; break; case 2: hw->rx[hw->count * 2] = rxd; hw->rx[hw->count * 2 + 1] = rxd >> 8; break; } } hw->count++; if (hw->count < hw->len) writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA); else break; } } return hw->count * hw->bytes_per_word; }