summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2021-05-11 11:41:59 +0100
committerMark Brown <broonie@kernel.org>2021-05-11 11:41:59 +0100
commit6e5c3ab8959499491f96fdba686eabb50fc6062d (patch)
treed4707c654a510c69575b09905f4c838d4f30d5ed /drivers
parent532259bfd1c12d561215c32b94cd9bb7c997bc6f (diff)
parent3fdb59cf10b020b32b9f1dfc78611320623dcb3e (diff)
downloadlinux-6e5c3ab8959499491f96fdba686eabb50fc6062d.tar.bz2
Merge series "spi: pxa2xx: Set of cleanups" from Andy Shevchenko <andriy.shevchenko@linux.intel.com>:
Set of cleanups here and there related to the SPI PXA2xx driver. On top of them, adding the special type for Intel Merrifield. In v3: - rebased on top of v5.13-rc1 and/or spi/for-5,14 In v2: - cover letter (Mark) - drop moving the header in patch 5 (Mark) Andy Shevchenko (14): spi: pxa2xx: Use one point of return when ->probe() fails spi: pxa2xx: Utilize MMIO and physical base from struct ssp_device spi: pxa2xx: Utilize struct device from struct ssp_device spi: pxa2xx: Replace header inclusions by forward declarations spi: pxa2xx: Unify ifdeffery used in the headers spi: pxa2xx: Group Intel Quark specific definitions spi: pxa2xx: Introduce int_stop_and_reset() helper spi: pxa2xx: Reuse int_error_stop() in pxa2xx_spi_slave_abort() spi: pxa2xx: Use pxa_ssp_enable()/pxa_ssp_disable() in the driver spi: pxa2xx: Extract pxa2xx_spi_update() helper spi: pxa2xx: Extract clear_SSCR1_bits() helper spi: pxa2xx: Extract read_SSSR_bits() helper spi: pxa2xx: Constify struct driver_data parameter spi: pxa2xx: Introduce special type for Merrifield SPIs drivers/spi/spi-pxa2xx-dma.c | 37 +++---- drivers/spi/spi-pxa2xx-pci.c | 4 +- drivers/spi/spi-pxa2xx.c | 190 +++++++++++++++++---------------- drivers/spi/spi-pxa2xx.h | 52 ++++----- include/linux/pxa2xx_ssp.h | 42 +++++++- include/linux/spi/pxa2xx_spi.h | 9 +- sound/soc/pxa/pxa-ssp.c | 16 --- 7 files changed, 185 insertions(+), 165 deletions(-) -- 2.30.2
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/spi-pxa2xx-dma.c17
-rw-r--r--drivers/spi/spi-pxa2xx-pci.c2
-rw-r--r--drivers/spi/spi-pxa2xx.c170
-rw-r--r--drivers/spi/spi-pxa2xx.h16
4 files changed, 107 insertions, 98 deletions
diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c
index e00dbadd39ec..f022d82dcb1b 100644
--- a/drivers/spi/spi-pxa2xx-dma.c
+++ b/drivers/spi/spi-pxa2xx-dma.c
@@ -34,25 +34,18 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
* might not know about the error yet. So we re-check the
* ROR bit here before we clear the status register.
*/
- if (!error) {
- u32 status = pxa2xx_spi_read(drv_data, SSSR)
- & drv_data->mask_sr;
- error = status & SSSR_ROR;
- }
+ if (!error)
+ error = read_SSSR_bits(drv_data, drv_data->mask_sr) & SSSR_ROR;
/* Clear status & disable interrupts */
- pxa2xx_spi_write(drv_data, SSCR1,
- pxa2xx_spi_read(drv_data, SSCR1)
- & ~drv_data->dma_cr1);
+ clear_SSCR1_bits(drv_data, drv_data->dma_cr1);
write_SSSR_CS(drv_data, drv_data->clear_sr);
if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0);
if (error) {
/* In case we got an error we disable the SSP now */
- pxa2xx_spi_write(drv_data, SSCR0,
- pxa2xx_spi_read(drv_data, SSCR0)
- & ~SSCR0_SSE);
+ pxa_ssp_disable(drv_data->ssp);
msg->status = -EIO;
}
@@ -123,7 +116,7 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
{
u32 status;
- status = pxa2xx_spi_read(drv_data, SSSR) & drv_data->mask_sr;
+ status = read_SSSR_bits(drv_data, drv_data->mask_sr);
if (status & SSSR_ROR) {
dev_err(drv_data->ssp->dev, "FIFO overrun\n");
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index a259be12d326..dce9ade9a4df 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -179,7 +179,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.rx_param = &bsw2_rx_param,
},
[PORT_MRFLD] = {
- .type = PXA27x_SSP,
+ .type = MRFLD_SSP,
.max_clk_rate = 25000000,
.setup = mrfld_spi_setup,
},
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 1d4c7f4217ed..5985b39e2dd6 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -200,6 +200,17 @@ static bool is_mmp2_ssp(const struct driver_data *drv_data)
return drv_data->ssp_type == MMP2_SSP;
}
+static bool is_mrfld_ssp(const struct driver_data *drv_data)
+{
+ return drv_data->ssp_type == MRFLD_SSP;
+}
+
+static void pxa2xx_spi_update(const struct driver_data *drv_data, u32 reg, u32 mask, u32 value)
+{
+ if ((pxa2xx_spi_read(drv_data, reg) & mask) != value)
+ pxa2xx_spi_write(drv_data, reg, value & mask);
+}
+
static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data)
{
switch (drv_data->ssp_type) {
@@ -241,7 +252,7 @@ static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data)
break;
}
- return (pxa2xx_spi_read(drv_data, SSSR) & mask) == mask;
+ return read_SSSR_bits(drv_data, mask) == mask;
}
static void pxa2xx_spi_clear_rx_thre(const struct driver_data *drv_data,
@@ -286,13 +297,11 @@ static u32 pxa2xx_configure_sscr0(const struct driver_data *drv_data,
case QUARK_X1000_SSP:
return clk_div
| QUARK_X1000_SSCR0_Motorola
- | QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits)
- | SSCR0_SSE;
+ | QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits);
default:
return clk_div
| SSCR0_Motorola
| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
- | SSCR0_SSE
| (bits > 16 ? SSCR0_EDSS : 0);
}
}
@@ -484,7 +493,7 @@ int pxa2xx_spi_flush(struct driver_data *drv_data)
unsigned long limit = loops_per_jiffy << 1;
do {
- while (pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE)
+ while (read_SSSR_bits(drv_data, SSSR_RNE))
pxa2xx_spi_read(drv_data, SSDR);
} while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY) && --limit);
write_SSSR_CS(drv_data, SSSR_ROR);
@@ -498,8 +507,7 @@ static void pxa2xx_spi_off(struct driver_data *drv_data)
if (is_mmp2_ssp(drv_data))
return;
- pxa2xx_spi_write(drv_data, SSCR0,
- pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
+ pxa_ssp_disable(drv_data->ssp);
}
static int null_writer(struct driver_data *drv_data)
@@ -520,8 +528,7 @@ static int null_reader(struct driver_data *drv_data)
{
u8 n_bytes = drv_data->n_bytes;
- while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
pxa2xx_spi_read(drv_data, SSDR);
drv_data->rx += n_bytes;
}
@@ -543,8 +550,7 @@ static int u8_writer(struct driver_data *drv_data)
static int u8_reader(struct driver_data *drv_data)
{
- while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
*(u8 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR);
++drv_data->rx;
}
@@ -566,8 +572,7 @@ static int u16_writer(struct driver_data *drv_data)
static int u16_reader(struct driver_data *drv_data)
{
- while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
*(u16 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR);
drv_data->rx += 2;
}
@@ -589,8 +594,7 @@ static int u32_writer(struct driver_data *drv_data)
static int u32_reader(struct driver_data *drv_data)
{
- while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
*(u32 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR);
drv_data->rx += 4;
}
@@ -620,47 +624,51 @@ static void reset_sccr1(struct driver_data *drv_data)
pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg);
}
-static void int_error_stop(struct driver_data *drv_data, const char *msg)
+static void int_stop_and_reset(struct driver_data *drv_data)
{
- /* Stop and reset SSP */
+ /* Clear and disable interrupts */
write_SSSR_CS(drv_data, drv_data->clear_sr);
reset_sccr1(drv_data);
- if (!pxa25x_ssp_comp(drv_data))
- pxa2xx_spi_write(drv_data, SSTO, 0);
+ if (pxa25x_ssp_comp(drv_data))
+ return;
+
+ pxa2xx_spi_write(drv_data, SSTO, 0);
+}
+
+static void int_error_stop(struct driver_data *drv_data, const char *msg, int err)
+{
+ int_stop_and_reset(drv_data);
pxa2xx_spi_flush(drv_data);
pxa2xx_spi_off(drv_data);
dev_err(drv_data->ssp->dev, "%s\n", msg);
- drv_data->controller->cur_msg->status = -EIO;
+ drv_data->controller->cur_msg->status = err;
spi_finalize_current_transfer(drv_data->controller);
}
static void int_transfer_complete(struct driver_data *drv_data)
{
- /* Clear and disable interrupts */
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- reset_sccr1(drv_data);
- if (!pxa25x_ssp_comp(drv_data))
- pxa2xx_spi_write(drv_data, SSTO, 0);
+ int_stop_and_reset(drv_data);
spi_finalize_current_transfer(drv_data->controller);
}
static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
{
- u32 irq_mask = (pxa2xx_spi_read(drv_data, SSCR1) & SSCR1_TIE) ?
- drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
+ u32 irq_status;
- u32 irq_status = pxa2xx_spi_read(drv_data, SSSR) & irq_mask;
+ irq_status = read_SSSR_bits(drv_data, drv_data->mask_sr);
+ if (!(pxa2xx_spi_read(drv_data, SSCR1) & SSCR1_TIE))
+ irq_status &= ~SSSR_TFS;
if (irq_status & SSSR_ROR) {
- int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
+ int_error_stop(drv_data, "interrupt_transfer: fifo overrun", -EIO);
return IRQ_HANDLED;
}
if (irq_status & SSSR_TUR) {
- int_error_stop(drv_data, "interrupt_transfer: fifo underrun");
+ int_error_stop(drv_data, "interrupt_transfer: fifo underrun", -EIO);
return IRQ_HANDLED;
}
@@ -727,8 +735,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
static void handle_bad_msg(struct driver_data *drv_data)
{
pxa2xx_spi_off(drv_data);
- pxa2xx_spi_write(drv_data, SSCR1,
- pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1);
+ clear_SSCR1_bits(drv_data, drv_data->int_cr1);
if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0);
write_SSSR_CS(drv_data, drv_data->clear_sr);
@@ -1081,42 +1088,40 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
dma_mapped ? "DMA" : "PIO");
if (is_lpss_ssp(drv_data)) {
- if ((pxa2xx_spi_read(drv_data, SSIRF) & 0xff)
- != chip->lpss_rx_threshold)
- pxa2xx_spi_write(drv_data, SSIRF,
- chip->lpss_rx_threshold);
- if ((pxa2xx_spi_read(drv_data, SSITF) & 0xffff)
- != chip->lpss_tx_threshold)
- pxa2xx_spi_write(drv_data, SSITF,
- chip->lpss_tx_threshold);
+ pxa2xx_spi_update(drv_data, SSIRF, GENMASK(7, 0), chip->lpss_rx_threshold);
+ pxa2xx_spi_update(drv_data, SSITF, GENMASK(15, 0), chip->lpss_tx_threshold);
}
- if (is_quark_x1000_ssp(drv_data) &&
- (pxa2xx_spi_read(drv_data, DDS_RATE) != chip->dds_rate))
- pxa2xx_spi_write(drv_data, DDS_RATE, chip->dds_rate);
+ if (is_mrfld_ssp(drv_data)) {
+ u32 thresh = 0;
- /* see if we need to reload the config registers */
- if ((pxa2xx_spi_read(drv_data, SSCR0) != cr0)
- || (pxa2xx_spi_read(drv_data, SSCR1) & change_mask)
- != (cr1 & change_mask)) {
- /* stop the SSP, and update the other bits */
- if (!is_mmp2_ssp(drv_data))
- pxa2xx_spi_write(drv_data, SSCR0, cr0 & ~SSCR0_SSE);
- if (!pxa25x_ssp_comp(drv_data))
- pxa2xx_spi_write(drv_data, SSTO, chip->timeout);
- /* first set CR1 without interrupt and service enables */
- pxa2xx_spi_write(drv_data, SSCR1, cr1 & change_mask);
- /* restart the SSP */
- pxa2xx_spi_write(drv_data, SSCR0, cr0);
+ thresh |= SFIFOTT_RxThresh(chip->lpss_rx_threshold);
+ thresh |= SFIFOTT_TxThresh(chip->lpss_tx_threshold);
- } else {
- if (!pxa25x_ssp_comp(drv_data))
- pxa2xx_spi_write(drv_data, SSTO, chip->timeout);
+ pxa2xx_spi_update(drv_data, SFIFOTT, 0xffffffff, thresh);
}
+ if (is_quark_x1000_ssp(drv_data))
+ pxa2xx_spi_update(drv_data, DDS_RATE, GENMASK(23, 0), chip->dds_rate);
+
+ /* Stop the SSP */
+ if (!is_mmp2_ssp(drv_data))
+ pxa_ssp_disable(drv_data->ssp);
+
+ if (!pxa25x_ssp_comp(drv_data))
+ pxa2xx_spi_write(drv_data, SSTO, chip->timeout);
+
+ /* first set CR1 without interrupt and service enables */
+ pxa2xx_spi_update(drv_data, SSCR1, change_mask, cr1);
+
+ /* see if we need to reload the config registers */
+ pxa2xx_spi_update(drv_data, SSCR0, GENMASK(31, 0), cr0);
+
+ /* Restart the SSP */
+ pxa_ssp_enable(drv_data->ssp);
+
if (is_mmp2_ssp(drv_data)) {
- u8 tx_level = (pxa2xx_spi_read(drv_data, SSSR)
- & SSSR_TFL_MASK) >> 8;
+ u8 tx_level = read_SSSR_bits(drv_data, SSSR_TFL_MASK) >> 8;
if (tx_level) {
/* On MMP2, flipping SSE doesn't to empty TXFIFO. */
@@ -1151,18 +1156,7 @@ static int pxa2xx_spi_slave_abort(struct spi_controller *controller)
{
struct driver_data *drv_data = spi_controller_get_devdata(controller);
- /* Stop and reset SSP */
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- reset_sccr1(drv_data);
- if (!pxa25x_ssp_comp(drv_data))
- pxa2xx_spi_write(drv_data, SSTO, 0);
- pxa2xx_spi_flush(drv_data);
- pxa2xx_spi_off(drv_data);
-
- dev_dbg(drv_data->ssp->dev, "transfer aborted\n");
-
- drv_data->controller->cur_msg->status = -EINTR;
- spi_finalize_current_transfer(drv_data->controller);
+ int_error_stop(drv_data, "transfer aborted", -EINTR);
return 0;
}
@@ -1176,9 +1170,7 @@ static void pxa2xx_spi_handle_err(struct spi_controller *controller,
pxa2xx_spi_off(drv_data);
/* Clear and disable interrupts and service requests */
write_SSSR_CS(drv_data, drv_data->clear_sr);
- pxa2xx_spi_write(drv_data, SSCR1,
- pxa2xx_spi_read(drv_data, SSCR1)
- & ~(drv_data->int_cr1 | drv_data->dma_cr1));
+ clear_SSCR1_bits(drv_data, drv_data->int_cr1 | drv_data->dma_cr1);
if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0);
@@ -1275,6 +1267,11 @@ static int setup(struct spi_device *spi)
tx_hi_thres = 0;
rx_thres = RX_THRESH_QUARK_X1000_DFLT;
break;
+ case MRFLD_SSP:
+ tx_thres = TX_THRESH_MRFLD_DFLT;
+ tx_hi_thres = 0;
+ rx_thres = RX_THRESH_MRFLD_DFLT;
+ break;
case CE4100_SSP:
tx_thres = TX_THRESH_CE4100_DFLT;
tx_hi_thres = 0;
@@ -1350,9 +1347,16 @@ static int setup(struct spi_device *spi)
chip->cr1 |= SSCR1_SPH;
}
- chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
- chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres)
- | SSITF_TxHiThresh(tx_hi_thres);
+ if (is_lpss_ssp(drv_data)) {
+ chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
+ chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres) |
+ SSITF_TxHiThresh(tx_hi_thres);
+ }
+
+ if (is_mrfld_ssp(drv_data)) {
+ chip->lpss_rx_threshold = rx_thres;
+ chip->lpss_tx_threshold = tx_thres;
+ }
/* set dma burst and threshold outside of chip_info path so that if
* chip_info goes away after setting chip->enable_dma, the
@@ -1794,8 +1798,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
controller->min_speed_hz =
DIV_ROUND_UP(controller->max_speed_hz, 512);
+ pxa_ssp_disable(ssp);
+
/* Load default SSP configuration */
- pxa2xx_spi_write(drv_data, SSCR0, 0);
switch (drv_data->ssp_type) {
case QUARK_X1000_SSP:
tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT) |
@@ -1936,7 +1941,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
spi_unregister_controller(drv_data->controller);
/* Disable the SSP at the peripheral and SOC level */
- pxa2xx_spi_write(drv_data, SSCR0, 0);
+ pxa_ssp_disable(ssp);
clk_disable_unprepare(ssp->clk);
/* Release DMA */
@@ -1965,7 +1970,8 @@ static int pxa2xx_spi_suspend(struct device *dev)
status = spi_controller_suspend(drv_data->controller);
if (status != 0)
return status;
- pxa2xx_spi_write(drv_data, SSCR0, 0);
+
+ pxa_ssp_disable(ssp);
if (!pm_runtime_suspended(dev))
clk_disable_unprepare(ssp->clk);
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 739e264feaa6..5c6a5e0f249e 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -93,7 +93,7 @@ static inline void pxa2xx_spi_write(const struct driver_data *drv_data, u32 reg,
#define DMA_ALIGNMENT 8
-static inline int pxa25x_ssp_comp(struct driver_data *drv_data)
+static inline int pxa25x_ssp_comp(const struct driver_data *drv_data)
{
switch (drv_data->ssp_type) {
case PXA25x_SSP:
@@ -105,11 +105,21 @@ static inline int pxa25x_ssp_comp(struct driver_data *drv_data)
}
}
-static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val)
+static inline void clear_SSCR1_bits(const struct driver_data *drv_data, u32 bits)
+{
+ pxa2xx_spi_write(drv_data, SSCR1, pxa2xx_spi_read(drv_data, SSCR1) & ~bits);
+}
+
+static inline u32 read_SSSR_bits(const struct driver_data *drv_data, u32 bits)
+{
+ return pxa2xx_spi_read(drv_data, SSSR) & bits;
+}
+
+static inline void write_SSSR_CS(const struct driver_data *drv_data, u32 val)
{
if (drv_data->ssp_type == CE4100_SSP ||
drv_data->ssp_type == QUARK_X1000_SSP)
- val |= pxa2xx_spi_read(drv_data, SSSR) & SSSR_ALT_FRM_MASK;
+ val |= read_SSSR_bits(drv_data, SSSR_ALT_FRM_MASK);
pxa2xx_spi_write(drv_data, SSSR, val);
}