Commit 6e5c3ab8 authored by Mark Brown's avatar Mark Brown

Merge series "spi: pxa2xx: Set of cleanups" from Andy Shevchenko...

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
parents 532259bf 3fdb59cf
...@@ -34,25 +34,18 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, ...@@ -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 * might not know about the error yet. So we re-check the
* ROR bit here before we clear the status register. * ROR bit here before we clear the status register.
*/ */
if (!error) { if (!error)
u32 status = pxa2xx_spi_read(drv_data, SSSR) error = read_SSSR_bits(drv_data, drv_data->mask_sr) & SSSR_ROR;
& drv_data->mask_sr;
error = status & SSSR_ROR;
}
/* Clear status & disable interrupts */ /* Clear status & disable interrupts */
pxa2xx_spi_write(drv_data, SSCR1, clear_SSCR1_bits(drv_data, drv_data->dma_cr1);
pxa2xx_spi_read(drv_data, SSCR1)
& ~drv_data->dma_cr1);
write_SSSR_CS(drv_data, drv_data->clear_sr); write_SSSR_CS(drv_data, drv_data->clear_sr);
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_write(drv_data, SSTO, 0);
if (error) { if (error) {
/* In case we got an error we disable the SSP now */ /* In case we got an error we disable the SSP now */
pxa2xx_spi_write(drv_data, SSCR0, pxa_ssp_disable(drv_data->ssp);
pxa2xx_spi_read(drv_data, SSCR0)
& ~SSCR0_SSE);
msg->status = -EIO; msg->status = -EIO;
} }
...@@ -123,7 +116,7 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data) ...@@ -123,7 +116,7 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
{ {
u32 status; 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) { if (status & SSSR_ROR) {
dev_err(drv_data->ssp->dev, "FIFO overrun\n"); dev_err(drv_data->ssp->dev, "FIFO overrun\n");
......
...@@ -179,7 +179,7 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -179,7 +179,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.rx_param = &bsw2_rx_param, .rx_param = &bsw2_rx_param,
}, },
[PORT_MRFLD] = { [PORT_MRFLD] = {
.type = PXA27x_SSP, .type = MRFLD_SSP,
.max_clk_rate = 25000000, .max_clk_rate = 25000000,
.setup = mrfld_spi_setup, .setup = mrfld_spi_setup,
}, },
......
...@@ -200,6 +200,17 @@ static bool is_mmp2_ssp(const struct driver_data *drv_data) ...@@ -200,6 +200,17 @@ static bool is_mmp2_ssp(const struct driver_data *drv_data)
return drv_data->ssp_type == MMP2_SSP; 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) static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data)
{ {
switch (drv_data->ssp_type) { switch (drv_data->ssp_type) {
...@@ -241,7 +252,7 @@ static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data) ...@@ -241,7 +252,7 @@ static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data)
break; 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, 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, ...@@ -286,13 +297,11 @@ static u32 pxa2xx_configure_sscr0(const struct driver_data *drv_data,
case QUARK_X1000_SSP: case QUARK_X1000_SSP:
return clk_div return clk_div
| QUARK_X1000_SSCR0_Motorola | QUARK_X1000_SSCR0_Motorola
| QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits) | QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits);
| SSCR0_SSE;
default: default:
return clk_div return clk_div
| SSCR0_Motorola | SSCR0_Motorola
| SSCR0_DataSize(bits > 16 ? bits - 16 : bits) | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
| SSCR0_SSE
| (bits > 16 ? SSCR0_EDSS : 0); | (bits > 16 ? SSCR0_EDSS : 0);
} }
} }
...@@ -484,7 +493,7 @@ int pxa2xx_spi_flush(struct driver_data *drv_data) ...@@ -484,7 +493,7 @@ int pxa2xx_spi_flush(struct driver_data *drv_data)
unsigned long limit = loops_per_jiffy << 1; unsigned long limit = loops_per_jiffy << 1;
do { do {
while (pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE) while (read_SSSR_bits(drv_data, SSSR_RNE))
pxa2xx_spi_read(drv_data, SSDR); pxa2xx_spi_read(drv_data, SSDR);
} while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY) && --limit); } while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY) && --limit);
write_SSSR_CS(drv_data, SSSR_ROR); write_SSSR_CS(drv_data, SSSR_ROR);
...@@ -498,8 +507,7 @@ static void pxa2xx_spi_off(struct driver_data *drv_data) ...@@ -498,8 +507,7 @@ static void pxa2xx_spi_off(struct driver_data *drv_data)
if (is_mmp2_ssp(drv_data)) if (is_mmp2_ssp(drv_data))
return; return;
pxa2xx_spi_write(drv_data, SSCR0, pxa_ssp_disable(drv_data->ssp);
pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
} }
static int null_writer(struct driver_data *drv_data) static int null_writer(struct driver_data *drv_data)
...@@ -520,8 +528,7 @@ static int null_reader(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; u8 n_bytes = drv_data->n_bytes;
while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE) while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
&& (drv_data->rx < drv_data->rx_end)) {
pxa2xx_spi_read(drv_data, SSDR); pxa2xx_spi_read(drv_data, SSDR);
drv_data->rx += n_bytes; drv_data->rx += n_bytes;
} }
...@@ -543,8 +550,7 @@ static int u8_writer(struct driver_data *drv_data) ...@@ -543,8 +550,7 @@ static int u8_writer(struct driver_data *drv_data)
static int u8_reader(struct driver_data *drv_data) static int u8_reader(struct driver_data *drv_data)
{ {
while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE) while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
&& (drv_data->rx < drv_data->rx_end)) {
*(u8 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR); *(u8 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR);
++drv_data->rx; ++drv_data->rx;
} }
...@@ -566,8 +572,7 @@ static int u16_writer(struct driver_data *drv_data) ...@@ -566,8 +572,7 @@ static int u16_writer(struct driver_data *drv_data)
static int u16_reader(struct driver_data *drv_data) static int u16_reader(struct driver_data *drv_data)
{ {
while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE) while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
&& (drv_data->rx < drv_data->rx_end)) {
*(u16 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR); *(u16 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR);
drv_data->rx += 2; drv_data->rx += 2;
} }
...@@ -589,8 +594,7 @@ static int u32_writer(struct driver_data *drv_data) ...@@ -589,8 +594,7 @@ static int u32_writer(struct driver_data *drv_data)
static int u32_reader(struct driver_data *drv_data) static int u32_reader(struct driver_data *drv_data)
{ {
while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_RNE) while (read_SSSR_bits(drv_data, SSSR_RNE) && drv_data->rx < drv_data->rx_end) {
&& (drv_data->rx < drv_data->rx_end)) {
*(u32 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR); *(u32 *)(drv_data->rx) = pxa2xx_spi_read(drv_data, SSDR);
drv_data->rx += 4; drv_data->rx += 4;
} }
...@@ -620,47 +624,51 @@ static void reset_sccr1(struct driver_data *drv_data) ...@@ -620,47 +624,51 @@ static void reset_sccr1(struct driver_data *drv_data)
pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg); 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); write_SSSR_CS(drv_data, drv_data->clear_sr);
reset_sccr1(drv_data); reset_sccr1(drv_data);
if (!pxa25x_ssp_comp(drv_data)) if (pxa25x_ssp_comp(drv_data))
return;
pxa2xx_spi_write(drv_data, SSTO, 0); 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_flush(drv_data);
pxa2xx_spi_off(drv_data); pxa2xx_spi_off(drv_data);
dev_err(drv_data->ssp->dev, "%s\n", msg); 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); spi_finalize_current_transfer(drv_data->controller);
} }
static void int_transfer_complete(struct driver_data *drv_data) static void int_transfer_complete(struct driver_data *drv_data)
{ {
/* Clear and disable interrupts */ int_stop_and_reset(drv_data);
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);
spi_finalize_current_transfer(drv_data->controller); spi_finalize_current_transfer(drv_data->controller);
} }
static irqreturn_t interrupt_transfer(struct driver_data *drv_data) static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
{ {
u32 irq_mask = (pxa2xx_spi_read(drv_data, SSCR1) & SSCR1_TIE) ? u32 irq_status;
drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
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) { 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; return IRQ_HANDLED;
} }
if (irq_status & SSSR_TUR) { 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; return IRQ_HANDLED;
} }
...@@ -727,8 +735,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) ...@@ -727,8 +735,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
static void handle_bad_msg(struct driver_data *drv_data) static void handle_bad_msg(struct driver_data *drv_data)
{ {
pxa2xx_spi_off(drv_data); pxa2xx_spi_off(drv_data);
pxa2xx_spi_write(drv_data, SSCR1, clear_SSCR1_bits(drv_data, drv_data->int_cr1);
pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1);
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_write(drv_data, SSTO, 0);
write_SSSR_CS(drv_data, drv_data->clear_sr); write_SSSR_CS(drv_data, drv_data->clear_sr);
...@@ -1081,42 +1088,40 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller, ...@@ -1081,42 +1088,40 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
dma_mapped ? "DMA" : "PIO"); dma_mapped ? "DMA" : "PIO");
if (is_lpss_ssp(drv_data)) { if (is_lpss_ssp(drv_data)) {
if ((pxa2xx_spi_read(drv_data, SSIRF) & 0xff) pxa2xx_spi_update(drv_data, SSIRF, GENMASK(7, 0), chip->lpss_rx_threshold);
!= chip->lpss_rx_threshold) pxa2xx_spi_update(drv_data, SSITF, GENMASK(15, 0), chip->lpss_tx_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);
} }
if (is_quark_x1000_ssp(drv_data) && if (is_mrfld_ssp(drv_data)) {
(pxa2xx_spi_read(drv_data, DDS_RATE) != chip->dds_rate)) u32 thresh = 0;
pxa2xx_spi_write(drv_data, DDS_RATE, chip->dds_rate);
/* see if we need to reload the config registers */ thresh |= SFIFOTT_RxThresh(chip->lpss_rx_threshold);
if ((pxa2xx_spi_read(drv_data, SSCR0) != cr0) thresh |= SFIFOTT_TxThresh(chip->lpss_tx_threshold);
|| (pxa2xx_spi_read(drv_data, SSCR1) & change_mask)
!= (cr1 & change_mask)) { pxa2xx_spi_update(drv_data, SFIFOTT, 0xffffffff, thresh);
/* stop the SSP, and update the other bits */ }
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)) if (!is_mmp2_ssp(drv_data))
pxa2xx_spi_write(drv_data, SSCR0, cr0 & ~SSCR0_SSE); pxa_ssp_disable(drv_data->ssp);
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, chip->timeout); pxa2xx_spi_write(drv_data, SSTO, chip->timeout);
/* first set CR1 without interrupt and service enables */ /* first set CR1 without interrupt and service enables */
pxa2xx_spi_write(drv_data, SSCR1, cr1 & change_mask); pxa2xx_spi_update(drv_data, SSCR1, change_mask, cr1);
/* restart the SSP */
pxa2xx_spi_write(drv_data, SSCR0, cr0);
} else { /* see if we need to reload the config registers */
if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_update(drv_data, SSCR0, GENMASK(31, 0), cr0);
pxa2xx_spi_write(drv_data, SSTO, chip->timeout);
} /* Restart the SSP */
pxa_ssp_enable(drv_data->ssp);
if (is_mmp2_ssp(drv_data)) { if (is_mmp2_ssp(drv_data)) {
u8 tx_level = (pxa2xx_spi_read(drv_data, SSSR) u8 tx_level = read_SSSR_bits(drv_data, SSSR_TFL_MASK) >> 8;
& SSSR_TFL_MASK) >> 8;
if (tx_level) { if (tx_level) {
/* On MMP2, flipping SSE doesn't to empty TXFIFO. */ /* On MMP2, flipping SSE doesn't to empty TXFIFO. */
...@@ -1151,18 +1156,7 @@ static int pxa2xx_spi_slave_abort(struct spi_controller *controller) ...@@ -1151,18 +1156,7 @@ static int pxa2xx_spi_slave_abort(struct spi_controller *controller)
{ {
struct driver_data *drv_data = spi_controller_get_devdata(controller); struct driver_data *drv_data = spi_controller_get_devdata(controller);
/* Stop and reset SSP */ int_error_stop(drv_data, "transfer aborted", -EINTR);
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);
return 0; return 0;
} }
...@@ -1176,9 +1170,7 @@ static void pxa2xx_spi_handle_err(struct spi_controller *controller, ...@@ -1176,9 +1170,7 @@ static void pxa2xx_spi_handle_err(struct spi_controller *controller,
pxa2xx_spi_off(drv_data); pxa2xx_spi_off(drv_data);
/* Clear and disable interrupts and service requests */ /* Clear and disable interrupts and service requests */
write_SSSR_CS(drv_data, drv_data->clear_sr); write_SSSR_CS(drv_data, drv_data->clear_sr);
pxa2xx_spi_write(drv_data, SSCR1, clear_SSCR1_bits(drv_data, drv_data->int_cr1 | drv_data->dma_cr1);
pxa2xx_spi_read(drv_data, SSCR1)
& ~(drv_data->int_cr1 | drv_data->dma_cr1));
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_write(drv_data, SSTO, 0);
...@@ -1275,6 +1267,11 @@ static int setup(struct spi_device *spi) ...@@ -1275,6 +1267,11 @@ static int setup(struct spi_device *spi)
tx_hi_thres = 0; tx_hi_thres = 0;
rx_thres = RX_THRESH_QUARK_X1000_DFLT; rx_thres = RX_THRESH_QUARK_X1000_DFLT;
break; break;
case MRFLD_SSP:
tx_thres = TX_THRESH_MRFLD_DFLT;
tx_hi_thres = 0;
rx_thres = RX_THRESH_MRFLD_DFLT;
break;
case CE4100_SSP: case CE4100_SSP:
tx_thres = TX_THRESH_CE4100_DFLT; tx_thres = TX_THRESH_CE4100_DFLT;
tx_hi_thres = 0; tx_hi_thres = 0;
...@@ -1350,9 +1347,16 @@ static int setup(struct spi_device *spi) ...@@ -1350,9 +1347,16 @@ static int setup(struct spi_device *spi)
chip->cr1 |= SSCR1_SPH; chip->cr1 |= SSCR1_SPH;
} }
if (is_lpss_ssp(drv_data)) {
chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres); chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres) chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres) |
| SSITF_TxHiThresh(tx_hi_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 /* set dma burst and threshold outside of chip_info path so that if
* chip_info goes away after setting chip->enable_dma, the * chip_info goes away after setting chip->enable_dma, the
...@@ -1794,8 +1798,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1794,8 +1798,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
controller->min_speed_hz = controller->min_speed_hz =
DIV_ROUND_UP(controller->max_speed_hz, 512); DIV_ROUND_UP(controller->max_speed_hz, 512);
pxa_ssp_disable(ssp);
/* Load default SSP configuration */ /* Load default SSP configuration */
pxa2xx_spi_write(drv_data, SSCR0, 0);
switch (drv_data->ssp_type) { switch (drv_data->ssp_type) {
case QUARK_X1000_SSP: case QUARK_X1000_SSP:
tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT) | tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT) |
...@@ -1936,7 +1941,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) ...@@ -1936,7 +1941,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
spi_unregister_controller(drv_data->controller); spi_unregister_controller(drv_data->controller);
/* Disable the SSP at the peripheral and SOC level */ /* 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); clk_disable_unprepare(ssp->clk);
/* Release DMA */ /* Release DMA */
...@@ -1965,7 +1970,8 @@ static int pxa2xx_spi_suspend(struct device *dev) ...@@ -1965,7 +1970,8 @@ static int pxa2xx_spi_suspend(struct device *dev)
status = spi_controller_suspend(drv_data->controller); status = spi_controller_suspend(drv_data->controller);
if (status != 0) if (status != 0)
return status; return status;
pxa2xx_spi_write(drv_data, SSCR0, 0);
pxa_ssp_disable(ssp);
if (!pm_runtime_suspended(dev)) if (!pm_runtime_suspended(dev))
clk_disable_unprepare(ssp->clk); clk_disable_unprepare(ssp->clk);
......
...@@ -93,7 +93,7 @@ static inline void pxa2xx_spi_write(const struct driver_data *drv_data, u32 reg, ...@@ -93,7 +93,7 @@ static inline void pxa2xx_spi_write(const struct driver_data *drv_data, u32 reg,
#define DMA_ALIGNMENT 8 #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) { switch (drv_data->ssp_type) {
case PXA25x_SSP: case PXA25x_SSP:
...@@ -105,11 +105,21 @@ static inline int pxa25x_ssp_comp(struct driver_data *drv_data) ...@@ -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 || if (drv_data->ssp_type == CE4100_SSP ||
drv_data->ssp_type == QUARK_X1000_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); pxa2xx_spi_write(drv_data, SSSR, val);
} }
......
...@@ -183,6 +183,21 @@ struct device_node; ...@@ -183,6 +183,21 @@ struct device_node;
#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */ #define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */
#define SSACD_SCDX8 BIT(7) /* SYSCLK division ratio select */ #define SSACD_SCDX8 BIT(7) /* SYSCLK division ratio select */
/* Intel Merrifield SSP */
#define SFIFOL 0x68 /* FIFO level */
#define SFIFOTT 0x6c /* FIFO trigger threshold */
#define RX_THRESH_MRFLD_DFLT 16
#define TX_THRESH_MRFLD_DFLT 16
#define SFIFOL_TFL_MASK GENMASK(15, 0) /* Transmit FIFO Level mask */
#define SFIFOL_RFL_MASK GENMASK(31, 16) /* Receive FIFO Level mask */
#define SFIFOTT_TFT GENMASK(15, 0) /* Transmit FIFO Threshold (mask) */
#define SFIFOTT_TxThresh(x) (((x) - 1) << 0) /* TX FIFO trigger threshold / level */
#define SFIFOTT_RFT GENMASK(31, 16) /* Receive FIFO Threshold (mask) */
#define SFIFOTT_RxThresh(x) (((x) - 1) << 16) /* RX FIFO trigger threshold / level */
/* LPSS SSP */ /* LPSS SSP */
#define SSITF 0x44 /* TX FIFO trigger level */ #define SSITF 0x44 /* TX FIFO trigger level */
#define SSITF_TxHiThresh(x) (((x) - 1) << 0) #define SSITF_TxHiThresh(x) (((x) - 1) << 0)
...@@ -205,6 +220,7 @@ enum pxa_ssp_type { ...@@ -205,6 +220,7 @@ enum pxa_ssp_type {
MMP2_SSP, MMP2_SSP,
PXA910_SSP, PXA910_SSP,
CE4100_SSP, CE4100_SSP,
MRFLD_SSP,
QUARK_X1000_SSP, QUARK_X1000_SSP,
LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */ LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
LPSS_BYT_SSP, LPSS_BYT_SSP,
...@@ -254,6 +270,22 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg) ...@@ -254,6 +270,22 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
return __raw_readl(dev->mmio_base + reg); return __raw_readl(dev->mmio_base + reg);
} }
static inline void pxa_ssp_enable(struct ssp_device *ssp)
{
u32 sscr0;
sscr0 = pxa_ssp_read_reg(ssp, SSCR0) | SSCR0_SSE;
pxa_ssp_write_reg(ssp, SSCR0, sscr0);
}
static inline void pxa_ssp_disable(struct ssp_device *ssp)
{
u32 sscr0;
sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~SSCR0_SSE;
pxa_ssp_write_reg(ssp, SSCR0, sscr0);
}
#if IS_ENABLED(CONFIG_PXA_SSP) #if IS_ENABLED(CONFIG_PXA_SSP)
struct ssp_device *pxa_ssp_request(int port, const char *label); struct ssp_device *pxa_ssp_request(int port, const char *label);
void pxa_ssp_free(struct ssp_device *); void pxa_ssp_free(struct ssp_device *);
......
...@@ -61,22 +61,6 @@ static void dump_registers(struct ssp_device *ssp) ...@@ -61,22 +61,6 @@ static void dump_registers(struct ssp_device *ssp)
pxa_ssp_read_reg(ssp, SSACD)); pxa_ssp_read_reg(ssp, SSACD));
} }
static void pxa_ssp_enable(struct ssp_device *ssp)
{
uint32_t sscr0;
sscr0 = __raw_readl(ssp->mmio_base + SSCR0) | SSCR0_SSE;
__raw_writel(sscr0, ssp->mmio_base + SSCR0);
}
static void pxa_ssp_disable(struct ssp_device *ssp)
{
uint32_t sscr0;
sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SSE;
__raw_writel(sscr0, ssp->mmio_base + SSCR0);
}
static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4, static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4,
int out, struct snd_dmaengine_dai_dma_data *dma) int out, struct snd_dmaengine_dai_dma_data *dma)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment