arm:lpc32xx:spi/pl022 Add spi->mode support AMBA SPI driver
authorKevin Wells <wellsk40@gmail.com>
Tue, 10 Jan 2012 10:21:48 +0000 (10:21 +0000)
committerBangaragiri G <bangaragiri.g@nxp.com>
Tue, 10 Jan 2012 10:21:48 +0000 (10:21 +0000)
This patch adds spi->mode support for the AMBA pl022 driver and
allows spidev to correctly alter SPI modes. Unused fields used in
the pl022 header file for the pl022_config_chip have been
removed. The ab8500 client driver selects the data transfer size
instead of the platform data. For platforms that use the
amba pl022 driver, the unused fields in the controller data
structure have been removed and the .mode field in the SPI board
info structure is used instead.

Signed-off-by: Bangaragiri G <bangaragiri.g@nxp.com>

arch/arm/mach-lpc32xx/ea3250.c
arch/arm/mach-lpc32xx/fdi3250.c
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-u300/dummyspichip.c
arch/arm/mach-u300/spi.c
arch/arm/mach-ux500/board-mop500.c
drivers/spi/amba-pl022.c
include/linux/amba/pl022.h

index 1ae1609..6eceec8 100644 (file)
@@ -175,18 +175,12 @@ static void ea3250_spi_cs_set(u32 control)
 
 /* Touch screen SPI parameters */
 static struct pl022_config_chip spi0_chip_info = {
-       .lbm                    = LOOPBACK_DISABLED,
        .com_mode               = INTERRUPT_TRANSFER,
        .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
        .hierarchy              = SSP_MASTER,
        .slave_tx_disable       = 0,
-       .endian_tx              = SSP_TX_LSB,
-       .endian_rx              = SSP_RX_LSB,
-       .data_size              = SSP_DATA_BITS_8,
        .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
        .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
-       .clk_phase              = SSP_CLK_FIRST_EDGE,
-       .clk_pol                = SSP_CLK_POL_IDLE_LOW,
        .ctrl_len               = SSP_BITS_8,
        .wait_state             = SSP_MWIRE_WAIT_ZERO,
        .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -220,18 +214,12 @@ static void ea3250_spi_lcdc_cs_set(u32 control)
 
 /* LCDC SPI parameters */
 static struct pl022_config_chip spi0_chip_info1 = {
-       .lbm                    = LOOPBACK_DISABLED,
        .com_mode               = INTERRUPT_TRANSFER,
        .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
        .hierarchy              = SSP_MASTER,
        .slave_tx_disable       = 0,
-       .endian_tx              = SSP_TX_LSB,
-       .endian_rx              = SSP_RX_LSB,
-       .data_size              = SSP_DATA_BITS_8,
        .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
        .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
-       .clk_phase              = SSP_CLK_FIRST_EDGE,
-       .clk_pol                = SSP_CLK_POL_IDLE_LOW,
        .ctrl_len               = SSP_BITS_8,
        .wait_state             = SSP_MWIRE_WAIT_ZERO,
        .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -257,6 +245,7 @@ static int __init ea3250_spi_devices_register(void)
                        .modalias      = "ads7846",
                        .max_speed_hz  = 2500000,
                        .chip_select   = 0,
+                       .mode = SPI_MODE_0,
                        .irq           = IRQ_LPC32XX_GPIO_00,
                        .platform_data = &ea_ads7846_platform_data,
                        .controller_data = &spi0_chip_info,
@@ -265,6 +254,7 @@ static int __init ea3250_spi_devices_register(void)
                        .modalias      = "ea3250_lcdc",
                        .max_speed_hz  = 10000000,
                        .chip_select   = 1,
+                       .mode = SPI_MODE_0,
                        .controller_data = &spi0_chip_info1,
                },
        };
