diff options
| -rw-r--r-- | drivers/spi/spi_qsd.c | 60 | ||||
| -rw-r--r-- | drivers/spi/spi_qsd.h | 3 |
2 files changed, 51 insertions, 12 deletions
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c index 5c56001e36db..5fd1565d692f 100644 --- a/drivers/spi/spi_qsd.c +++ b/drivers/spi/spi_qsd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -55,6 +55,7 @@ static int get_local_resources(struct msm_spi *dd); static void put_local_resources(struct msm_spi *dd); static void msm_spi_slv_setup(struct msm_spi *dd); static inline int msm_spi_wait_valid(struct msm_spi *dd); +static int reset_core(struct msm_spi *dd); static inline int msm_spi_configure_gsbi(struct msm_spi *dd, struct platform_device *pdev) @@ -551,7 +552,7 @@ static inline int msm_spi_set_state(struct msm_spi *dd, } if (msm_spi_wait_valid(dd)) return -EIO; - + atomic_set(&dd->qup_state, state); return 0; } @@ -1491,6 +1492,10 @@ static int msm_spi_process_transfer(struct msm_spi *dd) } } while (msm_spi_dma_send_next(dd)); + if (status && dd->pdata->is_slv_ctrl) { + if (reset_core(dd)) + dev_err(dd->dev, "Reset failed\n"); + } msm_spi_udelay(dd->xfrs_delay_usec); transfer_end: @@ -1578,14 +1583,15 @@ static int reset_core(struct msm_spi *dd) * bit. */ msm_spi_enable_error_flags(dd); - - spi_ioc = readl_relaxed(dd->base + SPI_IO_CONTROL); - spi_ioc |= SPI_IO_C_NO_TRI_STATE; - writel_relaxed(spi_ioc , dd->base + SPI_IO_CONTROL); - /* - * Ensure that the IO control is written to before returning. - */ - mb(); + if (!dd->pdata->is_slv_ctrl) { + spi_ioc = readl_relaxed(dd->base + SPI_IO_CONTROL); + spi_ioc |= SPI_IO_C_NO_TRI_STATE; + writel_relaxed(spi_ioc, dd->base + SPI_IO_CONTROL); + /* + * Ensure that the IO control is written to before returning. + */ + mb(); + } msm_spi_set_state(dd, SPI_OP_STATE_RESET); return 0; } @@ -2034,6 +2040,33 @@ static ssize_t set_stats(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(stats, S_IRUGO | S_IWUSR, show_stats, set_stats); +static ssize_t show_qup_state(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct platform_device *pdev = container_of(dev, struct + platform_device, dev); + struct spi_master *master = platform_get_drvdata(pdev); + struct msm_spi *dd; + + dd = spi_master_get_devdata(master); + /* This check should not fail */ + if (dd) + ret = snprintf(buf, sizeof(int), "%u\n", + atomic_read(&dd->qup_state)); + return ret; +} + +static ssize_t set_qup_state(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return 1; +} + +static DEVICE_ATTR(spi_qup_state, S_IWUSR | S_IRUGO, + show_qup_state, set_qup_state); + static struct attribute *dev_attrs[] = { &dev_attr_stats.attr, NULL, @@ -2471,7 +2504,9 @@ static int init_resources(struct platform_device *pdev) */ msm_spi_enable_error_flags(dd); - writel_relaxed(SPI_IO_C_NO_TRI_STATE, dd->base + SPI_IO_CONTROL); + if (dd->pdata && !dd->pdata->is_slv_ctrl) + writel_relaxed(SPI_IO_C_NO_TRI_STATE, + dd->base + SPI_IO_CONTROL); rc = msm_spi_set_state(dd, SPI_OP_STATE_RESET); if (rc) goto err_spi_state; @@ -2609,6 +2644,7 @@ static int msm_spi_probe(struct platform_device *pdev) dd->mem_size = resource_size(resource); dd->dev = &pdev->dev; + atomic_set(&dd->qup_state, SPI_OP_STATE_RESET); if (pdata) { master->rt = pdata->rt_priority; if (pdata->dma_config) { @@ -2682,6 +2718,7 @@ skip_dma_resources: dev_err(&pdev->dev, "failed to create dev. attrs : %d\n", rc); goto err_attrs; } + rc = sysfs_create_file(&(dd->dev->kobj), &dev_attr_spi_qup_state.attr); spi_debugfs_init(dd); return 0; @@ -2835,6 +2872,7 @@ static int msm_spi_remove(struct platform_device *pdev) spi_debugfs_exit(dd); sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp); + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_spi_qup_state.attr); if (dd->dma_teardown) dd->dma_teardown(dd); diff --git a/drivers/spi/spi_qsd.h b/drivers/spi/spi_qsd.h index 6632fe806e41..09b9cb9d5b7d 100644 --- a/drivers/spi/spi_qsd.h +++ b/drivers/spi/spi_qsd.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -405,6 +405,7 @@ struct msm_spi { bool is_init_complete; bool pack_words; bool slv_support; + atomic_t qup_state; }; /* Forward declaration */ |
