aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi-rockchip.c51
1 files changed, 26 insertions, 25 deletions
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 52ea1605d4c6..0b4a52b3e1dc 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -25,6 +25,11 @@
25 25
26#define DRIVER_NAME "rockchip-spi" 26#define DRIVER_NAME "rockchip-spi"
27 27
28#define ROCKCHIP_SPI_CLR_BITS(reg, bits) \
29 writel_relaxed(readl_relaxed(reg) & ~(bits), reg)
30#define ROCKCHIP_SPI_SET_BITS(reg, bits) \
31 writel_relaxed(readl_relaxed(reg) | (bits), reg)
32
28/* SPI register offsets */ 33/* SPI register offsets */
29#define ROCKCHIP_SPI_CTRLR0 0x0000 34#define ROCKCHIP_SPI_CTRLR0 0x0000
30#define ROCKCHIP_SPI_CTRLR1 0x0004 35#define ROCKCHIP_SPI_CTRLR1 0x0004
@@ -149,6 +154,8 @@
149 */ 154 */
150#define ROCKCHIP_SPI_MAX_TRANLEN 0xffff 155#define ROCKCHIP_SPI_MAX_TRANLEN 0xffff
151 156
157#define ROCKCHIP_SPI_MAX_CS_NUM 2
158
152enum rockchip_ssi_type { 159enum rockchip_ssi_type {
153 SSI_MOTO_SPI = 0, 160 SSI_MOTO_SPI = 0,
154 SSI_TI_SSP, 161 SSI_TI_SSP,
@@ -193,6 +200,8 @@ struct rockchip_spi {
193 /* protect state */ 200 /* protect state */
194 spinlock_t lock; 201 spinlock_t lock;
195 202
203 bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
204
196 u32 use_dma; 205 u32 use_dma;
197 struct sg_table tx_sg; 206 struct sg_table tx_sg;
198 struct sg_table rx_sg; 207 struct sg_table rx_sg;
@@ -264,37 +273,29 @@ static inline u32 rx_max(struct rockchip_spi *rs)
264 273
265static void rockchip_spi_set_cs(struct spi_device *spi, bool enable) 274static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
266{ 275{
267 u32 ser;
268 struct spi_master *master = spi->master; 276 struct spi_master *master = spi->master;
269 struct rockchip_spi *rs = spi_master_get_devdata(master); 277 struct rockchip_spi *rs = spi_master_get_devdata(master);
278 bool cs_asserted = !enable;
270 279
271 pm_runtime_get_sync(rs->dev); 280 /* Return immediately for no-op */
281 if (cs_asserted == rs->cs_asserted[spi->chip_select])
282 return;
272 283
273 ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK; 284 if (cs_asserted) {
285 /* Keep things powered as long as CS is asserted */
286 pm_runtime_get_sync(rs->dev);
274 287
275 /* 288 ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER,
276 * drivers/spi/spi.c: 289 BIT(spi->chip_select));
277 * static void spi_set_cs(struct spi_device *spi, bool enable) 290 } else {
278 * { 291 ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER,
279 * if (spi->mode & SPI_CS_HIGH) 292 BIT(spi->chip_select));
280 * enable = !enable;
281 *
282 * if (spi->cs_gpio >= 0)
283 * gpio_set_value(spi->cs_gpio, !enable);
284 * else if (spi->master->set_cs)
285 * spi->master->set_cs(spi, !enable);
286 * }
287 *
288 * Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs)
289 */
290 if (!enable)
291 ser |= 1 << spi->chip_select;
292 else
293 ser &= ~(1 << spi->chip_select);
294 293
295 writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER); 294 /* Drop reference from when we first asserted CS */
295 pm_runtime_put(rs->dev);
296 }
296 297
297 pm_runtime_put_sync(rs->dev); 298 rs->cs_asserted[spi->chip_select] = cs_asserted;
298} 299}
299 300
300static int rockchip_spi_prepare_message(struct spi_master *master, 301static int rockchip_spi_prepare_message(struct spi_master *master,
@@ -739,7 +740,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
739 master->auto_runtime_pm = true; 740 master->auto_runtime_pm = true;
740 master->bus_num = pdev->id; 741 master->bus_num = pdev->id;
741 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; 742 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
742 master->num_chipselect = 2; 743 master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM;
743 master->dev.of_node = pdev->dev.of_node; 744 master->dev.of_node = pdev->dev.of_node;
744 master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); 745 master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
745 746