index 14001f2..eb4fd0b 100644 (file)
@@ -103,18 +103,12 @@ static void fdi3250_spi_cs_set(u32 control)
 
 /* SPIDEV parameters */
 static struct pl022_config_chip spi0_chip_info = {
-       .lbm                    = LOOPBACK_DISABLED,
        .com_mode               = INTERRUPT_TRANSFER,
        .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
        .hierarchy              = SSP_MASTER,
        .slave_tx_disable       = 0,
-       .endian_tx              = SSP_TX_LSB,
-       .endian_rx              = SSP_RX_LSB,
-       .data_size              = SSP_DATA_BITS_8,
        .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
        .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
-       .clk_phase              = SSP_CLK_FIRST_EDGE,
-       .clk_pol                = SSP_CLK_POL_IDLE_LOW,
        .ctrl_len               = SSP_BITS_8,
        .wait_state             = SSP_MWIRE_WAIT_ZERO,
        .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
index a42530b..3231f09 100644 (file)
@@ -180,18 +180,12 @@ static void phy3250_spi_cs_set(u32 control)
 }
 
 static struct pl022_config_chip spi0_chip_info = {
-       .lbm                    = LOOPBACK_DISABLED,
        .com_mode               = INTERRUPT_TRANSFER,
        .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
        .hierarchy              = SSP_MASTER,
        .slave_tx_disable       = 0,
-       .endian_tx              = SSP_TX_LSB,
-       .endian_rx              = SSP_RX_LSB,
-       .data_size              = SSP_DATA_BITS_8,
        .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
        .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
-       .clk_phase              = SSP_CLK_FIRST_EDGE,
-       .clk_pol                = SSP_CLK_POL_IDLE_LOW,
        .ctrl_len               = SSP_BITS_8,
        .wait_state             = SSP_MWIRE_WAIT_ZERO,
        .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -247,6 +241,7 @@ static int __init phy3250_spi_board_register(void)
                        .max_speed_hz = 5000000,
                        .bus_num = 0,
                        .chip_select = 0,
+                       .mode = SPI_MODE_0,
                        .platform_data = &eeprom,
                        .controller_data = &spi0_chip_info,
                },
index 5f55012..03f7936 100644 (file)
@@ -46,7 +46,6 @@ static ssize_t dummy_looptest(struct device *dev,
         * struct, this is just used here to alter the behaviour of the chip
         * in order to perform tests.
         */
-       struct pl022_config_chip *chip_info = spi->controller_data;
        int status;
        u8 txbuf[14] = {0xDE, 0xAD, 0xBE, 0xEF, 0x2B, 0xAD,
                        0xCA, 0xFE, 0xBA, 0xBE, 0xB1, 0x05,
@@ -72,7 +71,7 @@ static ssize_t dummy_looptest(struct device *dev,
         * Force chip to 8 bit mode
         * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
         */
-       chip_info->data_size = SSP_DATA_BITS_8;
+       spi->bits_per_word = 8;
        /* You should NOT DO THIS EITHER */
        spi->master->setup(spi);
 
@@ -159,7 +158,7 @@ static ssize_t dummy_looptest(struct device *dev,
         * Force chip to 16 bit mode
         * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
         */
-       chip_info->data_size = SSP_DATA_BITS_16;
+       spi->bits_per_word = 16;
        /* You should NOT DO THIS EITHER */
        spi->master->setup(spi);
 
index f0e887b..edb2c0d 100644 (file)
@@ -30,8 +30,6 @@ static void select_dummy_chip(u32 chipselect)
 }
 
 struct pl022_config_chip dummy_chip_info = {
-       /* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
-       .lbm = LOOPBACK_ENABLED,
        /*
         * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
         * DMA_TRANSFER does not work
@@ -42,14 +40,8 @@ struct pl022_config_chip dummy_chip_info = {
        .hierarchy = SSP_MASTER,
        /* 0 = drive TX even as slave, 1 = do not drive TX as slave */
        .slave_tx_disable = 0,
-       /* LSB first */
-       .endian_tx = SSP_TX_LSB,
-       .endian_rx = SSP_RX_LSB,
-       .data_size = SSP_DATA_BITS_8, /* used to be 12 in some default */
        .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
        .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-       .clk_phase = SSP_CLK_SECOND_EDGE,
-       .clk_pol = SSP_CLK_POL_IDLE_LOW,
        .ctrl_len = SSP_BITS_12,
        .wait_state = SSP_MWIRE_WAIT_ZERO,
        .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -75,7 +67,7 @@ static struct spi_board_info u300_spi_devices[] = {
                .bus_num        = 0, /* Only one bus on this chip */
                .chip_select    = 0,
                /* Means SPI_CS_HIGH, change if e.g low CS */
-               .mode           = 0,
+               .mode           = SPI_MODE_1 | SPI_LSB_FIRST | SPI_LOOP,
        },
 #endif
 };
index 803aec1..8e87154 100644 (file)
@@ -55,19 +55,13 @@ static void ab4500_spi_cs_control(u32 command)
 }
 
 struct pl022_config_chip ab4500_chip_info = {
-       .lbm = LOOPBACK_DISABLED,
        .com_mode = INTERRUPT_TRANSFER,
        .iface = SSP_INTERFACE_MOTOROLA_SPI,
        /* we can act as master only */
        .hierarchy = SSP_MASTER,
        .slave_tx_disable = 0,
-       .endian_rx = SSP_RX_MSB,
-       .endian_tx = SSP_TX_MSB,
-       .data_size = SSP_DATA_BITS_24,
        .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
        .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-       .clk_phase = SSP_CLK_SECOND_EDGE,
-       .clk_pol = SSP_CLK_POL_IDLE_HIGH,
        .cs_control = ab4500_spi_cs_control,
 };
 
@@ -78,7 +72,7 @@ static struct spi_board_info u8500_spi_devices[] = {
                .max_speed_hz = 12000000,
                .bus_num = 0,
                .chip_select = 0,
-               .mode = SPI_MODE_0,
+               .mode = SPI_MODE_3,
                .irq = IRQ_AB4500,
        },
 };
index e9aeee1..dd70dd1 100644 (file)
@@ -1185,12 +1185,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,
@@ -1216,24 +1210,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)) {
@@ -1253,20 +1229,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)) {
@@ -1421,23 +1383,14 @@ static int process_dma_info(struct pl022_config_chip *chip_info,
  * 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;
@@ -1482,18 +1435,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;
@@ -1528,12 +1475,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;
@@ -1550,6 +1501,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;
                }
        }
