| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * This driver has been based on the spi-gpio.c: |
|---|
| 7 | 8 | * Copyright (C) 2006,2008 David Brownell |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 10 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 11 | | - * published by the Free Software Foundation. |
|---|
| 12 | | - * |
|---|
| 13 | 9 | */ |
|---|
| 14 | 10 | |
|---|
| 15 | 11 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 21 | 17 | #include <linux/spi/spi.h> |
|---|
| 22 | 18 | #include <linux/spi/spi_bitbang.h> |
|---|
| 23 | 19 | #include <linux/bitops.h> |
|---|
| 24 | | -#include <linux/gpio.h> |
|---|
| 25 | 20 | #include <linux/clk.h> |
|---|
| 26 | 21 | #include <linux/err.h> |
|---|
| 27 | | - |
|---|
| 28 | | -#include <asm/mach-ath79/ar71xx_regs.h> |
|---|
| 29 | | -#include <asm/mach-ath79/ath79_spi_platform.h> |
|---|
| 22 | +#include <linux/platform_data/spi-ath79.h> |
|---|
| 30 | 23 | |
|---|
| 31 | 24 | #define DRV_NAME "ath79-spi" |
|---|
| 32 | 25 | |
|---|
| 33 | 26 | #define ATH79_SPI_RRW_DELAY_FACTOR 12000 |
|---|
| 34 | 27 | #define MHZ (1000 * 1000) |
|---|
| 28 | + |
|---|
| 29 | +#define AR71XX_SPI_REG_FS 0x00 /* Function Select */ |
|---|
| 30 | +#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */ |
|---|
| 31 | +#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */ |
|---|
| 32 | +#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */ |
|---|
| 33 | + |
|---|
| 34 | +#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */ |
|---|
| 35 | + |
|---|
| 36 | +#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */ |
|---|
| 37 | +#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */ |
|---|
| 38 | +#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) |
|---|
| 35 | 39 | |
|---|
| 36 | 40 | struct ath79_spi { |
|---|
| 37 | 41 | struct spi_bitbang bitbang; |
|---|
| .. | .. |
|---|
| 67 | 71 | { |
|---|
| 68 | 72 | struct ath79_spi *sp = ath79_spidev_to_sp(spi); |
|---|
| 69 | 73 | int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; |
|---|
| 74 | + u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); |
|---|
| 70 | 75 | |
|---|
| 71 | | - if (is_active) { |
|---|
| 72 | | - /* set initial clock polarity */ |
|---|
| 73 | | - if (spi->mode & SPI_CPOL) |
|---|
| 74 | | - sp->ioc_base |= AR71XX_SPI_IOC_CLK; |
|---|
| 75 | | - else |
|---|
| 76 | | - sp->ioc_base &= ~AR71XX_SPI_IOC_CLK; |
|---|
| 76 | + if (cs_high) |
|---|
| 77 | + sp->ioc_base |= cs_bit; |
|---|
| 78 | + else |
|---|
| 79 | + sp->ioc_base &= ~cs_bit; |
|---|
| 77 | 80 | |
|---|
| 78 | | - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); |
|---|
| 79 | | - } |
|---|
| 80 | | - |
|---|
| 81 | | - if (gpio_is_valid(spi->cs_gpio)) { |
|---|
| 82 | | - /* SPI is normally active-low */ |
|---|
| 83 | | - gpio_set_value_cansleep(spi->cs_gpio, cs_high); |
|---|
| 84 | | - } else { |
|---|
| 85 | | - u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); |
|---|
| 86 | | - |
|---|
| 87 | | - if (cs_high) |
|---|
| 88 | | - sp->ioc_base |= cs_bit; |
|---|
| 89 | | - else |
|---|
| 90 | | - sp->ioc_base &= ~cs_bit; |
|---|
| 91 | | - |
|---|
| 92 | | - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); |
|---|
| 93 | | - } |
|---|
| 94 | | - |
|---|
| 81 | + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); |
|---|
| 95 | 82 | } |
|---|
| 96 | 83 | |
|---|
| 97 | 84 | static void ath79_spi_enable(struct ath79_spi *sp) |
|---|
| .. | .. |
|---|
| 103 | 90 | sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); |
|---|
| 104 | 91 | sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); |
|---|
| 105 | 92 | |
|---|
| 93 | + /* clear clk and mosi in the base state */ |
|---|
| 94 | + sp->ioc_base &= ~(AR71XX_SPI_IOC_DO | AR71XX_SPI_IOC_CLK); |
|---|
| 95 | + |
|---|
| 106 | 96 | /* TODO: setup speed? */ |
|---|
| 107 | 97 | ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); |
|---|
| 108 | 98 | } |
|---|
| .. | .. |
|---|
| 113 | 103 | ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); |
|---|
| 114 | 104 | /* disable GPIO mode */ |
|---|
| 115 | 105 | ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); |
|---|
| 116 | | -} |
|---|
| 117 | | - |
|---|
| 118 | | -static int ath79_spi_setup_cs(struct spi_device *spi) |
|---|
| 119 | | -{ |
|---|
| 120 | | - struct ath79_spi *sp = ath79_spidev_to_sp(spi); |
|---|
| 121 | | - int status; |
|---|
| 122 | | - |
|---|
| 123 | | - status = 0; |
|---|
| 124 | | - if (gpio_is_valid(spi->cs_gpio)) { |
|---|
| 125 | | - unsigned long flags; |
|---|
| 126 | | - |
|---|
| 127 | | - flags = GPIOF_DIR_OUT; |
|---|
| 128 | | - if (spi->mode & SPI_CS_HIGH) |
|---|
| 129 | | - flags |= GPIOF_INIT_LOW; |
|---|
| 130 | | - else |
|---|
| 131 | | - flags |= GPIOF_INIT_HIGH; |
|---|
| 132 | | - |
|---|
| 133 | | - status = gpio_request_one(spi->cs_gpio, flags, |
|---|
| 134 | | - dev_name(&spi->dev)); |
|---|
| 135 | | - } else { |
|---|
| 136 | | - u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); |
|---|
| 137 | | - |
|---|
| 138 | | - if (spi->mode & SPI_CS_HIGH) |
|---|
| 139 | | - sp->ioc_base &= ~cs_bit; |
|---|
| 140 | | - else |
|---|
| 141 | | - sp->ioc_base |= cs_bit; |
|---|
| 142 | | - |
|---|
| 143 | | - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); |
|---|
| 144 | | - } |
|---|
| 145 | | - |
|---|
| 146 | | - return status; |
|---|
| 147 | | -} |
|---|
| 148 | | - |
|---|
| 149 | | -static void ath79_spi_cleanup_cs(struct spi_device *spi) |
|---|
| 150 | | -{ |
|---|
| 151 | | - if (gpio_is_valid(spi->cs_gpio)) |
|---|
| 152 | | - gpio_free(spi->cs_gpio); |
|---|
| 153 | | -} |
|---|
| 154 | | - |
|---|
| 155 | | -static int ath79_spi_setup(struct spi_device *spi) |
|---|
| 156 | | -{ |
|---|
| 157 | | - int status = 0; |
|---|
| 158 | | - |
|---|
| 159 | | - if (!spi->controller_state) { |
|---|
| 160 | | - status = ath79_spi_setup_cs(spi); |
|---|
| 161 | | - if (status) |
|---|
| 162 | | - return status; |
|---|
| 163 | | - } |
|---|
| 164 | | - |
|---|
| 165 | | - status = spi_bitbang_setup(spi); |
|---|
| 166 | | - if (status && !spi->controller_state) |
|---|
| 167 | | - ath79_spi_cleanup_cs(spi); |
|---|
| 168 | | - |
|---|
| 169 | | - return status; |
|---|
| 170 | | -} |
|---|
| 171 | | - |
|---|
| 172 | | -static void ath79_spi_cleanup(struct spi_device *spi) |
|---|
| 173 | | -{ |
|---|
| 174 | | - ath79_spi_cleanup_cs(spi); |
|---|
| 175 | | - spi_bitbang_cleanup(spi); |
|---|
| 176 | 106 | } |
|---|
| 177 | 107 | |
|---|
| 178 | 108 | static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs, |
|---|
| .. | .. |
|---|
| 209 | 139 | struct spi_master *master; |
|---|
| 210 | 140 | struct ath79_spi *sp; |
|---|
| 211 | 141 | struct ath79_spi_platform_data *pdata; |
|---|
| 212 | | - struct resource *r; |
|---|
| 213 | 142 | unsigned long rate; |
|---|
| 214 | 143 | int ret; |
|---|
| 215 | 144 | |
|---|
| .. | .. |
|---|
| 225 | 154 | |
|---|
| 226 | 155 | pdata = dev_get_platdata(&pdev->dev); |
|---|
| 227 | 156 | |
|---|
| 157 | + master->use_gpio_descriptors = true; |
|---|
| 228 | 158 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); |
|---|
| 229 | | - master->setup = ath79_spi_setup; |
|---|
| 230 | | - master->cleanup = ath79_spi_cleanup; |
|---|
| 159 | + master->flags = SPI_MASTER_GPIO_SS; |
|---|
| 231 | 160 | if (pdata) { |
|---|
| 232 | 161 | master->bus_num = pdata->bus_num; |
|---|
| 233 | 162 | master->num_chipselect = pdata->num_chipselect; |
|---|
| .. | .. |
|---|
| 236 | 165 | sp->bitbang.master = master; |
|---|
| 237 | 166 | sp->bitbang.chipselect = ath79_spi_chipselect; |
|---|
| 238 | 167 | sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; |
|---|
| 239 | | - sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; |
|---|
| 240 | 168 | sp->bitbang.flags = SPI_CS_HIGH; |
|---|
| 241 | 169 | |
|---|
| 242 | | - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 243 | | - sp->base = devm_ioremap_resource(&pdev->dev, r); |
|---|
| 170 | + sp->base = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 244 | 171 | if (IS_ERR(sp->base)) { |
|---|
| 245 | 172 | ret = PTR_ERR(sp->base); |
|---|
| 246 | 173 | goto err_put_master; |
|---|