Commit 4fdb2424 authored by Weike Chen's avatar Weike Chen Committed by Mark Brown

spi: spi-pxa2xx: Add helpers for regiseters' accessing

There are several registers for SPI, and the registers of 'SSCR0' and 'SSCR1'
are accessed frequently. This path is to introduce helper functions to
simplify the accessing of 'SSCR0' and 'SSCR1'.
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: default avatarWeike Chen <alvin.chen@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 5d01410f
...@@ -80,6 +80,73 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) ...@@ -80,6 +80,73 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
return drv_data->ssp_type == LPSS_SSP; return drv_data->ssp_type == LPSS_SSP;
} }
static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data)
{
switch (drv_data->ssp_type) {
default:
return SSCR1_CHANGE_MASK;
}
}
static u32
pxa2xx_spi_get_rx_default_thre(const struct driver_data *drv_data)
{
switch (drv_data->ssp_type) {
default:
return RX_THRESH_DFLT;
}
}
static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
u32 mask;
switch (drv_data->ssp_type) {
default:
mask = SSSR_TFL_MASK;
break;
}
return (read_SSSR(reg) & mask) == mask;
}
static void pxa2xx_spi_clear_rx_thre(const struct driver_data *drv_data,
u32 *sccr1_reg)
{
u32 mask;
switch (drv_data->ssp_type) {
default:
mask = SSCR1_RFT;
break;
}
*sccr1_reg &= ~mask;
}
static void pxa2xx_spi_set_rx_thre(const struct driver_data *drv_data,
u32 *sccr1_reg, u32 threshold)
{
switch (drv_data->ssp_type) {
default:
*sccr1_reg |= SSCR1_RxTresh(threshold);
break;
}
}
static u32 pxa2xx_configure_sscr0(const struct driver_data *drv_data,
u32 clk_div, u8 bits)
{
switch (drv_data->ssp_type) {
default:
return clk_div
| SSCR0_Motorola
| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
| SSCR0_SSE
| (bits > 16 ? SSCR0_EDSS : 0);
}
}
/* /*
* Read and write LPSS SSP private registers. Caller must first check that * Read and write LPSS SSP private registers. Caller must first check that
* is_lpss_ssp() returns true before these can be called. * is_lpss_ssp() returns true before these can be called.
...@@ -234,7 +301,7 @@ static int null_writer(struct driver_data *drv_data) ...@@ -234,7 +301,7 @@ static int null_writer(struct driver_data *drv_data)
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
u8 n_bytes = drv_data->n_bytes; u8 n_bytes = drv_data->n_bytes;
if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) if (pxa2xx_spi_txfifo_full(drv_data)
|| (drv_data->tx == drv_data->tx_end)) || (drv_data->tx == drv_data->tx_end))
return 0; return 0;
...@@ -262,7 +329,7 @@ static int u8_writer(struct driver_data *drv_data) ...@@ -262,7 +329,7 @@ static int u8_writer(struct driver_data *drv_data)
{ {
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) if (pxa2xx_spi_txfifo_full(drv_data)
|| (drv_data->tx == drv_data->tx_end)) || (drv_data->tx == drv_data->tx_end))
return 0; return 0;
...@@ -289,7 +356,7 @@ static int u16_writer(struct driver_data *drv_data) ...@@ -289,7 +356,7 @@ static int u16_writer(struct driver_data *drv_data)
{ {
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) if (pxa2xx_spi_txfifo_full(drv_data)
|| (drv_data->tx == drv_data->tx_end)) || (drv_data->tx == drv_data->tx_end))
return 0; return 0;
...@@ -316,7 +383,7 @@ static int u32_writer(struct driver_data *drv_data) ...@@ -316,7 +383,7 @@ static int u32_writer(struct driver_data *drv_data)
{ {
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) if (pxa2xx_spi_txfifo_full(drv_data)
|| (drv_data->tx == drv_data->tx_end)) || (drv_data->tx == drv_data->tx_end))
return 0; return 0;
...@@ -508,8 +575,9 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) ...@@ -508,8 +575,9 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
* remaining RX bytes. * remaining RX bytes.
*/ */
if (pxa25x_ssp_comp(drv_data)) { if (pxa25x_ssp_comp(drv_data)) {
u32 rx_thre;
sccr1_reg &= ~SSCR1_RFT; pxa2xx_spi_clear_rx_thre(drv_data, &sccr1_reg);
bytes_left = drv_data->rx_end - drv_data->rx; bytes_left = drv_data->rx_end - drv_data->rx;
switch (drv_data->n_bytes) { switch (drv_data->n_bytes) {
...@@ -519,10 +587,11 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) ...@@ -519,10 +587,11 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
bytes_left >>= 1; bytes_left >>= 1;
} }
if (bytes_left > RX_THRESH_DFLT) rx_thre = pxa2xx_spi_get_rx_default_thre(drv_data);
bytes_left = RX_THRESH_DFLT; if (rx_thre > bytes_left)
rx_thre = bytes_left;
sccr1_reg |= SSCR1_RxTresh(bytes_left); pxa2xx_spi_set_rx_thre(drv_data, &sccr1_reg, rx_thre);
} }
write_SSCR1(sccr1_reg, reg); write_SSCR1(sccr1_reg, reg);
} }
...@@ -613,6 +682,7 @@ static void pump_transfers(unsigned long data) ...@@ -613,6 +682,7 @@ static void pump_transfers(unsigned long data)
u32 cr1; u32 cr1;
u32 dma_thresh = drv_data->cur_chip->dma_threshold; u32 dma_thresh = drv_data->cur_chip->dma_threshold;
u32 dma_burst = drv_data->cur_chip->dma_burst_size; u32 dma_burst = drv_data->cur_chip->dma_burst_size;
u32 change_mask = pxa2xx_spi_get_ssrc1_change_mask(drv_data);
/* Get current state information */ /* Get current state information */
message = drv_data->cur_msg; message = drv_data->cur_msg;
...@@ -731,11 +801,7 @@ static void pump_transfers(unsigned long data) ...@@ -731,11 +801,7 @@ static void pump_transfers(unsigned long data)
"pump_transfers: DMA burst size reduced to match bits_per_word\n"); "pump_transfers: DMA burst size reduced to match bits_per_word\n");
} }
cr0 = clk_div cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
| SSCR0_Motorola
| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
| SSCR0_SSE
| (bits > 16 ? SSCR0_EDSS : 0);
} }
message->state = RUNNING_STATE; message->state = RUNNING_STATE;
...@@ -772,16 +838,15 @@ static void pump_transfers(unsigned long data) ...@@ -772,16 +838,15 @@ static void pump_transfers(unsigned long data)
} }
/* see if we need to reload the config registers */ /* see if we need to reload the config registers */
if ((read_SSCR0(reg) != cr0) if ((read_SSCR0(reg) != cr0) ||
|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) != (read_SSCR1(reg) & change_mask) != (cr1 & change_mask)) {
(cr1 & SSCR1_CHANGE_MASK)) {
/* stop the SSP, and update the other bits */ /* stop the SSP, and update the other bits */
write_SSCR0(cr0 & ~SSCR0_SSE, reg); write_SSCR0(cr0 & ~SSCR0_SSE, reg);
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
write_SSTO(chip->timeout, reg); write_SSTO(chip->timeout, reg);
/* first set CR1 without interrupt and service enables */ /* first set CR1 without interrupt and service enables */
write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg); write_SSCR1(cr1 & change_mask, reg);
/* restart the SSP */ /* restart the SSP */
write_SSCR0(cr0, reg); write_SSCR0(cr0, reg);
...@@ -959,12 +1024,8 @@ static int setup(struct spi_device *spi) ...@@ -959,12 +1024,8 @@ static int setup(struct spi_device *spi)
clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz); clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
chip->speed_hz = spi->max_speed_hz; chip->speed_hz = spi->max_speed_hz;
chip->cr0 = clk_div chip->cr0 = pxa2xx_configure_sscr0(drv_data, clk_div,
| SSCR0_Motorola spi->bits_per_word);
| SSCR0_DataSize(spi->bits_per_word > 16 ?
spi->bits_per_word - 16 : spi->bits_per_word)
| SSCR0_SSE
| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH); chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0) chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
......
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