Skip to content

Commit 485e4a4

Browse files
Jon Linrkhuangtao
authored andcommitted
spi: rockchip: Support cs-gpio
Change-Id: I8f839189038afd77d534d767d938c845aa54fedb Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
1 parent 5963f47 commit 485e4a4

2 files changed

Lines changed: 81 additions & 26 deletions

File tree

drivers/spi/spi-rockchip.c

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <linux/clk.h>
1717
#include <linux/dmaengine.h>
18+
#include <linux/gpio.h>
1819
#include <linux/module.h>
1920
#include <linux/of.h>
2021
#include <linux/platform_device.h>
@@ -24,6 +25,11 @@
2425

2526
#define DRIVER_NAME "rockchip-spi"
2627

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+
2733
/* SPI register offsets */
2834
#define ROCKCHIP_SPI_CTRLR0 0x0000
2935
#define ROCKCHIP_SPI_CTRLR1 0x0004
@@ -144,6 +150,8 @@
144150
/* max sclk of driver strength 4mA */
145151
#define IO_DRIVER_4MA_MAX_SCLK_OUT 24000000
146152

153+
#define ROCKCHIP_SPI_MAX_CS_NUM 4
154+
147155
enum rockchip_ssi_type {
148156
SSI_MOTO_SPI = 0,
149157
SSI_TI_SSP,
@@ -194,6 +202,10 @@ struct rockchip_spi {
194202
struct rockchip_spi_dma_data dma_rx;
195203
struct rockchip_spi_dma_data dma_tx;
196204
struct pinctrl_state *high_speed_state;
205+
206+
bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
207+
208+
bool gpio_requested;
197209
};
198210

199211
static inline void spi_enable_chip(struct rockchip_spi *rs, int enable)
@@ -259,37 +271,33 @@ static inline u32 rx_max(struct rockchip_spi *rs)
259271

260272
static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
261273
{
262-
u32 ser;
263274
struct spi_master *master = spi->master;
264275
struct rockchip_spi *rs = spi_master_get_devdata(master);
276+
bool cs_asserted = spi->mode & SPI_CS_HIGH ? enable : !enable;
265277

266-
pm_runtime_get_sync(rs->dev);
278+
/* Return immediately for no-op */
279+
if (cs_asserted == rs->cs_asserted[spi->chip_select])
280+
return;
267281

268-
ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK;
282+
if (cs_asserted) {
283+
/* Keep things powered as long as CS is asserted */
284+
pm_runtime_get_sync(rs->dev);
269285

270-
/*
271-
* drivers/spi/spi.c:
272-
* static void spi_set_cs(struct spi_device *spi, bool enable)
273-
* {
274-
* if (spi->mode & SPI_CS_HIGH)
275-
* enable = !enable;
276-
*
277-
* if (spi->cs_gpio >= 0)
278-
* gpio_set_value(spi->cs_gpio, !enable);
279-
* else if (spi->master->set_cs)
280-
* spi->master->set_cs(spi, !enable);
281-
* }
282-
*
283-
* Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs)
284-
*/
285-
if (!enable)
286-
ser |= 1 << spi->chip_select;
287-
else
288-
ser &= ~(1 << spi->chip_select);
286+
if (gpio_is_valid(spi->cs_gpio))
287+
ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, 1);
288+
else
289+
ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select));
290+
} else {
291+
if (gpio_is_valid(spi->cs_gpio))
292+
ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER, 1);
293+
else
294+
ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select));
289295

290-
writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER);
296+
/* Drop reference from when we first asserted CS */
297+
pm_runtime_put(rs->dev);
298+
}
291299

292-
pm_runtime_put_sync(rs->dev);
300+
rs->cs_asserted[spi->chip_select] = cs_asserted;
293301
}
294302

295303
static int rockchip_spi_prepare_message(struct spi_master *master,
@@ -678,6 +686,49 @@ static bool rockchip_spi_can_dma(struct spi_master *master,
678686
return (xfer->len > rs->fifo_len);
679687
}
680688

689+
static int rockchip_spi_setup(struct spi_device *spi)
690+
{
691+
692+
int ret = -EINVAL;
693+
struct spi_master *master = spi->master;
694+
struct rockchip_spi *rs = spi_master_get_devdata(master);
695+
696+
if (spi->cs_gpio == -ENOENT)
697+
return 0;
698+
699+
if (!rs->gpio_requested && gpio_is_valid(spi->cs_gpio)) {
700+
ret = gpio_request_one(spi->cs_gpio,
701+
(spi->mode & SPI_CS_HIGH) ?
702+
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
703+
dev_name(&spi->dev));
704+
if (ret)
705+
dev_err(&spi->dev, "can't request chipselect gpio %d\n",
706+
spi->cs_gpio);
707+
else
708+
rs->gpio_requested = true;
709+
} else {
710+
if (gpio_is_valid(spi->cs_gpio)) {
711+
int mode = ((spi->mode & SPI_CS_HIGH) ? 0 : 1);
712+
713+
ret = gpio_direction_output(spi->cs_gpio, mode);
714+
if (ret)
715+
dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
716+
spi->cs_gpio, ret);
717+
}
718+
}
719+
720+
return ret;
721+
}
722+
723+
static void rockchip_spi_cleanup(struct spi_device *spi)
724+
{
725+
struct spi_master *master = spi->master;
726+
struct rockchip_spi *rs = spi_master_get_devdata(master);
727+
728+
if (rs->gpio_requested)
729+
gpio_free(spi->cs_gpio);
730+
}
731+
681732
static int rockchip_spi_probe(struct platform_device *pdev)
682733
{
683734
int ret = 0;
@@ -759,6 +810,8 @@ static int rockchip_spi_probe(struct platform_device *pdev)
759810
master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
760811

761812
master->set_cs = rockchip_spi_set_cs;
813+
master->setup = rockchip_spi_setup;
814+
master->cleanup = rockchip_spi_cleanup;
762815
master->prepare_message = rockchip_spi_prepare_message;
763816
master->unprepare_message = rockchip_spi_unprepare_message;
764817
master->transfer_one = rockchip_spi_transfer_one;

drivers/spi/spi.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,12 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
673673
if (spi->mode & SPI_CS_HIGH)
674674
enable = !enable;
675675

676-
if (gpio_is_valid(spi->cs_gpio))
676+
if (gpio_is_valid(spi->cs_gpio)) {
677677
gpio_set_value(spi->cs_gpio, !enable);
678-
else if (spi->master->set_cs)
679678
spi->master->set_cs(spi, !enable);
679+
} else {
680+
spi->master->set_cs(spi, !enable);
681+
}
680682
}
681683

682684
#ifdef CONFIG_HAS_DMA

0 commit comments

Comments
 (0)