|
@@ -1595,12 +1595,6 @@ static int destroy_queue(struct pl022 *pl022)
|
|
|
static int verify_controller_parameters(struct pl022 *pl022,
|
|
|
struct pl022_config_chip *chip_info)
|
|
|
{
|
|
|
- if ((chip_info->lbm != LOOPBACK_ENABLED)
|
|
|
- && (chip_info->lbm != LOOPBACK_DISABLED)) {
|
|
|
- dev_err(chip_info->dev,
|
|
|
- "loopback Mode is configured incorrectly\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
|
|
|
|| (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
|
|
|
dev_err(chip_info->dev,
|
|
@@ -1626,24 +1620,6 @@ static int verify_controller_parameters(struct pl022 *pl022,
|
|
|
"cpsdvsr is configured incorrectly\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- if ((chip_info->endian_rx != SSP_RX_MSB)
|
|
|
- && (chip_info->endian_rx != SSP_RX_LSB)) {
|
|
|
- dev_err(chip_info->dev,
|
|
|
- "RX FIFO endianess is configured incorrectly\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- if ((chip_info->endian_tx != SSP_TX_MSB)
|
|
|
- && (chip_info->endian_tx != SSP_TX_LSB)) {
|
|
|
- dev_err(chip_info->dev,
|
|
|
- "TX FIFO endianess is configured incorrectly\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- if ((chip_info->data_size < SSP_DATA_BITS_4)
|
|
|
- || (chip_info->data_size > SSP_DATA_BITS_32)) {
|
|
|
- dev_err(chip_info->dev,
|
|
|
- "DATA Size is configured incorrectly\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
if ((chip_info->com_mode != INTERRUPT_TRANSFER)
|
|
|
&& (chip_info->com_mode != DMA_TRANSFER)
|
|
|
&& (chip_info->com_mode != POLLING_TRANSFER)) {
|
|
@@ -1663,20 +1639,6 @@ static int verify_controller_parameters(struct pl022 *pl022,
|
|
|
"TX FIFO Trigger Level is configured incorrectly\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- if (chip_info->iface == SSP_INTERFACE_MOTOROLA_SPI) {
|
|
|
- if ((chip_info->clk_phase != SSP_CLK_FIRST_EDGE)
|
|
|
- && (chip_info->clk_phase != SSP_CLK_SECOND_EDGE)) {
|
|
|
- dev_err(chip_info->dev,
|
|
|
- "Clock Phase is configured incorrectly\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- if ((chip_info->clk_pol != SSP_CLK_POL_IDLE_LOW)
|
|
|
- && (chip_info->clk_pol != SSP_CLK_POL_IDLE_HIGH)) {
|
|
|
- dev_err(chip_info->dev,
|
|
|
- "Clock Polarity is configured incorrectly\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- }
|
|
|
if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
|
|
|
if ((chip_info->ctrl_len < SSP_BITS_4)
|
|
|
|| (chip_info->ctrl_len > SSP_BITS_32)) {
|
|
@@ -1825,23 +1787,14 @@ static int calculate_effective_freq(struct pl022 *pl022,
|
|
|
* controller hardware here, that is not done until the actual transfer
|
|
|
* commence.
|
|
|
*/
|
|
|
-
|
|
|
-/* FIXME: JUST GUESSING the spi->mode bits understood by this driver */
|
|
|
-#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
|
|
|
- | SPI_LSB_FIRST | SPI_LOOP)
|
|
|
-
|
|
|
static int pl022_setup(struct spi_device *spi)
|
|
|
{
|
|
|
struct pl022_config_chip *chip_info;
|
|
|
struct chip_data *chip;
|
|
|
int status = 0;
|
|
|
struct pl022 *pl022 = spi_master_get_devdata(spi->master);
|
|
|
-
|
|
|
- if (spi->mode & ~MODEBITS) {
|
|
|
- dev_dbg(&spi->dev, "unsupported mode bits %x\n",
|
|
|
- spi->mode & ~MODEBITS);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
+ unsigned int bits = spi->bits_per_word;
|
|
|
+ u32 tmp;
|
|
|
|
|
|
if (!spi->max_speed_hz)
|
|
|
return -EINVAL;
|
|
@@ -1884,18 +1837,12 @@ static int pl022_setup(struct spi_device *spi)
|
|
|
* Set controller data default values:
|
|
|
* Polling is supported by default
|
|
|
*/
|
|
|
- chip_info->lbm = LOOPBACK_DISABLED;
|
|
|
chip_info->com_mode = POLLING_TRANSFER;
|
|
|
chip_info->iface = SSP_INTERFACE_MOTOROLA_SPI;
|
|
|
chip_info->hierarchy = SSP_SLAVE;
|
|
|
chip_info->slave_tx_disable = DO_NOT_DRIVE_TX;
|
|
|
- chip_info->endian_tx = SSP_TX_LSB;
|
|
|
- chip_info->endian_rx = SSP_RX_LSB;
|
|
|
- chip_info->data_size = SSP_DATA_BITS_12;
|
|
|
chip_info->rx_lev_trig = SSP_RX_1_OR_MORE_ELEM;
|
|
|
chip_info->tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC;
|
|
|
- chip_info->clk_phase = SSP_CLK_SECOND_EDGE;
|
|
|
- chip_info->clk_pol = SSP_CLK_POL_IDLE_LOW;
|
|
|
chip_info->ctrl_len = SSP_BITS_8;
|
|
|
chip_info->wait_state = SSP_MWIRE_WAIT_ZERO;
|
|
|
chip_info->duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX;
|
|
@@ -1933,12 +1880,16 @@ static int pl022_setup(struct spi_device *spi)
|
|
|
chip->xfer_type = chip_info->com_mode;
|
|
|
chip->cs_control = chip_info->cs_control;
|
|
|
|
|
|
- if (chip_info->data_size <= 8) {
|
|
|
- dev_dbg(&spi->dev, "1 <= n <=8 bits per word\n");
|
|
|
+ if (bits <= 3) {
|
|
|
+ /* PL022 doesn't support less than 4-bits */
|
|
|
+ status = -ENOTSUPP;
|
|
|
+ goto err_config_params;
|
|
|
+ } else if (bits <= 8) {
|
|
|
+ dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
|
|
|
chip->n_bytes = 1;
|
|
|
chip->read = READING_U8;
|
|
|
chip->write = WRITING_U8;
|
|
|
- } else if (chip_info->data_size <= 16) {
|
|
|
+ } else if (bits <= 16) {
|
|
|
dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n");
|
|
|
chip->n_bytes = 2;
|
|
|
chip->read = READING_U16;
|
|
@@ -1955,6 +1906,7 @@ static int pl022_setup(struct spi_device *spi)
|
|
|
dev_err(&spi->dev,
|
|
|
"a standard pl022 can only handle "
|
|
|
"1 <= n <= 16 bit words\n");
|
|
|
+ status = -ENOTSUPP;
|
|
|
goto err_config_params;
|
|
|
}
|
|
|
}
|
|
@@ -1987,6 +1939,8 @@ static int pl022_setup(struct spi_device *spi)
|
|
|
|
|
|
/* Special setup for the ST micro extended control registers */
|
|
|
if (pl022->vendor->extended_cr) {
|
|
|
+ u32 etx;
|
|
|
+
|
|
|
if (pl022->vendor->pl023) {
|
|
|
/* These bits are only in the PL023 */
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
|
|
@@ -2002,29 +1956,51 @@ static int pl022_setup(struct spi_device *spi)
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
|
|
|
SSP_CR1_MASK_MWAIT_ST, 6);
|
|
|
}
|
|
|
- SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
|
|
|
+ SSP_WRITE_BITS(chip->cr0, bits - 1,
|
|
|
SSP_CR0_MASK_DSS_ST, 0);
|
|
|
- SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx,
|
|
|
- SSP_CR1_MASK_RENDN_ST, 4);
|
|
|
- SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx,
|
|
|
- SSP_CR1_MASK_TENDN_ST, 5);
|
|
|
+
|
|
|
+ if (spi->mode & SPI_LSB_FIRST) {
|
|
|
+ tmp = SSP_RX_LSB;
|
|
|
+ etx = SSP_TX_LSB;
|
|
|
+ } else {
|
|
|
+ tmp = SSP_RX_MSB;
|
|
|
+ etx = SSP_TX_MSB;
|
|
|
+ }
|
|
|
+ SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_RENDN_ST, 4);
|
|
|
+ SSP_WRITE_BITS(chip->cr1, etx, SSP_CR1_MASK_TENDN_ST, 5);
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
|
|
|
SSP_CR1_MASK_RXIFLSEL_ST, 7);
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
|
|
|
SSP_CR1_MASK_TXIFLSEL_ST, 10);
|
|
|
} else {
|
|
|
- SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
|
|
|
+ SSP_WRITE_BITS(chip->cr0, bits - 1,
|
|
|
SSP_CR0_MASK_DSS, 0);
|
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->iface,
|
|
|
SSP_CR0_MASK_FRF, 4);
|
|
|
}
|
|
|
+
|
|
|
/* Stuff that is common for all versions */
|
|
|
- SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6);
|
|
|
- SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7);
|
|
|
+ if (spi->mode & SPI_CPOL)
|
|
|
+ tmp = SSP_CLK_POL_IDLE_HIGH;
|
|
|
+ else
|
|
|
+ tmp = SSP_CLK_POL_IDLE_LOW;
|
|
|
+ SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6);
|
|
|
+
|
|
|
+ if (spi->mode & SPI_CPHA)
|
|
|
+ tmp = SSP_CLK_SECOND_EDGE;
|
|
|
+ else
|
|
|
+ tmp = SSP_CLK_FIRST_EDGE;
|
|
|
+ SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPH, 7);
|
|
|
+
|
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8);
|
|
|
/* Loopback is available on all versions except PL023 */
|
|
|
- if (!pl022->vendor->pl023)
|
|
|
- SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0);
|
|
|
+ if (!pl022->vendor->pl023) {
|
|
|
+ if (spi->mode & SPI_LOOP)
|
|
|
+ tmp = LOOPBACK_ENABLED;
|
|
|
+ else
|
|
|
+ tmp = LOOPBACK_DISABLED;
|
|
|
+ SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_LBM, 0);
|
|
|
+ }
|
|
|
SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
|
|
@@ -2033,6 +2009,7 @@ static int pl022_setup(struct spi_device *spi)
|
|
|
spi_set_ctldata(spi, chip);
|
|
|
return status;
|
|
|
err_config_params:
|
|
|
+ spi_set_ctldata(spi, NULL);
|
|
|
err_first_setup:
|
|
|
kfree(chip);
|
|
|
return status;
|
|
@@ -2095,6 +2072,14 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
|
|
|
master->setup = pl022_setup;
|
|
|
master->transfer = pl022_transfer;
|
|
|
|
|
|
+ /*
|
|
|
+ * Supports mode 0-3, loopback, and active low CS. Transfers are
|
|
|
+ * always MS bit first on the original pl022.
|
|
|
+ */
|
|
|
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
|
|
|
+ if (pl022->vendor->extended_cr)
|
|
|
+ master->mode_bits |= SPI_LSB_FIRST;
|
|
|
+
|
|
|
dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
|
|
|
|
|
|
status = amba_request_regions(adev, NULL);
|