From patchwork Thu Sep 2 17:03:12 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wellsk40@gmail.com X-Patchwork-Id: 151601 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o8304bhg022286 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 3 Sep 2010 00:05:13 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-1.v29.ch3.sourceforge.com) by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OrJli-0008R8-9z; Fri, 03 Sep 2010 00:04:34 +0000 Received: from sog-mx-4.v43.ch3.sourceforge.com ([172.29.43.194] helo=mx.sourceforge.net) by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OrJlh-0008R3-VA for spi-devel-general@lists.sourceforge.net; Fri, 03 Sep 2010 00:04:33 +0000 Received-SPF: pass (sog-mx-4.v43.ch3.sourceforge.com: domain of gmail.com designates 209.85.216.175 as permitted sender) client-ip=209.85.216.175; envelope-from=wellsk40@gmail.com; helo=mail-qy0-f175.google.com; Received: from mail-qy0-f175.google.com ([209.85.216.175]) by sog-mx-4.v43.ch3.sourceforge.com with esmtp (Exim 4.69) id 1OrJlc-00079T-Hw for spi-devel-general@lists.sourceforge.net; Fri, 03 Sep 2010 00:04:33 +0000 Received: by qyk31 with SMTP id 31so2852758qyk.13 for ; Thu, 02 Sep 2010 17:04:23 -0700 (PDT) Received: by 10.224.2.213 with SMTP id 21mr384156qak.14.1283472262944; Thu, 02 Sep 2010 17:04:22 -0700 (PDT) Received: from localhost.localdomain (66-193-100-242.static.twtelecom.net [66.193.100.242]) by mx.google.com with ESMTPS id r1sm1128608qcq.10.2010.09.02.17.04.20 (version=SSLv3 cipher=RC4-MD5); Thu, 02 Sep 2010 17:04:21 -0700 (PDT) From: wellsk40@gmail.com To: spi-devel-general@lists.sourceforge.net Subject: [PATCH] amba_pl022: Setup SPI configuration based on spi->mode Date: Thu, 2 Sep 2010 10:03:12 -0700 Message-Id: <1283446992-23764-1-git-send-email-wellsk40@gmail.com> X-Mailer: git-send-email 1.7.2.2 X-Spam-Score: 1.5 (+) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain 0.0 FREEMAIL_FROM Sender email is freemail (wellsk40[at]gmail.com) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.216.175 listed in list.dnswl.org] 1.1 DATE_IN_PAST_06_12 Date: is 6 to 12 hours before Received: date -0.0 SPF_PASS SPF: sender matches SPF record 2.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (wellsk40[at]gmail.com) -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 T_TO_NO_BRKTS_FREEMAIL T_TO_NO_BRKTS_FREEMAIL -0.3 AWL AWL: From: address is in the auto white-list X-Headers-End: 1OrJlc-00079T-Hw X-BeenThere: spi-devel-general@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux SPI core/device drivers discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: spi-devel-general-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 03 Sep 2010 00:05:13 +0000 (UTC) diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index acd35d1..1be488a 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -1248,12 +1248,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, @@ -1279,24 +1273,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)) { @@ -1316,20 +1292,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)) { @@ -1494,23 +1456,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; @@ -1555,18 +1508,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; @@ -1601,12 +1548,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; @@ -1623,6 +1574,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; } } @@ -1656,6 +1608,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, @@ -1671,29 +1625,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, 6); + 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); @@ -1702,6 +1678,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; @@ -1764,6 +1741,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);