From patchwork Sun Jan 17 10:56:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Ricard X-Patchwork-Id: 569242 X-Patchwork-Delegate: jagannadh.teki@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id CE879140662 for ; Sun, 17 Jan 2016 21:57:41 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=BouP+6rk; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 44F44A7811; Sun, 17 Jan 2016 11:57:25 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id WrSjwQSyhd2r; Sun, 17 Jan 2016 11:57:25 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3B652A7838; Sun, 17 Jan 2016 11:57:21 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E9310A76E8 for ; Sun, 17 Jan 2016 11:57:06 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8wS11OiOib73 for ; Sun, 17 Jan 2016 11:57:06 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-wm0-f66.google.com (mail-wm0-f66.google.com [74.125.82.66]) by theia.denx.de (Postfix) with ESMTPS id 07E2FA77EB for ; Sun, 17 Jan 2016 11:57:00 +0100 (CET) Received: by mail-wm0-f66.google.com with SMTP id b14so11124641wmb.1 for ; Sun, 17 Jan 2016 02:57:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6MjIF1SSchXeK2FdYYt6FsmF5gUnpKzkDddcyq/PCUA=; b=BouP+6rkOBAf8oV3Mun8zQ+6lpCJ9mWiGG93gG4kL9Iz206AvXZt3KmgDFCzgHCMyI vQum9t2TqAIr5fRrFxO40e4MFB9BGu03J4BDraXdLssSbx8LSWk5Xm4sXbdhUsitwCqE 0ccqaNGkIn0nFz/na7eSsOuLP8AdJg0ZT4mbMZ3kL1oUrhqBn9+1D7vLQjTI+hftQyPb 14Xg7JdF0hI8SblRm4nk4hI6ddvnyDD1PDG0G/p0p9MLh8F2NJlDY4zwzY9Tn7oiXdQe bwcFT5BM3KPxPTRX5tn+TfwL1N85mih6fqSmJwcF3QTeAXvXIGMEpqdjgjDXz94/mpb2 PqHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6MjIF1SSchXeK2FdYYt6FsmF5gUnpKzkDddcyq/PCUA=; b=fhpcZ2uxsTbusUX7n3F0PylM4qBMxEZpWX9NHGYT3jX6gp/biJnj5JncFQYnRao7fl SbQM/x61zqxQtbuReUMWjHCAbnAc4rH4cyKp4h4Hrbn8XYrev0JqmJm1PTmlnCzPb6S6 amegc2EryM0R7Dps177HKEooFzQz24ceYqu2vFNnKfcRpvF19nouYrAkPj5pbSfubK6+ c5WAIQ9S4al1VNKkL6rE1zge9CscYQSSqDs6lSfgQcEC81hVf7pGOdfOVUAG4QTvzuWg h1X0lxpUENFFz8OyKpiK5zC1R49g/6S67LXKJl2SyEXXCfno5CI6fTlxfWdlWStsJGFr gp2A== X-Gm-Message-State: AG10YORteUddHeWmogsspCndoINb+qFve5KLre0R+llDLb15dx4pM1qiKC/22DPfkgMPRA== X-Received: by 10.28.176.133 with SMTP id z127mr8025069wme.22.1453028220552; Sun, 17 Jan 2016 02:57:00 -0800 (PST) Received: from localhost.localdomain (ax113-6-78-236-204-66.fbx.proxad.net. [78.236.204.66]) by smtp.gmail.com with ESMTPSA id e2sm12259178wma.1.2016.01.17.02.56.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 17 Jan 2016 02:56:59 -0800 (PST) From: Christophe Ricard X-Google-Original-From: Christophe Ricard To: u-boot@lists.denx.de Date: Sun, 17 Jan 2016 11:56:49 +0100 Message-Id: <1453028210-10139-4-git-send-email-christophe-h.ricard@st.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1453028210-10139-1-git-send-email-christophe-h.ricard@st.com> References: <1453028210-10139-1-git-send-email-christophe-h.ricard@st.com> Cc: Christophe Ricard , Jagan Teki , Benoit Houyere Subject: [U-Boot] [PATCH 3/4] spi: omap3: Convert to DM X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Convert omap3_spi driver to DM and keep compatibility with previous mode. Signed-off-by: Christophe Ricard --- drivers/spi/Kconfig | 6 + drivers/spi/omap3_spi.c | 439 ++++++++++++++++++++++++++++++++++++++++++------ drivers/spi/omap3_spi.h | 14 +- 3 files changed, 402 insertions(+), 57 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2cdb110..b8c2498 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -155,6 +155,12 @@ config ZYNQ_QSPI Zynq QSPI IP core. This IP is used to connect the flash in 4-bit qspi, 8-bit dual stacked and shared 4-bit dual parallel. +config OMAP3_SPI + bool "McSPI driver for OMAP" + help + SPI master controller for OMAP24XX and later Multichannel SPI + (McSPI) modules. + endif # if DM_SPI config FSL_ESPI diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 95cdfa3..09fb1ef 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -11,10 +11,14 @@ * * Modified by Ruslan Araslanov * + * Copyright (c) 2016 Christophe Ricard + * - Added support for DM_SPI + * * SPDX-License-Identifier: GPL-2.0+ */ #include +#include #include #include #include @@ -22,9 +26,17 @@ #define SPI_WAIT_TIMEOUT 10 +#ifdef CONFIG_DM_SPI +static void spi_reset(struct udevice *dev) +#else static void spi_reset(struct omap3_spi_slave *ds) +#endif { unsigned int tmp; +#ifdef CONFIG_DM_SPI + struct omap3_spi_slave *ds = dev_get_priv(dev->parent); + +#endif writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig); do { @@ -39,20 +51,50 @@ static void spi_reset(struct omap3_spi_slave *ds) writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable); } +#ifdef CONFIG_DM_SPI +static void omap3_spi_write_chconf(struct udevice *dev, int val) +#else static void omap3_spi_write_chconf(struct omap3_spi_slave *ds, int val) +#endif { - writel(val, &ds->regs->channel[ds->slave.cs].chconf); + unsigned int cs; +#ifdef CONFIG_DM_SPI + struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev); + struct omap3_spi_slave *ds = dev_get_priv(dev->parent); + + + cs = platdata->cs; +#else + cs = ds->slave.cs; +#endif + + writel(val, &ds->regs->channel[cs].chconf); /* Flash post writes to make immediate effect */ - readl(&ds->regs->channel[ds->slave.cs].chconf); + readl(&ds->regs->channel[cs].chconf); } +#ifdef CONFIG_DM_SPI +static void omap3_spi_set_enable(struct udevice *dev, int enable) +#else static void omap3_spi_set_enable(struct omap3_spi_slave *ds, int enable) +#endif { - writel(enable, &ds->regs->channel[ds->slave.cs].chctrl); + unsigned int cs; +#ifdef CONFIG_DM_SPI + struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev); + struct omap3_spi_slave *ds = dev_get_priv(dev->parent); + + cs = platdata->cs; +#else + cs = ds->slave.cs; +#endif + + writel(enable, &ds->regs->channel[cs].chctrl); /* Flash post writes to make immediate effect */ - readl(&ds->regs->channel[ds->slave.cs].chctrl); + readl(&ds->regs->channel[cs].chctrl); } +#ifndef CONFIG_DM_SPI void spi_init() { /* do nothing */ @@ -138,10 +180,32 @@ void spi_free_slave(struct spi_slave *slave) free(ds); } +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + return 1; +} +#endif + +#ifdef CONFIG_DM_SPI +static int omap3_spi_claim_bus(struct udevice *dev) +#else int spi_claim_bus(struct spi_slave *slave) +#endif { - struct omap3_spi_slave *ds = to_omap3_spi(slave); + unsigned int cs; + struct omap3_spi_slave *ds; unsigned int conf, div = 0; +#ifdef CONFIG_DM_SPI + struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); + + ds = dev_get_priv(dev->parent); + cs = platdata->cs; + ds->freq = slave->max_hz; +#else + ds = to_omap3_spi(slave); + cs = ds->slave.cs; +#endif /* McSPI global module configuration */ @@ -149,7 +213,11 @@ int spi_claim_bus(struct spi_slave *slave) * setup when switching from (reset default) slave mode * to single-channel master mode */ +#ifdef CONFIG_DM_SPI + spi_reset(dev); +#else spi_reset(ds); +#endif conf = readl(&ds->regs->modulctrl); conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS); conf |= OMAP3_MCSPI_MODULCTRL_SINGLE; @@ -165,8 +233,7 @@ int spi_claim_bus(struct spi_slave *slave) } else div = 0xC; - conf = readl(&ds->regs->channel[ds->slave.cs].chconf); - + conf = readl(&ds->regs->channel[cs].chconf); /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS * REVISIT: this controller could support SPI_3WIRE mode. */ @@ -184,7 +251,7 @@ int spi_claim_bus(struct spi_slave *slave) /* wordlength */ conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK; - conf |= (ds->slave.wordlen - 1) << 7; + conf |= (slave->wordlen - 1) << 7; /* set chipselect polarity; manage with FORCE */ if (!(ds->mode & SPI_CS_HIGH)) @@ -209,113 +276,222 @@ int spi_claim_bus(struct spi_slave *slave) /* Transmit & receive mode */ conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, conf); +#else omap3_spi_write_chconf(ds,conf); +#endif return 0; } +#ifdef CONFIG_DM_SPI +int omap3_spi_release_bus(struct udevice *dev) +#else void spi_release_bus(struct spi_slave *slave) +#endif { +#ifndef CONFIG_DM_SPI struct omap3_spi_slave *ds = to_omap3_spi(slave); - +#endif /* Reset the SPI hardware */ +#ifdef CONFIG_DM_SPI + spi_reset(dev); +#else spi_reset(ds); +#endif + +#ifdef CONFIG_DM_SPI + return 0; +#endif } +#ifdef CONFIG_DM_SPI +int omap3_spi_write(struct udevice *dev, unsigned int len, const void *txp, + unsigned long flags) +#else int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp, unsigned long flags) +#endif { - struct omap3_spi_slave *ds = to_omap3_spi(slave); - int i; + struct omap3_spi_slave *ds; + int i, chconf; ulong start; - int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); + unsigned int cs; +#ifdef CONFIG_DM_SPI + struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); + + ds = dev_get_priv(dev->parent); + cs = platdata->cs; +#else + ds = to_omap3_spi(slave); + cs = ds->slave.cs; +#endif + + chconf = readl(&ds->regs->channel[cs].chconf); + +#ifdef CONFIG_DM_SPI /* Enable the channel */ - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN); + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN); +#else + /* Enable the channel */ + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN); +#endif chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK); +#ifdef CONFIG_DM_SPI + chconf |= (slave->wordlen - 1) << 7; +#else chconf |= (ds->slave.wordlen - 1) << 7; +#endif chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY; chconf |= OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); +#else + omap3_spi_write_chconf(ds, chconf); +#endif for (i = 0; i < len; i++) { /* wait till TX register is empty (TXS == 1) */ start = get_timer(0); - while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & + while (!(readl(&ds->regs->channel[cs].chstat) & OMAP3_MCSPI_CHSTAT_TXS)) { if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI TXS timed out, status=0x%08x\n", - readl(&ds->regs->channel[ds->slave.cs].chstat)); + readl(&ds->regs->channel[cs].chstat)); return -1; } } + /* Write the data */ - unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx; + unsigned int *tx = &ds->regs->channel[cs].tx; +#ifdef CONFIG_DM_SPI + if (slave->wordlen > 16) +#else if (ds->slave.wordlen > 16) +#endif writel(((u32 *)txp)[i], tx); +#ifdef CONFIG_DM_SPI + else if (slave->wordlen > 8) +#else else if (ds->slave.wordlen > 8) +#endif writel(((u16 *)txp)[i], tx); else writel(((u8 *)txp)[i], tx); } /* wait to finish of transfer */ - while ((readl(&ds->regs->channel[ds->slave.cs].chstat) & + while ((readl(&ds->regs->channel[cs].chstat) & (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) != - (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)); + (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) + ; +#ifdef CONFIG_DM_SPI + /* Disable the channel otherwise the next immediate RX will get affected */ + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS); +#else /* Disable the channel otherwise the next immediate RX will get affected */ - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS); + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS); +#endif if (flags & SPI_XFER_END) { chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); +#else + omap3_spi_write_chconf(ds, chconf); +#endif } + return 0; } +#ifdef CONFIG_DM_SPI +int omap3_spi_read(struct udevice *dev, unsigned int len, void *rxp, + unsigned long flags) +#else int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, unsigned long flags) +#endif { - struct omap3_spi_slave *ds = to_omap3_spi(slave); - int i; + struct omap3_spi_slave *ds; + int i, chconf; ulong start; - int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); + unsigned int cs; +#ifdef CONFIG_DM_SPI + struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); + + ds = dev_get_priv(dev->parent); + cs = platdata->cs; +#else + ds = to_omap3_spi(slave); + cs = ds->slave.cs; +#endif + chconf = readl(&ds->regs->channel[cs].chconf); + +#ifdef CONFIG_DM_SPI + /* Enable the channel */ + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN); +#else /* Enable the channel */ - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN); + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN); +#endif chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK); +#ifdef CONFIG_DM_SPI + chconf |= (slave->wordlen - 1) << 7; +#else chconf |= (ds->slave.wordlen - 1) << 7; +#endif chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY; chconf |= OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); +#else + omap3_spi_write_chconf(ds, chconf); +#endif - writel(0, &ds->regs->channel[ds->slave.cs].tx); + writel(0, &ds->regs->channel[cs].tx); for (i = 0; i < len; i++) { start = get_timer(0); /* Wait till RX register contains data (RXS == 1) */ - while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & + while (!(readl(&ds->regs->channel[cs].chstat) & OMAP3_MCSPI_CHSTAT_RXS)) { if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI RXS timed out, status=0x%08x\n", - readl(&ds->regs->channel[ds->slave.cs].chstat)); + readl(&ds->regs->channel[cs].chstat)); return -1; } } - /* Disable the channel to prevent furher receiving */ if(i == (len - 1)) - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS); +#ifdef CONFIG_DM_SPI + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS); +#else + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS); +#endif /* Read the data */ - unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx; + unsigned int *rx = &ds->regs->channel[cs].rx; +#ifdef CONFIG_DM_SPI + if (slave->wordlen > 16) +#else if (ds->slave.wordlen > 16) +#endif ((u32 *)rxp)[i] = readl(rx); +#ifdef CONFIG_DM_SPI + else if (slave->wordlen > 8) +#else else if (ds->slave.wordlen > 8) +#endif ((u16 *)rxp)[i] = (u16)readl(rx); else ((u8 *)rxp)[i] = (u8)readl(rx); @@ -323,89 +499,177 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, if (flags & SPI_XFER_END) { chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); +#else + omap3_spi_write_chconf(ds, chconf); +#endif } return 0; } +#ifdef CONFIG_DM_SPI +/*McSPI Transmit Receive Mode*/ +int omap3_spi_txrx(struct udevice *dev, unsigned int len, + const void *txp, void *rxp, unsigned long flags) +#else /*McSPI Transmit Receive Mode*/ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, const void *txp, void *rxp, unsigned long flags) +#endif { - struct omap3_spi_slave *ds = to_omap3_spi(slave); + struct omap3_spi_slave *ds; ulong start; - int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); + int chconf; int i=0; + unsigned int cs; +#ifdef CONFIG_DM_SPI + struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); + + ds = dev_get_priv(dev->parent); + cs = platdata->cs; +#else + ds = to_omap3_spi(slave); + cs = ds->slave.cs; +#endif + chconf = readl(&ds->regs->channel[cs].chconf); + +#ifdef CONFIG_DM_SPI + /*Enable SPI channel*/ + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN); +#else /*Enable SPI channel*/ - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN); + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN); +#endif /*set TRANSMIT-RECEIVE Mode*/ chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK); +#ifdef CONFIG_DM_SPI + chconf |= (slave->wordlen - 1) << 7; +#else chconf |= (ds->slave.wordlen - 1) << 7; +#endif chconf |= OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); +#else + omap3_spi_write_chconf(ds, chconf); +#endif /*Shift in and out 1 byte at time*/ for (i=0; i < len; i++){ /* Write: wait for TX empty (TXS == 1)*/ start = get_timer(0); - while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & + while (!(readl(&ds->regs->channel[cs].chstat) & OMAP3_MCSPI_CHSTAT_TXS)) { if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI TXS timed out, status=0x%08x\n", - readl(&ds->regs->channel[ds->slave.cs].chstat)); + readl(&ds->regs->channel[cs].chstat)); return -1; } } /* Write the data */ - unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx; + unsigned int *tx = &ds->regs->channel[cs].tx; +#ifdef CONFIG_DM_SPI + if (slave->wordlen > 16) +#else if (ds->slave.wordlen > 16) +#endif writel(((u32 *)txp)[i], tx); +#ifdef CONFIG_DM_SPI + else if (slave->wordlen > 8) +#else else if (ds->slave.wordlen > 8) +#endif writel(((u16 *)txp)[i], tx); else writel(((u8 *)txp)[i], tx); /*Read: wait for RX containing data (RXS == 1)*/ start = get_timer(0); - while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & + while (!(readl(&ds->regs->channel[cs].chstat) & OMAP3_MCSPI_CHSTAT_RXS)) { if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI RXS timed out, status=0x%08x\n", - readl(&ds->regs->channel[ds->slave.cs].chstat)); + readl(&ds->regs->channel[cs].chstat)); return -1; } } /* Read the data */ - unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx; + unsigned int *rx = &ds->regs->channel[cs].rx; +#ifdef CONFIG_DM_SPI + if (slave->wordlen > 16) +#else if (ds->slave.wordlen > 16) +#endif ((u32 *)rxp)[i] = readl(rx); +#ifdef CONFIG_DM_SPI + else if (slave->wordlen > 8) +#else else if (ds->slave.wordlen > 8) +#endif ((u16 *)rxp)[i] = (u16)readl(rx); else ((u8 *)rxp)[i] = (u8)readl(rx); } + +#ifdef CONFIG_DM_SPI + /* Disable the channel */ + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS); +#else /* Disable the channel */ - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS); + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS); +#endif /*if transfer must be terminated disable the channel*/ if (flags & SPI_XFER_END) { chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); +#else + omap3_spi_write_chconf(ds, chconf); +#endif } return 0; } +#ifdef CONFIG_DM_SPI +int omap3_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +#else int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) +#endif { - struct omap3_spi_slave *ds = to_omap3_spi(slave); - unsigned int len; + struct omap3_spi_slave *ds; + unsigned int len, cs; int ret = -1; +#ifdef CONFIG_DM_SPI + struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); + + ds = dev_get_priv(dev->parent); + cs = platdata->cs; +#else + ds = to_omap3_spi(slave); + cs = ds->slave.cs; +#endif +#ifdef CONFIG_DM_SPI + if (slave->wordlen < 4 || slave->wordlen > 32) { + printf("omap3_spi: invalid wordlen %d\n", slave->wordlen); + return -1; + } + + if (bitlen % slave->wordlen) + return -1; + + len = bitlen / slave->wordlen; +#else if (ds->slave.wordlen < 4 || ds->slave.wordlen > 32) { printf("omap3_spi: invalid wordlen %d\n", ds->slave.wordlen); return -1; @@ -415,41 +679,104 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, return -1; len = bitlen / ds->slave.wordlen; +#endif if (bitlen == 0) { /* only change CS */ - int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); + int chconf = readl(&ds->regs->channel[cs].chconf); if (flags & SPI_XFER_BEGIN) { - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN); +#ifdef CONFIG_DM_SPI + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN); +#else + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN); +#endif chconf |= OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); +#else + omap3_spi_write_chconf(ds, chconf); +#endif } if (flags & SPI_XFER_END) { chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; - omap3_spi_write_chconf(ds,chconf); - omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS); +#ifdef CONFIG_DM_SPI + omap3_spi_write_chconf(dev, chconf); + omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS); +#else + omap3_spi_write_chconf(ds, chconf); + omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS); +#endif } ret = 0; } else { +#ifdef CONFIG_DM_SPI + if (dout != NULL && din != NULL) + ret = omap3_spi_txrx(dev, len, dout, din, flags); + else if (dout != NULL) + ret = omap3_spi_write(dev, len, dout, flags); + else if (din != NULL) + ret = omap3_spi_read(dev, len, din, flags); +#else if (dout != NULL && din != NULL) ret = omap3_spi_txrx(slave, len, dout, din, flags); else if (dout != NULL) ret = omap3_spi_write(slave, len, dout, flags); else if (din != NULL) ret = omap3_spi_read(slave, len, din, flags); +#endif } return ret; } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +void spi_cs_activate(struct spi_slave *slave) { - return 1; } -void spi_cs_activate(struct spi_slave *slave) +void spi_cs_deactivate(struct spi_slave *slave) { } -void spi_cs_deactivate(struct spi_slave *slave) +#ifdef CONFIG_DM_SPI +static int omap3_spi_probe(struct udevice *dev) { + struct omap3_spi_slave *ds = dev_get_priv(dev); + + ds->regs = (struct mcspi *)dev_get_addr(dev); + + return 0; } + +static int omap3_spi_set_speed(struct udevice *dev, unsigned int speed) +{ + return 0; +} + +static int omap3_spi_set_mode(struct udevice *bus, uint mode) +{ + return 0; +} + + +static const struct dm_spi_ops omap3_spi_ops = { + .claim_bus = omap3_spi_claim_bus, + .release_bus = omap3_spi_release_bus, + .xfer = omap3_spi_xfer, + .set_speed = omap3_spi_set_speed, + .set_mode = omap3_spi_set_mode, +}; + +static const struct udevice_id omap3_spi_ids[] = { + { .compatible = "ti,omap2-mcspi" }, + { .compatible = "ti,omap4-mcspi" }, + { } +}; + +U_BOOT_DRIVER(omap3_spi) = { + .name = "omap3_spi", + .id = UCLASS_SPI, + .of_match = omap3_spi_ids, + .probe = omap3_spi_probe, + .ops = &omap3_spi_ops, + .priv_auto_alloc_size = sizeof(struct omap3_spi_slave), +}; +#endif diff --git a/drivers/spi/omap3_spi.h b/drivers/spi/omap3_spi.h index 6a07c6d..a974ca3 100644 --- a/drivers/spi/omap3_spi.h +++ b/drivers/spi/omap3_spi.h @@ -88,22 +88,34 @@ struct mcspi { #define OMAP3_MCSPI_WAKEUPENABLE_WKEN BIT(0) struct omap3_spi_slave { +#ifndef CONFIG_DM_SPI struct spi_slave slave; +#endif struct mcspi *regs; unsigned int freq; unsigned int mode; }; +#ifndef CONFIG_DM_SPI static inline struct omap3_spi_slave *to_omap3_spi(struct spi_slave *slave) { return container_of(slave, struct omap3_spi_slave, slave); } +#endif +#ifdef CONFIG_DM_SPI +int omap3_spi_txrx(struct udevice *dev, unsigned int len, const void *txp, + void *rxp, unsigned long flags); +int omap3_spi_write(struct udevice *dev, unsigned int len, const void *txp, + unsigned long flags); +int omap3_spi_read(struct udevice *dev, unsigned int len, void *rxp, + unsigned long flags); +#else int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, const void *txp, void *rxp, unsigned long flags); int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp, unsigned long flags); int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, unsigned long flags); - +#endif #endif /* _OMAP3_SPI_H_ */