From patchwork Sun Oct 2 12:22:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiner Kallweit X-Patchwork-Id: 9359611 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7DCB36075E for ; Sun, 2 Oct 2016 12:24:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6F02528AE9 for ; Sun, 2 Oct 2016 12:24:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 63D0228AF3; Sun, 2 Oct 2016 12:24:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D79D928AE9 for ; Sun, 2 Oct 2016 12:24:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751827AbcJBMYS (ORCPT ); Sun, 2 Oct 2016 08:24:18 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:33632 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751611AbcJBMYR (ORCPT ); Sun, 2 Oct 2016 08:24:17 -0400 Received: by mail-wm0-f65.google.com with SMTP id p138so10385585wmb.0 for ; Sun, 02 Oct 2016 05:24:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:subject:to:references:cc:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=77tFLCOjQ2eVlRvAk4EeXuKtUqzbliPqSaQ3FfN7oGg=; b=oiSuZnsH8T6+PzCX6cVJXZaLdfb0AV+2KLiL6/4TkmnqgoeickqhEYHp0r9a0Ek0Tq sRrHlhTov1SQUYaDQRM07dWmkv4teM28qSx+k1YaVb2TOWFVGxiLanaHI6Wf2E84+KPw T6l5cYEpcLjay3svLfzSdMLfQcvx2CoVWt8zuLDPvV+0fbAjEl0obwk0q5lb8LWjCYly DhbrOncYmxtcNeugYzOk/sVG9fHn0A9zRj69I9qW4OfWkilpTSq6idyGI7auY60In/la U9m4t7aJBBO0ZpBed+Pd2gT+i6+NMMBYx+oO804ME77lDW6p4MVu3zuhEGoYQFznJZAC zy/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:subject:to:references:cc:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=77tFLCOjQ2eVlRvAk4EeXuKtUqzbliPqSaQ3FfN7oGg=; b=GfHlyRNIaYDz+io4dvU7zS5k/cJPo+6ABxdrmUfHCdwTL9SO6w7uzfEXgcKBwJ1j0v csJmkDquT/a+eh5Q4nhwIplrb7z2iwEGaFUCNbMmTTP4+zNB2tneG4ta5IGiEPeYve2B yKQTQ8Fkq/soO//MgxznAMZdJx+ZRbBa2dwwqDQ84ROu4XNZ5Nyml11VDOoPu05eQZ7C KuRl4kgzCxcmZGLeaUrQPAOgatxTP3Y6t92yWNTQawUh8KR9CQbWFwUCQfSSrE0Y+Z+G q4MFLlo0l24MgI/sK1k7nNw8sP2M3Mj1C7np1ZdRG8S+WQSB9BED9F4ZGWzYg+tV9sK/ ItGA== X-Gm-Message-State: AA6/9RkWRZ/g+1wLxxRqnN6VyGk4x6z0SGc2x/v9yiWkZcEiJ6Mq32V3dnhmYwu+ILfAKQ== X-Received: by 10.194.100.169 with SMTP id ez9mr4311035wjb.9.1475411055897; Sun, 02 Oct 2016 05:24:15 -0700 (PDT) Received: from ?IPv6:2003:62:5f1b:3000:8dbc:eb8a:fb9c:9173? ([2003:62:5f1b:3000:8dbc:eb8a:fb9c:9173]) by smtp.googlemail.com with ESMTPSA id e12sm13696054wmg.17.2016.10.02.05.24.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 02 Oct 2016 05:24:15 -0700 (PDT) From: Heiner Kallweit Subject: [PATCH 03/11] spi: fsl-espi: fix handling of word sizes other than 8 bit To: Mark Brown References: <5b98be38-17a2-79a2-14da-fb2bb6f8820f@gmail.com> Cc: "linux-spi@vger.kernel.org" Message-ID: <2ad0ed64-f9b4-d3a9-e330-80dbb6f70c01@gmail.com> Date: Sun, 2 Oct 2016 14:22:57 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 MIME-Version: 1.0 In-Reply-To: <5b98be38-17a2-79a2-14da-fb2bb6f8820f@gmail.com> Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The code in fsl_espi_tx_buf_lsb and parts of fsl_espi_setup_transfer look very weird and don't reflect the ESPI spec. ESPI stores values with <= 8 bit word size right justified as 8 bit value and values with > 8 bit word size right justified as 16 bit value. Therefore no such shifting is needed. Only case MSB-first with 8 bit word size is correctly handled, and most likely nobody ever used this driver with a different config. On ESPI only the case LSB-first with word size > 8 bit needs a special handling. In this case a little endian 16 bit value has to be written to the TX FIFO what requires a byte swap as the host system is big endian. The same applies to reading from the RX FIFO. Signed-off-by: Heiner Kallweit --- drivers/spi/spi-fsl-espi.c | 84 ++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 48 deletions(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 8281aea1..4a7fe77 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -112,6 +112,32 @@ static inline void fsl_espi_write_reg8(struct mpc8xxx_spi *mspi, int offset, iowrite8(val, mspi->reg_base + offset); } +static void fsl_espi_memcpy_swab(void *to, const void *from, + struct spi_message *m, + struct spi_transfer *t) +{ + unsigned int len = t->len; + + if (!(m->spi->mode & SPI_LSB_FIRST) || t->bits_per_word <= 8) { + memcpy(to, from, len); + return; + } + + /* In case of LSB-first and bits_per_word > 8 byte-swap all words */ + while (len) + if (len >= 4) { + *(u32 *)to = swahb32p(from); + to += 4; + from += 4; + len -= 4; + } else { + *(u16 *)to = swab16p(from); + to += 2; + from += 2; + len -= 2; + } +} + static void fsl_espi_copy_to_buf(struct spi_message *m, struct mpc8xxx_spi *mspi) { @@ -120,7 +146,7 @@ static void fsl_espi_copy_to_buf(struct spi_message *m, list_for_each_entry(t, &m->transfers, transfer_list) { if (t->tx_buf) - memcpy(buf, t->tx_buf, t->len); + fsl_espi_memcpy_swab(buf, t->tx_buf, m, t); else memset(buf, 0, t->len); buf += t->len; @@ -135,7 +161,7 @@ static void fsl_espi_copy_from_buf(struct spi_message *m, list_for_each_entry(t, &m->transfers, transfer_list) { if (t->rx_buf) - memcpy(t->rx_buf, buf, t->len); + fsl_espi_memcpy_swab(t->rx_buf, buf, m, t); buf += t->len; } } @@ -194,27 +220,6 @@ static void fsl_espi_change_mode(struct spi_device *spi) local_irq_restore(flags); } -static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi) -{ - u32 data; - u16 data_h; - u16 data_l; - const u32 *tx = mpc8xxx_spi->tx; - - if (!tx) - return 0; - - data = *tx++ << mpc8xxx_spi->tx_shift; - data_l = data & 0xffff; - data_h = (data >> 16) & 0xffff; - swab16s(&data_l); - swab16s(&data_h); - data = data_h | data_l; - - mpc8xxx_spi->tx = tx; - return data; -} - static void fsl_espi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { @@ -224,23 +229,6 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, u8 pm; struct spi_mpc8xxx_cs *cs = spi->controller_state; - cs->rx_shift = 0; - cs->tx_shift = 0; - cs->get_rx = mpc8xxx_spi_rx_buf_u32; - cs->get_tx = mpc8xxx_spi_tx_buf_u32; - if (bits_per_word <= 8) { - cs->rx_shift = 8 - bits_per_word; - } else { - cs->rx_shift = 16 - bits_per_word; - if (spi->mode & SPI_LSB_FIRST) - cs->get_tx = fsl_espi_tx_buf_lsb; - } - - mpc8xxx_spi->rx_shift = cs->rx_shift; - mpc8xxx_spi->tx_shift = cs->tx_shift; - mpc8xxx_spi->get_rx = cs->get_rx; - mpc8xxx_spi->get_tx = cs->get_tx; - /* mask out bits we are going to set */ cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF)); @@ -271,7 +259,6 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); - u32 word; int ret; mpc8xxx_spi->len = t->len; @@ -290,8 +277,8 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, SPIM_RNE); /* transmit word */ - word = mpc8xxx_spi->get_tx(mpc8xxx_spi); - fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPITF, word); + fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPITF, *(u32 *)mpc8xxx_spi->tx); + mpc8xxx_spi->tx += 4; /* Won't hang up forever, SPI bus sometimes got lost interrupts... */ ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ); @@ -468,8 +455,10 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) mspi->len -= rx_nr_bytes; - if (mspi->rx) - mspi->get_rx(rx_data, mspi); + if (mspi->rx) { + *(u32 *)mspi->rx = rx_data; + mspi->rx += 4; + } } if (!(events & SPIE_TNF)) { @@ -487,9 +476,8 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) mspi->count -= 1; if (mspi->count) { - u32 word = mspi->get_tx(mspi); - - fsl_espi_write_reg(mspi, ESPI_SPITF, word); + fsl_espi_write_reg(mspi, ESPI_SPITF, *(u32 *)mspi->tx); + mspi->tx += 4; } else { complete(&mspi->done); }