spi: s3c64xx: Added provision for dedicated cs pin
The existing driver supports gpio based /cs signal. For controller's that have one device per controller, the slave device's /cs signal might be internally controlled by the chip select bit of slave select register. They are not externally asserted/deasserted using gpio pin. This patch adds support for controllers with dedicated /cs pin. if "cs-gpio" property doesnt exist in a spi dts node, the controller would treat the /cs pin as dedicated. Signed-off-by: Girish K S <ks.giri@samsung.com> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
Родитель
796170733e
Коммит
3146beec21
|
@ -208,6 +208,7 @@ struct s3c64xx_spi_driver_data {
|
|||
struct s3c64xx_spi_port_config *port_conf;
|
||||
unsigned int port_id;
|
||||
unsigned long gpios[4];
|
||||
bool cs_gpio;
|
||||
};
|
||||
|
||||
static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
|
||||
|
@ -570,14 +571,16 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
|
|||
if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
|
||||
/* Deselect the last toggled device */
|
||||
cs = sdd->tgl_spi->controller_data;
|
||||
gpio_set_value(cs->line,
|
||||
spi->mode & SPI_CS_HIGH ? 0 : 1);
|
||||
if (sdd->cs_gpio)
|
||||
gpio_set_value(cs->line,
|
||||
spi->mode & SPI_CS_HIGH ? 0 : 1);
|
||||
}
|
||||
sdd->tgl_spi = NULL;
|
||||
}
|
||||
|
||||
cs = spi->controller_data;
|
||||
gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
|
||||
if (sdd->cs_gpio)
|
||||
gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
|
||||
|
||||
/* Start the signals */
|
||||
writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
|
||||
|
@ -710,7 +713,8 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
|
|||
if (sdd->tgl_spi == spi)
|
||||
sdd->tgl_spi = NULL;
|
||||
|
||||
gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
|
||||
if (sdd->cs_gpio)
|
||||
gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
|
||||
|
||||
/* Quiese the signals */
|
||||
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
|
||||
|
@ -998,8 +1002,10 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
|
|||
{
|
||||
struct s3c64xx_spi_csinfo *cs;
|
||||
struct device_node *slave_np, *data_np = NULL;
|
||||
struct s3c64xx_spi_driver_data *sdd;
|
||||
u32 fb_delay = 0;
|
||||
|
||||
sdd = spi_master_get_devdata(spi->master);
|
||||
slave_np = spi->dev.of_node;
|
||||
if (!slave_np) {
|
||||
dev_err(&spi->dev, "device node not found\n");
|
||||
|
@ -1019,7 +1025,10 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
|
||||
/* The CS line is asserted/deasserted by the gpio pin */
|
||||
if (sdd->cs_gpio)
|
||||
cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
|
||||
|
||||
if (!gpio_is_valid(cs->line)) {
|
||||
dev_err(&spi->dev, "chip select gpio is not specified or invalid\n");
|
||||
kfree(cs);
|
||||
|
@ -1059,7 +1068,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!spi_get_ctldata(spi)) {
|
||||
/* Request gpio only if cs line is asserted by gpio pins */
|
||||
if (sdd->cs_gpio) {
|
||||
err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH,
|
||||
dev_name(&spi->dev));
|
||||
if (err) {
|
||||
|
@ -1068,9 +1078,11 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
|
|||
cs->line, err);
|
||||
goto err_gpio_req;
|
||||
}
|
||||
spi_set_ctldata(spi, cs);
|
||||
}
|
||||
|
||||
if (!spi_get_ctldata(spi))
|
||||
spi_set_ctldata(spi, cs);
|
||||
|
||||
sci = sdd->cntrlr_info;
|
||||
|
||||
spin_lock_irqsave(&sdd->lock, flags);
|
||||
|
@ -1148,8 +1160,10 @@ err_gpio_req:
|
|||
static void s3c64xx_spi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
|
||||
struct s3c64xx_spi_driver_data *sdd;
|
||||
|
||||
if (cs) {
|
||||
sdd = spi_master_get_devdata(spi->master);
|
||||
if (cs && sdd->cs_gpio) {
|
||||
gpio_free(cs->line);
|
||||
if (spi->dev.of_node)
|
||||
kfree(cs);
|
||||
|
@ -1326,7 +1340,11 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
|
|||
sdd->cntrlr_info = sci;
|
||||
sdd->pdev = pdev;
|
||||
sdd->sfr_start = mem_res->start;
|
||||
sdd->cs_gpio = true;
|
||||
if (pdev->dev.of_node) {
|
||||
if (!of_find_property(pdev->dev.of_node, "cs-gpio", NULL))
|
||||
sdd->cs_gpio = false;
|
||||
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "spi");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
|
||||
|
|
Загрузка…
Ссылка в новой задаче