From patchwork Thu Jul 12 09:57:48 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= X-Patchwork-Id: 1188141 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 57027E0038 for ; Thu, 12 Jul 2012 10:10:26 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SpGHl-000066-Or; Thu, 12 Jul 2012 10:06:14 +0000 Received: from metis.ext.pengutronix.de ([2001:6f8:1178:4:290:27ff:fe1d:cc33]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1SpGAg-00073j-BO for linux-arm-kernel@lists.infradead.org; Thu, 12 Jul 2012 09:59:02 +0000 Received: from dude.hi.pengutronix.de ([2001:6f8:1178:2:21e:67ff:fe11:9c5c]) by metis.ext.pengutronix.de with esmtp (Exim 4.72) (envelope-from ) id 1SpG9o-0008VQ-7v; Thu, 12 Jul 2012 11:58:00 +0200 Received: from ukl by dude.hi.pengutronix.de with local (Exim 4.80) (envelope-from ) id 1SpG9n-00014L-4B; Thu, 12 Jul 2012 11:57:59 +0200 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= To: Samuel Ortiz Subject: [PATCH 2/7] MFD: mc13xxx workaround SPI hardware bug on i.Mx Date: Thu, 12 Jul 2012 11:57:48 +0200 Message-Id: <1342087073-3892-3-git-send-email-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1342087073-3892-1-git-send-email-u.kleine-koenig@pengutronix.de> References: <1342087073-3892-1-git-send-email-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:6f8:1178:2:21e:67ff:fe11:9c5c X-SA-Exim-Mail-From: ukl@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: "Ying-Chun Liu \(PaulLiu\)" , Mark Brown , linux-kernel@vger.kernel.org, kernel@pengutronix.de, =?UTF-8?q?Philippe=20R=C3=A9tornaz?= , Marc Reilly , linux-arm-kernel@lists.infradead.org, Samuel Ortiz X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Philippe Rétornaz The MC13xxx PMIC is mainly used on i.Mx SoC. On thoses SoC the SPI hardware will deassert CS line as soon as the SPI FIFO is empty. The MC13xxx hardware is very sensitive to CS line change as it corrupts the transfert if CS is deasserted in the middle of a register read or write. It is not possible to use the CS line as a GPIO on some SoC, so we need to workaround this by implementing a single SPI transfer to access the PMIC. Reviewed-by: Mark Brown Acked-by: Marc Reilly Signed-off-by: Philippe Rétornaz Signed-off-by: Samuel Ortiz Origin: next-20120712, commit:e4ecf6ea84d68aea5a9785e89f52672e1e126998 Signed-off-by: Uwe Kleine-König --- drivers/mfd/mc13xxx-spi.c | 65 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 5d1969f..03df422 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -54,6 +54,67 @@ static struct regmap_config mc13xxx_regmap_spi_config = { .max_register = MC13XXX_NUMREGS, .cache_type = REGCACHE_NONE, + .use_single_rw = 1, +}; + +static int mc13xxx_spi_read(void *context, const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + unsigned char w[4] = { *((unsigned char *) reg), 0, 0, 0}; + unsigned char r[4]; + unsigned char *p = val; + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + struct spi_transfer t = { + .tx_buf = w, + .rx_buf = r, + .len = 4, + }; + + struct spi_message m; + int ret; + + if (val_size != 3 || reg_size != 1) + return -ENOTSUPP; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(spi, &m); + + memcpy(p, &r[1], 3); + + return ret; +} + +static int mc13xxx_spi_write(void *context, const void *data, size_t count) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + + if (count != 4) + return -ENOTSUPP; + + return spi_write(spi, data, count); +} + +/* + * We cannot use regmap-spi generic bus implementation here. + * The MC13783 chip will get corrupted if CS signal is deasserted + * and on i.Mx31 SoC (the target SoC for MC13783 PMIC) the SPI controller + * has the following errata (DSPhl22960): + * "The CSPI negates SS when the FIFO becomes empty with + * SSCTL= 0. Software cannot guarantee that the FIFO will not + * drain because of higher priority interrupts and the + * non-realtime characteristics of the operating system. As a + * result, the SS will negate before all of the data has been + * transferred to/from the peripheral." + * We workaround this by accessing the SPI controller with a + * single transfert. + */ + +static struct regmap_bus regmap_mc13xxx_bus = { + .write = mc13xxx_spi_write, + .read = mc13xxx_spi_read, }; static int mc13xxx_spi_probe(struct spi_device *spi) @@ -78,7 +139,9 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = regmap_init_spi(spi, &mc13xxx_regmap_spi_config); + mc13xxx->regmap = regmap_init(&spi->dev, ®map_mc13xxx_bus, &spi->dev, + &mc13xxx_regmap_spi_config); + if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",