static void ath79_spi_chipselect(struct spi_device *spi, int is_active) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; if (is_active) { /* set initial clock polarity */ if (spi->mode & SPI_CPOL) sp->ioc_base |= AR71XX_SPI_IOC_CLK; else sp->ioc_base &= ~AR71XX_SPI_IOC_CLK; ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } if (spi->chip_select) { struct ath79_spi_controller_data *cdata = spi->controller_data; /* SPI is normally active-low */ gpio_set_value(cdata->gpio, cs_high); } else { if (cs_high) sp->ioc_base |= AR71XX_SPI_IOC_CS0; else sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } }
static void ath79_spi_disable(struct ath79_spi *sp) { /* restore CTRL register */ ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); /* disable GPIO mode */ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); }
static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); u32 ioc = sp->ioc_base; /* clock starts at inactive polarity */ for (word <<= (32 - bits); likely(bits); bits--) { u32 out; if (word & (1 << 31)) out = ioc | AR71XX_SPI_IOC_DO; else out = ioc & ~AR71XX_SPI_IOC_DO; /* setup MSB (to slave) on trailing edge */ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out); ath79_spi_delay(sp, nsecs); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK); ath79_spi_delay(sp, nsecs); if (bits == 1) ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out); word <<= 1; } return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); }
static void ath79_spi_chipselect(struct spi_device *spi, int is_active) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; struct ath79_spi_controller_data *cdata = spi->controller_data; if (is_active) { /* set initial clock polarity */ if (spi->mode & SPI_CPOL) sp->ioc_base |= AR71XX_SPI_IOC_CLK; else sp->ioc_base &= ~AR71XX_SPI_IOC_CLK; ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } switch (cdata->cs_type) { case ATH79_SPI_CS_TYPE_INTERNAL: if (cs_high) sp->ioc_base |= AR71XX_SPI_IOC_CS(cdata->cs_line); else sp->ioc_base &= ~AR71XX_SPI_IOC_CS(cdata->cs_line); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); break; case ATH79_SPI_CS_TYPE_GPIO: /* SPI is normally active-low */ gpio_set_value(cdata->cs_line, cs_high); break; } }
static void ath79_spi_enable(struct ath79_spi *sp) { /* enable GPIO mode */ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); /* save CTRL register */ sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); /* TODO: setup speed? */ ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); }
static void ath79_spi_cleanup_cs(struct spi_device *spi) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); if (spi->chip_select) { struct ath79_spi_controller_data *cdata = spi->controller_data; gpio_free(cdata->gpio); } /* restore CTRL register */ ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); /* disable GPIO mode */ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); }
static int ath79_spi_setup_cs(struct spi_device *spi) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); int status; if (spi->chip_select && !gpio_is_valid(spi->cs_gpio)) return -EINVAL; status = 0; if (spi->chip_select) { unsigned long flags; flags = GPIOF_DIR_OUT; if (spi->mode & SPI_CS_HIGH) flags |= GPIOF_INIT_LOW; else flags |= GPIOF_INIT_HIGH; status = gpio_request_one(spi->cs_gpio, flags, dev_name(&spi->dev)); } else { if (spi->mode & SPI_CS_HIGH) sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; else sp->ioc_base |= AR71XX_SPI_IOC_CS0; ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } return status; }
static int ath79_spi_do_read_flash_data(struct spi_device *spi, struct spi_transfer *t) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); /* disable GPIO mode */ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); memcpy_fromio(t->rx_buf, sp->base + sp->read_addr, t->len); /* enable GPIO mode */ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); /* restore IOC register */ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); return t->len; }
static int ath79_spi_setup_cs(struct spi_device *spi) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); struct ath79_spi_controller_data *cdata; cdata = spi->controller_data; if (spi->chip_select && !cdata) return -EINVAL; /* enable GPIO mode */ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); /* save CTRL register */ sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); /* TODO: setup speed? */ ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); if (spi->chip_select) { int status = 0; status = gpio_request(cdata->gpio, dev_name(&spi->dev)); if (status) return status; status = gpio_direction_output(cdata->gpio, spi->mode & SPI_CS_HIGH); if (status) { gpio_free(cdata->gpio); return status; } } else { if (spi->mode & SPI_CS_HIGH) sp->ioc_base |= AR71XX_SPI_IOC_CS0; else sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } return 0; }