mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
![Uwe Kleine-König](/assets/img/avatar_default.png)
The value returned by an spi driver's remove function is mostly ignored. (Only an error message is printed if the value is non-zero that the error is ignored.) So change the prototype of the remove function to return no value. This way driver authors are not tempted to assume that passing an error to the upper layer is a good idea. All drivers are adapted accordingly. There is no intended change of behaviour, all callbacks were prepared to return 0 before. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Acked-by: Marc Kleine-Budde <mkl@pengutronix.de> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Acked-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Acked-by: Miquel Raynal <miquel.raynal@bootlin.com> Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Acked-by: Claudius Heine <ch@denx.de> Acked-by: Stefan Schmidt <stefan@datenfreihafen.org> Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Acked-by: Ulf Hansson <ulf.hansson@linaro.org> # For MMC Acked-by: Marcus Folkesson <marcus.folkesson@gmail.com> Acked-by: Łukasz Stelmach <l.stelmach@samsung.com> Acked-by: Lee Jones <lee.jones@linaro.org> Link: https://lore.kernel.org/r/20220123175201.34839-6-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown <broonie@kernel.org>
161 lines
3.5 KiB
C
161 lines
3.5 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* ST Microelectronics MFD: stmpe's spi client specific driver
|
|
*
|
|
* Copyright (C) ST Microelectronics SA 2011
|
|
*
|
|
* Author: Viresh Kumar <vireshk@kernel.org> for ST Microelectronics
|
|
*/
|
|
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of.h>
|
|
#include <linux/types.h>
|
|
#include "stmpe.h"
|
|
|
|
#define READ_CMD (1 << 7)
|
|
|
|
static int spi_reg_read(struct stmpe *stmpe, u8 reg)
|
|
{
|
|
struct spi_device *spi = stmpe->client;
|
|
int status = spi_w8r16(spi, reg | READ_CMD);
|
|
|
|
return (status < 0) ? status : status >> 8;
|
|
}
|
|
|
|
static int spi_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
|
|
{
|
|
struct spi_device *spi = stmpe->client;
|
|
u16 cmd = (val << 8) | reg;
|
|
|
|
return spi_write(spi, (const u8 *)&cmd, 2);
|
|
}
|
|
|
|
static int spi_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
|
|
{
|
|
int ret, i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
ret = spi_reg_read(stmpe, reg + i);
|
|
if (ret < 0)
|
|
return ret;
|
|
*(values + i) = ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int spi_block_write(struct stmpe *stmpe, u8 reg, u8 length,
|
|
const u8 *values)
|
|
{
|
|
int ret = 0, i;
|
|
|
|
for (i = length; i > 0; i--, reg++) {
|
|
ret = spi_reg_write(stmpe, reg, *(values + i - 1));
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void spi_init(struct stmpe *stmpe)
|
|
{
|
|
struct spi_device *spi = stmpe->client;
|
|
|
|
spi->bits_per_word = 8;
|
|
|
|
/* This register is only present for stmpe811 */
|
|
if (stmpe->variant->id_val == 0x0811)
|
|
spi_reg_write(stmpe, STMPE811_REG_SPI_CFG, spi->mode);
|
|
|
|
if (spi_setup(spi) < 0)
|
|
dev_dbg(&spi->dev, "spi_setup failed\n");
|
|
}
|
|
|
|
static struct stmpe_client_info spi_ci = {
|
|
.read_byte = spi_reg_read,
|
|
.write_byte = spi_reg_write,
|
|
.read_block = spi_block_read,
|
|
.write_block = spi_block_write,
|
|
.init = spi_init,
|
|
};
|
|
|
|
static int
|
|
stmpe_spi_probe(struct spi_device *spi)
|
|
{
|
|
const struct spi_device_id *id = spi_get_device_id(spi);
|
|
|
|
/* don't exceed max specified rate - 1MHz - Limitation of STMPE */
|
|
if (spi->max_speed_hz > 1000000) {
|
|
dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
|
|
(spi->max_speed_hz/1000));
|
|
return -EINVAL;
|
|
}
|
|
|
|
spi_ci.irq = spi->irq;
|
|
spi_ci.client = spi;
|
|
spi_ci.dev = &spi->dev;
|
|
|
|
return stmpe_probe(&spi_ci, id->driver_data);
|
|
}
|
|
|
|
static void stmpe_spi_remove(struct spi_device *spi)
|
|
{
|
|
struct stmpe *stmpe = spi_get_drvdata(spi);
|
|
|
|
stmpe_remove(stmpe);
|
|
}
|
|
|
|
static const struct of_device_id stmpe_spi_of_match[] = {
|
|
{ .compatible = "st,stmpe610", },
|
|
{ .compatible = "st,stmpe801", },
|
|
{ .compatible = "st,stmpe811", },
|
|
{ .compatible = "st,stmpe1601", },
|
|
{ .compatible = "st,stmpe2401", },
|
|
{ .compatible = "st,stmpe2403", },
|
|
{ /* sentinel */ },
|
|
};
|
|
MODULE_DEVICE_TABLE(of, stmpe_spi_of_match);
|
|
|
|
static const struct spi_device_id stmpe_spi_id[] = {
|
|
{ "stmpe610", STMPE610 },
|
|
{ "stmpe801", STMPE801 },
|
|
{ "stmpe811", STMPE811 },
|
|
{ "stmpe1601", STMPE1601 },
|
|
{ "stmpe2401", STMPE2401 },
|
|
{ "stmpe2403", STMPE2403 },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(spi, stmpe_id);
|
|
|
|
static struct spi_driver stmpe_spi_driver = {
|
|
.driver = {
|
|
.name = "stmpe-spi",
|
|
.of_match_table = of_match_ptr(stmpe_spi_of_match),
|
|
#ifdef CONFIG_PM
|
|
.pm = &stmpe_dev_pm_ops,
|
|
#endif
|
|
},
|
|
.probe = stmpe_spi_probe,
|
|
.remove = stmpe_spi_remove,
|
|
.id_table = stmpe_spi_id,
|
|
};
|
|
|
|
static int __init stmpe_init(void)
|
|
{
|
|
return spi_register_driver(&stmpe_spi_driver);
|
|
}
|
|
subsys_initcall(stmpe_init);
|
|
|
|
static void __exit stmpe_exit(void)
|
|
{
|
|
spi_unregister_driver(&stmpe_spi_driver);
|
|
}
|
|
module_exit(stmpe_exit);
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver");
|
|
MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>");
|