Skip to content

Commit

Permalink
rtc: rx6110: add i2c support
Browse files Browse the repository at this point in the history
The RX6110 also supports I2C, so this patch adds support for it to the
driver.

This also renames the SPI specific functions and variables to include
`_spi_` in their names.

Signed-off-by: Claudius Heine <ch@denx.de>
Signed-off-by: Henning Schild <henning.schild@siemens.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20201117121817.953924-3-ch@denx.de
  • Loading branch information
Claudius Heine authored and Alexandre Belloni committed Nov 17, 2020
1 parent 7e6066c commit afa819c
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 32 deletions.
20 changes: 11 additions & 9 deletions drivers/rtc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -817,15 +817,6 @@ config RTC_DRV_RX4581
This driver can also be built as a module. If so the module
will be called rtc-rx4581.

config RTC_DRV_RX6110
tristate "Epson RX-6110"
select REGMAP_SPI
help
If you say yes here you will get support for the Epson RX-6110.

This driver can also be built as a module. If so the module
will be called rtc-rx6110.

config RTC_DRV_RS5C348
tristate "Ricoh RS5C348A/B"
help
Expand Down Expand Up @@ -936,6 +927,17 @@ config RTC_DRV_RV3029_HWMON
Say Y here if you want to expose temperature sensor data on
rtc-rv3029.

config RTC_DRV_RX6110
tristate "Epson RX-6110"
depends on RTC_I2C_AND_SPI
select REGMAP_SPI if SPI_MASTER
select REGMAP_I2C if I2C
help
If you say yes here you will get support for the Epson RX-6110.

This driver can also be built as a module. If so the module
will be called rtc-rx6110.

comment "Platform RTC drivers"

# this 'CMOS' RTC driver is arch dependent because it requires
Expand Down
165 changes: 142 additions & 23 deletions drivers/rtc/rtc-rx6110.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/i2c.h>

/* RX-6110 Register definitions */
#define RX6110_REG_SEC 0x10
Expand Down Expand Up @@ -310,6 +311,27 @@ static const struct rtc_class_ops rx6110_rtc_ops = {
.set_time = rx6110_set_time,
};

static int rx6110_probe(struct rx6110_data *rx6110, struct device *dev)
{
int err;

rx6110->rtc = devm_rtc_device_register(dev,
RX6110_DRIVER_NAME,
&rx6110_rtc_ops, THIS_MODULE);

if (IS_ERR(rx6110->rtc))
return PTR_ERR(rx6110->rtc);

err = rx6110_init(rx6110);
if (err)
return err;

rx6110->rtc->max_user_freq = 1;

return 0;
}

#ifdef CONFIG_SPI_MASTER
static struct regmap_config regmap_spi_config = {
.reg_bits = 8,
.val_bits = 8,
Expand All @@ -318,13 +340,12 @@ static struct regmap_config regmap_spi_config = {
};

/**
* rx6110_probe - initialize rtc driver
* rx6110_spi_probe - initialize rtc driver
* @spi: pointer to spi device
*/
static int rx6110_probe(struct spi_device *spi)
static int rx6110_spi_probe(struct spi_device *spi)
{
struct rx6110_data *rx6110;
int err;

if ((spi->bits_per_word && spi->bits_per_word != 8) ||
(spi->max_speed_hz > 2000000) ||
Expand All @@ -346,44 +367,142 @@ static int rx6110_probe(struct spi_device *spi)

spi_set_drvdata(spi, rx6110);

rx6110->rtc = devm_rtc_device_register(&spi->dev,
RX6110_DRIVER_NAME,
&rx6110_rtc_ops, THIS_MODULE);

if (IS_ERR(rx6110->rtc))
return PTR_ERR(rx6110->rtc);

err = rx6110_init(rx6110);
if (err)
return err;

rx6110->rtc->max_user_freq = 1;

return 0;
return rx6110_probe(rx6110, &spi->dev);
}

static const struct spi_device_id rx6110_id[] = {
static const struct spi_device_id rx6110_spi_id[] = {
{ "rx6110", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, rx6110_id);
MODULE_DEVICE_TABLE(spi, rx6110_spi_id);

static const struct of_device_id rx6110_spi_of_match[] = {
{ .compatible = "epson,rx6110" },
{ },
};
MODULE_DEVICE_TABLE(of, rx6110_spi_of_match);

static struct spi_driver rx6110_driver = {
static struct spi_driver rx6110_spi_driver = {
.driver = {
.name = RX6110_DRIVER_NAME,
.of_match_table = of_match_ptr(rx6110_spi_of_match),
},
.probe = rx6110_probe,
.id_table = rx6110_id,
.probe = rx6110_spi_probe,
.id_table = rx6110_spi_id,
};

static int rx6110_spi_register(void)
{
return spi_register_driver(&rx6110_spi_driver);
}

static void rx6110_spi_unregister(void)
{
spi_unregister_driver(&rx6110_spi_driver);
}
#else
static int rx6110_spi_register(void)
{
return 0;
}

static void rx6110_spi_unregister(void)
{
}
#endif /* CONFIG_SPI_MASTER */

#ifdef CONFIG_I2C
static struct regmap_config regmap_i2c_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RX6110_REG_IRQ,
.read_flag_mask = 0x80,
};

module_spi_driver(rx6110_driver);
static int rx6110_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rx6110_data *rx6110;

if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_I2C_BLOCK)) {
dev_err(&adapter->dev,
"doesn't support required functionality\n");
return -EIO;
}

rx6110 = devm_kzalloc(&client->dev, sizeof(*rx6110), GFP_KERNEL);
if (!rx6110)
return -ENOMEM;

rx6110->regmap = devm_regmap_init_i2c(client, &regmap_i2c_config);
if (IS_ERR(rx6110->regmap)) {
dev_err(&client->dev, "regmap init failed for rtc rx6110\n");
return PTR_ERR(rx6110->regmap);
}

i2c_set_clientdata(client, rx6110);

return rx6110_probe(rx6110, &client->dev);
}

static const struct i2c_device_id rx6110_i2c_id[] = {
{ "rx6110", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx6110_i2c_id);

static struct i2c_driver rx6110_i2c_driver = {
.driver = {
.name = RX6110_DRIVER_NAME,
},
.probe = rx6110_i2c_probe,
.id_table = rx6110_i2c_id,
};

static int rx6110_i2c_register(void)
{
return i2c_add_driver(&rx6110_i2c_driver);
}

static void rx6110_i2c_unregister(void)
{
i2c_del_driver(&rx6110_i2c_driver);
}
#else
static int rx6110_i2c_register(void)
{
return 0;
}

static void rx6110_i2c_unregister(void)
{
}
#endif /* CONFIG_I2C */

static int __init rx6110_module_init(void)
{
int ret;

ret = rx6110_spi_register();
if (ret)
return ret;

ret = rx6110_i2c_register();
if (ret)
rx6110_spi_unregister();

return ret;
}
module_init(rx6110_module_init);

static void __exit rx6110_module_exit(void)
{
rx6110_spi_unregister();
rx6110_i2c_unregister();
}
module_exit(rx6110_module_exit);

MODULE_AUTHOR("Val Krutov <val.krutov@erd.epson.com>");
MODULE_DESCRIPTION("RX-6110 SA RTC driver");
Expand Down

0 comments on commit afa819c

Please sign in to comment.