]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/spi/amba-pl022.c
spi/pl022: get rid of chipinfo dev pointer
[net-next-2.6.git] / drivers / spi / amba-pl022.c
index db0c67908d2b56336e71cf5e5a34b81b72349af0..19d54aa31a36c46d192976803a157f9c91607537 100644 (file)
@@ -1595,98 +1595,60 @@ 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,
+               dev_err(&pl022->adev->dev,
                        "interface is configured incorrectly\n");
                return -EINVAL;
        }
        if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
            (!pl022->vendor->unidir)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "unidirectional mode not supported in this "
                        "hardware version\n");
                return -EINVAL;
        }
        if ((chip_info->hierarchy != SSP_MASTER)
            && (chip_info->hierarchy != SSP_SLAVE)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "hierarchy is configured incorrectly\n");
                return -EINVAL;
        }
        if (((chip_info->clk_freq).cpsdvsr < CPSDVR_MIN)
            || ((chip_info->clk_freq).cpsdvsr > CPSDVR_MAX)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "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)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "Communication mode is configured incorrectly\n");
                return -EINVAL;
        }
        if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM)
            || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "RX FIFO Trigger Level is configured incorrectly\n");
                return -EINVAL;
        }
        if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC)
            || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "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)) {
-                       dev_err(chip_info->dev,
+                       dev_err(&pl022->adev->dev,
                                "CTRL LEN is configured incorrectly\n");
                        return -EINVAL;
                }
                if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
                    && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
-                       dev_err(chip_info->dev,
+                       dev_err(&pl022->adev->dev,
                                "Wait State is configured incorrectly\n");
                        return -EINVAL;
                }
@@ -1696,13 +1658,13 @@ static int verify_controller_parameters(struct pl022 *pl022,
                             SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
                            && (chip_info->duplex !=
                                SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
-                               dev_err(chip_info->dev,
+                               dev_err(&pl022->adev->dev,
                                        "Microwire duplex mode is configured incorrectly\n");
                                return -EINVAL;
                        }
                } else {
                        if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
-                               dev_err(chip_info->dev,
+                               dev_err(&pl022->adev->dev,
                                        "Microwire half duplex mode requested,"
                                        " but this is only available in the"
                                        " ST version of PL022\n");
@@ -1710,7 +1672,7 @@ static int verify_controller_parameters(struct pl022 *pl022,
                }
        }
        if (chip_info->cs_control == NULL) {
-               dev_warn(chip_info->dev,
+               dev_warn(&pl022->adev->dev,
                        "Chip Select Function is NULL for this chip\n");
                chip_info->cs_control = null_cs_control;
        }
@@ -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;
@@ -1905,9 +1852,6 @@ static int pl022_setup(struct spi_device *spi)
                        "using user supplied controller_data settings\n");
        }
 
-       /* Pointer back to the SPI device */
-       chip_info->dev = &spi->dev;
-
        /*
         * We can override with custom divisors, else we use the board
         * frequency setting
@@ -1933,12 +1877,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 +1903,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 +1936,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 +1953,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 +2006,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 +2069,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);