From 77a5b3701832801619dc13d3e902fd8a216e531b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Tue, 29 May 2012 11:06:28 +0200 Subject: mfd: Fix mc13xxx SPI regmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fix the SPI regmap configuration, the wrong write flag was used. Also, bits_per_word should not be set as the regmap spi implementation uses a 8bits transfert granularity. Signed-off-by: Philippe Rétornaz Tested-by: Fabio Estevam Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd/mc13xxx-spi.c') diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 3fcdab3eb8eb..5d1969f67d82 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -49,6 +49,7 @@ static struct regmap_config mc13xxx_regmap_spi_config = { .reg_bits = 7, .pad_bits = 1, .val_bits = 24, + .write_flag_mask = 0x80, .max_register = MC13XXX_NUMREGS, @@ -73,7 +74,6 @@ static int mc13xxx_spi_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, mc13xxx); spi->mode = SPI_MODE_0 | SPI_CS_HIGH; - spi->bits_per_word = 32; mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); -- cgit v1.2.1 From e4ecf6ea84d68aea5a9785e89f52672e1e126998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Tue, 29 May 2012 11:06:29 +0200 Subject: mfd: mc13xxx workaround SPI hardware bug on i.Mx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MC13xxx PMIC is mainly used on i.Mx SoC. On those 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 transfer 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 --- drivers/mfd/mc13xxx-spi.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'drivers/mfd/mc13xxx-spi.c') diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 5d1969f67d82..03df422feb76 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", -- cgit v1.2.1 From e7c706b1e5ccf28eaaf76c7a4613e80b0ca52863 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 29 Jun 2012 15:14:36 +0200 Subject: mfd: Use devm_* APIs for mc13xxx Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-spi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/mfd/mc13xxx-spi.c') diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 03df422feb76..234207f7a831 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -129,7 +129,7 @@ static int mc13xxx_spi_probe(struct spi_device *spi) if (of_id) sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data]; - mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); + mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL); if (!mc13xxx) return -ENOMEM; @@ -139,15 +139,12 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = regmap_init(&spi->dev, ®map_mc13xxx_bus, &spi->dev, - &mc13xxx_regmap_spi_config); - + mc13xxx->regmap = devm_regmap_init_spi(spi, &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", ret); dev_set_drvdata(&spi->dev, NULL); - kfree(mc13xxx); return ret; } -- cgit v1.2.1 From e03088972f6e38e90077eaf09acf7b8a327a2da2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Jul 2012 16:03:00 +0800 Subject: mfd: Fix mc13xxx-spi merge conflict This patch fixes conflict between commit 8ae3559 "mfd: mc13xxx workaround SPI hardware bug on i.Mx" and commit 10c7a5d "mfd: Use devm_* APIs for mc13xxx". commit 8ae3559 changes regmap_init_spi to regmap_init. So now we need to use devm_regmap_init rather than devm_regmap_init_spi. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/mfd/mc13xxx-spi.c') diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 234207f7a831..35636261da6c 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -139,7 +139,9 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = devm_regmap_init_spi(spi, &mc13xxx_regmap_spi_config); + mc13xxx->regmap = devm_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", -- cgit v1.2.1 From 8b8495532c6ba85221b0f9757e1581b52ed66c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 16 Jul 2012 15:40:17 +0200 Subject: mfd: Drop modifying mc13xxx driver's id_table in probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was introduced in commit 876989d (mfd: Add device tree probe support for mc13xxx) for spi and later while introducing support for i2c copied to the i2c driver. Modifying driver details is very strange, for example probing an mc13892 device (instantiated via dt) removes the driver's ability to handle (traditionally probed) mc13783 devices in this case. I'm not aware of any problems that make this hack necessary and if there were some, they'd have to be fixed in the spi/i2c core, not in a driver. Signed-off-by: Uwe Kleine-König Acked-by: Shawn Guo Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13xxx-spi.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/mfd/mc13xxx-spi.c') diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 35636261da6c..0bdb43a0aff0 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -119,16 +119,10 @@ static struct regmap_bus regmap_mc13xxx_bus = { static int mc13xxx_spi_probe(struct spi_device *spi) { - const struct of_device_id *of_id; - struct spi_driver *sdrv = to_spi_driver(spi->dev.driver); struct mc13xxx *mc13xxx; struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev); int ret; - of_id = of_match_device(mc13xxx_dt_ids, &spi->dev); - if (of_id) - sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data]; - mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL); if (!mc13xxx) return -ENOMEM; -- cgit v1.2.1