@@ -1581,19 +1533,29 @@ static int pl022_setup(struct spi_device *spi)
 
        chip->cpsr = chip_info->clk_freq.cpsdvsr;
 
-       SSP_WRITE_BITS(chip->cr0, chip_info->data_size, SSP_CR0_MASK_DSS, 0);
+       SSP_WRITE_BITS(chip->cr0, bits - 1, SSP_CR0_MASK_DSS, 0);
        SSP_WRITE_BITS(chip->cr0, chip_info->duplex, SSP_CR0_MASK_HALFDUP, 5);
-       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);
        SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len, SSP_CR0_MASK_CSS, 16);
        SSP_WRITE_BITS(chip->cr0, chip_info->iface, SSP_CR0_MASK_FRF, 21);
-       SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0);
+       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);
-       SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx, SSP_CR1_MASK_RENDN, 4);
-       SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx, SSP_CR1_MASK_TENDN, 5);
        SSP_WRITE_BITS(chip->cr1, chip_info->wait_state, SSP_CR1_MASK_MWAIT, 6);
        SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig, SSP_CR1_MASK_RXIFLSEL, 7);
        SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, SSP_CR1_MASK_TXIFLSEL, 10);
@@ -1602,6 +1564,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;
@@ -1664,6 +1627,12 @@ 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;
+
        dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
 
        status = amba_request_regions(adev, NULL);
index e4836c6..81c733e 100644 (file)
@@ -219,19 +219,13 @@ struct pl022_ssp_controller {
  * struct ssp_config_chip - spi_board_info.controller_data for SPI
  * slave devices, copied to spi_device.controller_data.
  *
- * @lbm: used for test purpose to internally connect RX and TX
  * @iface: Interface type(Motorola, TI, Microwire, Universal)
  * @hierarchy: sets whether interface is master or slave
  * @slave_tx_disable: SSPTXD is disconnected (in slave mode only)
  * @clk_freq: Tune freq parameters of SSP(when in master mode)
- * @endian_rx: Endianess of Data in Rx FIFO
- * @endian_tx: Endianess of Data in Tx FIFO
- * @data_size: Width of data element(4 to 32 bits)
  * @com_mode: communication mode: polling, Interrupt or DMA
  * @rx_lev_trig: Rx FIFO watermark level (for IT & DMA mode)
  * @tx_lev_trig: Tx FIFO watermark level (for IT & DMA mode)
- * @clk_phase: Motorola SPI interface Clock phase
- * @clk_pol: Motorola SPI interface Clock polarity
  * @ctrl_len: Microwire interface: Control length
  * @wait_state: Microwire interface: Wait state
  * @duplex: Microwire interface: Full/Half duplex
@@ -242,19 +236,13 @@ struct pl022_ssp_controller {
  */
 struct pl022_config_chip {
        struct device *dev;
-       enum ssp_loopback lbm;
        enum ssp_interface iface;
        enum ssp_hierarchy hierarchy;
        bool slave_tx_disable;
        struct ssp_clock_params clk_freq;
-       enum ssp_rx_endian endian_rx;
-       enum ssp_tx_endian endian_tx;
-       enum ssp_data_size data_size;
        enum ssp_mode com_mode;
        enum ssp_rx_level_trig rx_lev_trig;
        enum ssp_tx_level_trig tx_lev_trig;
-       enum ssp_spi_clk_phase clk_phase;
-       enum ssp_spi_clk_pol clk_pol;
        enum ssp_microwire_ctrl_len ctrl_len;
        enum ssp_microwire_wait_state wait_state;
        enum ssp_duplex duplex;