diff options
author | Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> | 2015-01-28 07:23:46 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-01-28 14:42:42 -0500 |
commit | f9c6ef6cfe9c16b6681607afd7e4f8379e615c4f (patch) | |
tree | 8121493bf8c85ce8fb7afc1090c741052e6eed63 /drivers/spi/spi-xilinx.c | |
parent | d9f5881242db8f9dc8a262c4bc613ba6fcb66bfc (diff) |
spi/xilinx: Support for spi mode CS_HIGH
The core controls the chip select lines individually.
By default, all the lines are consider active_low. After
spi_setup_transfer, it has its real value.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-xilinx.c')
-rw-r--r-- | drivers/spi/spi-xilinx.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 6656b2c82693..523da738805f 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c | |||
@@ -89,6 +89,7 @@ struct xilinx_spi { | |||
89 | int remaining_bytes; /* the number of bytes left to transfer */ | 89 | int remaining_bytes; /* the number of bytes left to transfer */ |
90 | u8 bits_per_word; | 90 | u8 bits_per_word; |
91 | int buffer_size; /* buffer size in words */ | 91 | int buffer_size; /* buffer size in words */ |
92 | u32 cs_inactive; /* Level of the CS pins when inactive*/ | ||
92 | unsigned int (*read_fn)(void __iomem *); | 93 | unsigned int (*read_fn)(void __iomem *); |
93 | void (*write_fn)(u32, void __iomem *); | 94 | void (*write_fn)(u32, void __iomem *); |
94 | void (*tx_fn)(struct xilinx_spi *); | 95 | void (*tx_fn)(struct xilinx_spi *); |
@@ -194,33 +195,37 @@ static void xspi_init_hw(struct xilinx_spi *xspi) | |||
194 | static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | 195 | static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) |
195 | { | 196 | { |
196 | struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); | 197 | struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); |
198 | u16 cr; | ||
199 | u32 cs; | ||
197 | 200 | ||
198 | if (is_on == BITBANG_CS_INACTIVE) { | 201 | if (is_on == BITBANG_CS_INACTIVE) { |
199 | /* Deselect the slave on the SPI bus */ | 202 | /* Deselect the slave on the SPI bus */ |
200 | xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET); | 203 | xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET); |
201 | } else if (is_on == BITBANG_CS_ACTIVE) { | 204 | return; |
202 | /* Set the SPI clock phase and polarity */ | ||
203 | u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) | ||
204 | & ~XSPI_CR_MODE_MASK; | ||
205 | if (spi->mode & SPI_CPHA) | ||
206 | cr |= XSPI_CR_CPHA; | ||
207 | if (spi->mode & SPI_CPOL) | ||
208 | cr |= XSPI_CR_CPOL; | ||
209 | if (spi->mode & SPI_LSB_FIRST) | ||
210 | cr |= XSPI_CR_LSB_FIRST; | ||
211 | if (spi->mode & SPI_LOOP) | ||
212 | cr |= XSPI_CR_LOOP; | ||
213 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); | ||
214 | |||
215 | /* We do not check spi->max_speed_hz here as the SPI clock | ||
216 | * frequency is not software programmable (the IP block design | ||
217 | * parameter) | ||
218 | */ | ||
219 | |||
220 | /* Activate the chip select */ | ||
221 | xspi->write_fn(~(0x0001 << spi->chip_select), | ||
222 | xspi->regs + XSPI_SSR_OFFSET); | ||
223 | } | 205 | } |
206 | |||
207 | /* Set the SPI clock phase and polarity */ | ||
208 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_MODE_MASK; | ||
209 | if (spi->mode & SPI_CPHA) | ||
210 | cr |= XSPI_CR_CPHA; | ||
211 | if (spi->mode & SPI_CPOL) | ||
212 | cr |= XSPI_CR_CPOL; | ||
213 | if (spi->mode & SPI_LSB_FIRST) | ||
214 | cr |= XSPI_CR_LSB_FIRST; | ||
215 | if (spi->mode & SPI_LOOP) | ||
216 | cr |= XSPI_CR_LOOP; | ||
217 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); | ||
218 | |||
219 | /* We do not check spi->max_speed_hz here as the SPI clock | ||
220 | * frequency is not software programmable (the IP block design | ||
221 | * parameter) | ||
222 | */ | ||
223 | |||
224 | cs = xspi->cs_inactive; | ||
225 | cs ^= BIT(spi->chip_select); | ||
226 | |||
227 | /* Activate the chip select */ | ||
228 | xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET); | ||
224 | } | 229 | } |
225 | 230 | ||
226 | /* spi_bitbang requires custom setup_transfer() to be defined if there is a | 231 | /* spi_bitbang requires custom setup_transfer() to be defined if there is a |
@@ -229,6 +234,13 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | |||
229 | static int xilinx_spi_setup_transfer(struct spi_device *spi, | 234 | static int xilinx_spi_setup_transfer(struct spi_device *spi, |
230 | struct spi_transfer *t) | 235 | struct spi_transfer *t) |
231 | { | 236 | { |
237 | struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); | ||
238 | |||
239 | if (spi->mode & SPI_CS_HIGH) | ||
240 | xspi->cs_inactive &= ~BIT(spi->chip_select); | ||
241 | else | ||
242 | xspi->cs_inactive |= BIT(spi->chip_select); | ||
243 | |||
232 | return 0; | 244 | return 0; |
233 | } | 245 | } |
234 | 246 | ||
@@ -376,9 +388,11 @@ static int xilinx_spi_probe(struct platform_device *pdev) | |||
376 | return -ENODEV; | 388 | return -ENODEV; |
377 | 389 | ||
378 | /* the spi->mode bits understood by this driver: */ | 390 | /* the spi->mode bits understood by this driver: */ |
379 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP; | 391 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | |
392 | SPI_CS_HIGH; | ||
380 | 393 | ||
381 | xspi = spi_master_get_devdata(master); | 394 | xspi = spi_master_get_devdata(master); |
395 | xspi->cs_inactive = 0xffffffff; | ||
382 | xspi->bitbang.master = master; | 396 | xspi->bitbang.master = master; |
383 | xspi->bitbang.chipselect = xilinx_spi_chipselect; | 397 | xspi->bitbang.chipselect = xilinx_spi_chipselect; |
384 | xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; | 398 | xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; |