mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 21:02:19 +00:00
RTC for 6.1
Drivers: - switch to devm_clk_get_enabled() where relevant - cmos: event handler registration fix - isl12022: code improvements -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmNJ2cwACgkQY6TcMGxw OjJe8Q//UBAMgQ24Qsxnj8lJ/T9yp/FD1eMJmc80Fx4rf0oBq3qhDEA61hRMK6Gm ojqvlSL+H/flmVR32mzSZXEN61KU/tWUKBDeogTNZOnJHfh1X5f0qXZnmmCs+N8J IyA1dr8mtul67Mw9NdnoDOFVKLvLwFviPPjw8sv9ZuAS937eUlmGWUnE/y/g1FJh xaU+Wa9ynBnn5mJWWYQPM25YXSZ5dkcVGZVFI8BwqpaAPq/qVEPfkjtq9yjI+9vA GFRaEcSzacWsZle0GJU1fHIe3XAQM9Bn9YItVr6EzGJVn5vcjnzuVJzNWZ3EI1bB 8Llf4R2TgSksIRvvytDnKOlUr9+DjXWwU7okScNiYbpV1h9KYUjrUi0T4DBfvcSA V1U1AiA6vG5y/pX3+x+X6MxrTbRvS57HC7rNXlFCGTgi7vS84iPCVya+3PTm5MD6 ad8DLT7BUjtejNfGNzAOGc5sWiGIw/wx3A5aOfgz/0c1FDZ2D4txPu7rSwEpWJRa g2q0TxFTrwWpzULgh6hbGQKZxx+77Ow8nftMO8caxrhwa2hy50HKSVNMBw9sobON 4CIuH4PvXRsXwzxIrOH/d9hLihiwCseWr+1xaLrNr+diKmdHxt3qiTpeCZsDyRG7 W9FHQNgSkPb71I1Vha6+UHxIaM+VW7HXKtMjF1RwF80p2zwF9+k= =7smw -----END PGP SIGNATURE----- Merge tag 'rtc-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "A great rework of the isl12022 driver makes up the bulk of the changes. There is also an important fix for CMOS and then the usual small fixes: - switch to devm_clk_get_enabled() where relevant - cmos: event handler registration fix - isl12022: code improvements" * tag 'rtc-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: rtc: rv3028: Fix codestyle errors rtc: cmos: Fix event handler registration ordering issue rtc: k3: Use devm_clk_get_enabled() helper rtc: jz4740: Use devm_clk_get_enabled() helper rtc: mpfs: Use devm_clk_get_enabled() helper rtc: ds1685: Fix spelling of function name in comment block rtc: isl12022: switch to using regmap API rtc: isl12022: drop redundant write to HR register rtc: isl12022: use dev_set_drvdata() instead of i2c_set_clientdata() rtc: isl12022: use %ptR rtc: isl12022: simplify some expressions rtc: isl12022: drop a dev_info() rtc: isl12022: specify range_min and range_max rtc: isl12022: stop using deprecated devm_rtc_device_register() rtc: stmp3xxx: Add failure handling for stmp3xxx_wdt_register() rtc: mxc: Use devm_clk_get_enabled() helper rtc: gamecube: Always reset HW_SRNPROT after read rtc: k3: detect SoC to determine erratum fix rtc: k3: wait until the unlock field is not zero rtc: mpfs: Remove printing of stray CR
This commit is contained in:
commit
b7270c69a3
@ -423,6 +423,7 @@ config RTC_DRV_ISL1208
|
||||
|
||||
config RTC_DRV_ISL12022
|
||||
tristate "Intersil ISL12022"
|
||||
select REGMAP_I2C
|
||||
help
|
||||
If you say yes here you get support for the
|
||||
Intersil ISL12022 RTC chip.
|
||||
|
@ -1352,10 +1352,10 @@ static void cmos_check_acpi_rtc_status(struct device *dev,
|
||||
|
||||
static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
||||
{
|
||||
cmos_wake_setup(&pnp->dev);
|
||||
int irq, ret;
|
||||
|
||||
if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) {
|
||||
unsigned int irq = 0;
|
||||
irq = 0;
|
||||
#ifdef CONFIG_X86
|
||||
/* Some machines contain a PNP entry for the RTC, but
|
||||
* don't define the IRQ. It should always be safe to
|
||||
@ -1364,13 +1364,17 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
||||
if (nr_legacy_irqs())
|
||||
irq = RTC_IRQ;
|
||||
#endif
|
||||
return cmos_do_probe(&pnp->dev,
|
||||
pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
|
||||
} else {
|
||||
return cmos_do_probe(&pnp->dev,
|
||||
pnp_get_resource(pnp, IORESOURCE_IO, 0),
|
||||
pnp_irq(pnp, 0));
|
||||
irq = pnp_irq(pnp, 0);
|
||||
}
|
||||
|
||||
ret = cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmos_wake_setup(&pnp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cmos_pnp_remove(struct pnp_dev *pnp)
|
||||
@ -1454,10 +1458,9 @@ static inline void cmos_of_init(struct platform_device *pdev) {}
|
||||
static int __init cmos_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *resource;
|
||||
int irq;
|
||||
int irq, ret;
|
||||
|
||||
cmos_of_init(pdev);
|
||||
cmos_wake_setup(&pdev->dev);
|
||||
|
||||
if (RTC_IOMAPPED)
|
||||
resource = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||
@ -1467,7 +1470,13 @@ static int __init cmos_platform_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
irq = -1;
|
||||
|
||||
return cmos_do_probe(&pdev->dev, resource, irq);
|
||||
ret = cmos_do_probe(&pdev->dev, resource, irq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmos_wake_setup(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmos_platform_remove(struct platform_device *pdev)
|
||||
|
@ -132,7 +132,7 @@ ds1685_rtc_bin2bcd(struct ds1685_priv *rtc, u8 val, u8 bin_mask, u8 bcd_mask)
|
||||
}
|
||||
|
||||
/**
|
||||
* s1685_rtc_check_mday - check validity of the day of month.
|
||||
* ds1685_rtc_check_mday - check validity of the day of month.
|
||||
* @rtc: pointer to the ds1685 rtc structure.
|
||||
* @mday: day of month.
|
||||
*
|
||||
|
@ -265,18 +265,17 @@ static int gamecube_rtc_read_offset_from_sram(struct priv *d)
|
||||
* SRAM address as on previous consoles.
|
||||
*/
|
||||
ret = regmap_read(d->regmap, RTC_SRAM_BIAS, &d->rtc_bias);
|
||||
if (ret) {
|
||||
pr_err("failed to get the RTC bias\n");
|
||||
iounmap(hw_srnprot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reset SRAM access to how it was before, our job here is done. */
|
||||
if (old != 0x7bf)
|
||||
iowrite32be(old, hw_srnprot);
|
||||
|
||||
iounmap(hw_srnprot);
|
||||
|
||||
return 0;
|
||||
if (ret)
|
||||
pr_err("failed to get the RTC bias\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct regmap_range rtc_rd_ranges[] = {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* ISL register offsets */
|
||||
#define ISL12022_REG_SC 0x00
|
||||
@ -42,83 +43,32 @@ static struct i2c_driver isl12022_driver;
|
||||
|
||||
struct isl12022 {
|
||||
struct rtc_device *rtc;
|
||||
|
||||
bool write_enabled; /* true if write enable is set */
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
|
||||
static int isl12022_read_regs(struct i2c_client *client, uint8_t reg,
|
||||
uint8_t *data, size_t n)
|
||||
{
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = data
|
||||
}, /* setup read ptr */
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = n,
|
||||
.buf = data
|
||||
}
|
||||
};
|
||||
|
||||
int ret;
|
||||
|
||||
data[0] = reg;
|
||||
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret != ARRAY_SIZE(msgs)) {
|
||||
dev_err(&client->dev, "%s: read error, ret=%d\n",
|
||||
__func__, ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int isl12022_write_reg(struct i2c_client *client,
|
||||
uint8_t reg, uint8_t val)
|
||||
{
|
||||
uint8_t data[2] = { reg, val };
|
||||
int err;
|
||||
|
||||
err = i2c_master_send(client, data, sizeof(data));
|
||||
if (err != sizeof(data)) {
|
||||
dev_err(&client->dev,
|
||||
"%s: err=%d addr=%02x, data=%02x\n",
|
||||
__func__, err, data[0], data[1]);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* In the routines that deal directly with the isl12022 hardware, we use
|
||||
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
|
||||
*/
|
||||
static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct isl12022 *isl12022 = dev_get_drvdata(dev);
|
||||
struct regmap *regmap = isl12022->regmap;
|
||||
uint8_t buf[ISL12022_REG_INT + 1];
|
||||
int ret;
|
||||
|
||||
ret = isl12022_read_regs(client, ISL12022_REG_SC, buf, sizeof(buf));
|
||||
ret = regmap_bulk_read(regmap, ISL12022_REG_SC, buf, sizeof(buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (buf[ISL12022_REG_SR] & (ISL12022_SR_LBAT85 | ISL12022_SR_LBAT75)) {
|
||||
dev_warn(&client->dev,
|
||||
dev_warn(dev,
|
||||
"voltage dropped below %u%%, "
|
||||
"date and time is not reliable.\n",
|
||||
buf[ISL12022_REG_SR] & ISL12022_SR_LBAT85 ? 85 : 75);
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
dev_dbg(dev,
|
||||
"%s: raw data is sec=%02x, min=%02x, hr=%02x, "
|
||||
"mday=%02x, mon=%02x, year=%02x, wday=%02x, "
|
||||
"sr=%02x, int=%02x",
|
||||
@ -141,65 +91,25 @@ static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
tm->tm_mon = bcd2bin(buf[ISL12022_REG_MO] & 0x1F) - 1;
|
||||
tm->tm_year = bcd2bin(buf[ISL12022_REG_YR]) + 100;
|
||||
|
||||
dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
|
||||
"mday=%d, mon=%d, year=%d, wday=%d\n",
|
||||
__func__,
|
||||
tm->tm_sec, tm->tm_min, tm->tm_hour,
|
||||
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
|
||||
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct isl12022 *isl12022 = i2c_get_clientdata(client);
|
||||
size_t i;
|
||||
struct isl12022 *isl12022 = dev_get_drvdata(dev);
|
||||
struct regmap *regmap = isl12022->regmap;
|
||||
int ret;
|
||||
uint8_t buf[ISL12022_REG_DW + 1];
|
||||
|
||||
dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
|
||||
"mday=%d, mon=%d, year=%d, wday=%d\n",
|
||||
__func__,
|
||||
tm->tm_sec, tm->tm_min, tm->tm_hour,
|
||||
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
|
||||
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
|
||||
|
||||
if (!isl12022->write_enabled) {
|
||||
|
||||
ret = isl12022_read_regs(client, ISL12022_REG_INT, buf, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check if WRTC (write rtc enable) is set factory default is
|
||||
* 0 (not set) */
|
||||
if (!(buf[0] & ISL12022_INT_WRTC)) {
|
||||
dev_info(&client->dev,
|
||||
"init write enable and 24 hour format\n");
|
||||
|
||||
/* Set the write enable bit. */
|
||||
ret = isl12022_write_reg(client,
|
||||
ISL12022_REG_INT,
|
||||
buf[0] | ISL12022_INT_WRTC);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Write to any RTC register to start RTC, we use the
|
||||
* HR register, setting the MIL bit to use the 24 hour
|
||||
* format. */
|
||||
ret = isl12022_read_regs(client, ISL12022_REG_HR,
|
||||
buf, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = isl12022_write_reg(client,
|
||||
ISL12022_REG_HR,
|
||||
buf[0] | ISL12022_HR_MIL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
isl12022->write_enabled = true;
|
||||
}
|
||||
/* Ensure the write enable bit is set. */
|
||||
ret = regmap_update_bits(regmap, ISL12022_REG_INT,
|
||||
ISL12022_INT_WRTC, ISL12022_INT_WRTC);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* hours, minutes and seconds */
|
||||
buf[ISL12022_REG_SC] = bin2bcd(tm->tm_sec);
|
||||
@ -216,15 +126,8 @@ static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
|
||||
buf[ISL12022_REG_DW] = tm->tm_wday & 0x07;
|
||||
|
||||
/* write register's data */
|
||||
for (i = 0; i < ARRAY_SIZE(buf); i++) {
|
||||
ret = isl12022_write_reg(client, ISL12022_REG_SC + i,
|
||||
buf[ISL12022_REG_SC + i]);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return regmap_bulk_write(isl12022->regmap, ISL12022_REG_SC,
|
||||
buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops isl12022_rtc_ops = {
|
||||
@ -232,6 +135,12 @@ static const struct rtc_class_ops isl12022_rtc_ops = {
|
||||
.set_time = isl12022_rtc_set_time,
|
||||
};
|
||||
|
||||
static const struct regmap_config regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.use_single_write = true,
|
||||
};
|
||||
|
||||
static int isl12022_probe(struct i2c_client *client)
|
||||
{
|
||||
struct isl12022 *isl12022;
|
||||
@ -243,13 +152,23 @@ static int isl12022_probe(struct i2c_client *client)
|
||||
GFP_KERNEL);
|
||||
if (!isl12022)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(&client->dev, isl12022);
|
||||
|
||||
i2c_set_clientdata(client, isl12022);
|
||||
isl12022->regmap = devm_regmap_init_i2c(client, ®map_config);
|
||||
if (IS_ERR(isl12022->regmap)) {
|
||||
dev_err(&client->dev, "regmap allocation failed\n");
|
||||
return PTR_ERR(isl12022->regmap);
|
||||
}
|
||||
|
||||
isl12022->rtc = devm_rtc_device_register(&client->dev,
|
||||
isl12022_driver.driver.name,
|
||||
&isl12022_rtc_ops, THIS_MODULE);
|
||||
return PTR_ERR_OR_ZERO(isl12022->rtc);
|
||||
isl12022->rtc = devm_rtc_allocate_device(&client->dev);
|
||||
if (IS_ERR(isl12022->rtc))
|
||||
return PTR_ERR(isl12022->rtc);
|
||||
|
||||
isl12022->rtc->ops = &isl12022_rtc_ops;
|
||||
isl12022->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
isl12022->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
|
||||
return devm_rtc_register_device(isl12022->rtc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
@ -257,11 +257,6 @@ static void jz4740_rtc_power_off(void)
|
||||
kernel_halt();
|
||||
}
|
||||
|
||||
static void jz4740_rtc_clk_disable(void *data)
|
||||
{
|
||||
clk_disable_unprepare(data);
|
||||
}
|
||||
|
||||
static const struct of_device_id jz4740_rtc_of_match[] = {
|
||||
{ .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 },
|
||||
{ .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 },
|
||||
@ -329,23 +324,9 @@ static int jz4740_rtc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(rtc->base))
|
||||
return PTR_ERR(rtc->base);
|
||||
|
||||
clk = devm_clk_get(dev, "rtc");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "Failed to get RTC clock\n");
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(dev, jz4740_rtc_clk_disable, clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register devm action\n");
|
||||
return ret;
|
||||
}
|
||||
clk = devm_clk_get_enabled(dev, "rtc");
|
||||
if (IS_ERR(clk))
|
||||
return dev_err_probe(dev, PTR_ERR(clk), "Failed to get RTC clock\n");
|
||||
|
||||
spin_lock_init(&rtc->lock);
|
||||
|
||||
|
@ -193,23 +193,6 @@ static int mpfs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct clk *mpfs_rtc_init_clk(struct device *dev)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
clk = devm_clk_get(dev, "rtc");
|
||||
if (IS_ERR(clk))
|
||||
return clk;
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk);
|
||||
return clk;
|
||||
}
|
||||
|
||||
static irqreturn_t mpfs_rtc_wakeup_irq_handler(int irq, void *dev)
|
||||
{
|
||||
struct mpfs_rtc_dev *rtcdev = dev;
|
||||
@ -233,7 +216,7 @@ static int mpfs_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mpfs_rtc_dev *rtcdev;
|
||||
struct clk *clk;
|
||||
u32 prescaler;
|
||||
unsigned long prescaler;
|
||||
int wakeup_irq, ret;
|
||||
|
||||
rtcdev = devm_kzalloc(&pdev->dev, sizeof(struct mpfs_rtc_dev), GFP_KERNEL);
|
||||
@ -251,7 +234,7 @@ static int mpfs_rtc_probe(struct platform_device *pdev)
|
||||
/* range is capped by alarm max, lower reg is 31:0 & upper is 10:0 */
|
||||
rtcdev->rtc->range_max = GENMASK_ULL(42, 0);
|
||||
|
||||
clk = mpfs_rtc_init_clk(&pdev->dev);
|
||||
clk = devm_clk_get_enabled(&pdev->dev, "rtc");
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
@ -275,14 +258,13 @@ static int mpfs_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
/* prescaler hardware adds 1 to reg value */
|
||||
prescaler = clk_get_rate(devm_clk_get(&pdev->dev, "rtcref")) - 1;
|
||||
|
||||
if (prescaler > MAX_PRESCALER_COUNT) {
|
||||
dev_dbg(&pdev->dev, "invalid prescaler %d\n", prescaler);
|
||||
dev_dbg(&pdev->dev, "invalid prescaler %lu\n", prescaler);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(prescaler, rtcdev->base + PRESCALER_REG);
|
||||
dev_info(&pdev->dev, "prescaler set to: 0x%X \r\n", prescaler);
|
||||
dev_info(&pdev->dev, "prescaler set to: %lu\n", prescaler);
|
||||
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
ret = dev_pm_set_wake_irq(&pdev->dev, wakeup_irq);
|
||||
|
@ -291,14 +291,6 @@ static const struct rtc_class_ops mxc_rtc_ops = {
|
||||
.alarm_irq_enable = mxc_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static void mxc_rtc_action(void *p)
|
||||
{
|
||||
struct rtc_plat_data *pdata = p;
|
||||
|
||||
clk_disable_unprepare(pdata->clk_ref);
|
||||
clk_disable_unprepare(pdata->clk_ipg);
|
||||
}
|
||||
|
||||
static int mxc_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
@ -341,33 +333,18 @@ static int mxc_rtc_probe(struct platform_device *pdev)
|
||||
rtc->range_max = (1 << 16) * 86400ULL - 1;
|
||||
}
|
||||
|
||||
pdata->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
pdata->clk_ipg = devm_clk_get_enabled(&pdev->dev, "ipg");
|
||||
if (IS_ERR(pdata->clk_ipg)) {
|
||||
dev_err(&pdev->dev, "unable to get ipg clock!\n");
|
||||
return PTR_ERR(pdata->clk_ipg);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(pdata->clk_ipg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pdata->clk_ref = devm_clk_get(&pdev->dev, "ref");
|
||||
pdata->clk_ref = devm_clk_get_enabled(&pdev->dev, "ref");
|
||||
if (IS_ERR(pdata->clk_ref)) {
|
||||
clk_disable_unprepare(pdata->clk_ipg);
|
||||
dev_err(&pdev->dev, "unable to get ref clock!\n");
|
||||
return PTR_ERR(pdata->clk_ref);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(pdata->clk_ref);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(pdata->clk_ipg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev, mxc_rtc_action, pdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rate = clk_get_rate(pdata->clk_ref);
|
||||
|
||||
if (rate == 32768)
|
||||
|
@ -521,10 +521,9 @@ static int rv3028_param_get(struct device *dev, struct rtc_param *param)
|
||||
{
|
||||
struct rv3028_data *rv3028 = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
u32 value;
|
||||
|
||||
switch(param->param) {
|
||||
u32 value;
|
||||
|
||||
case RTC_PARAM_BACKUP_SWITCH_MODE:
|
||||
ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
|
||||
if (ret < 0)
|
||||
@ -554,9 +553,9 @@ static int rv3028_param_get(struct device *dev, struct rtc_param *param)
|
||||
static int rv3028_param_set(struct device *dev, struct rtc_param *param)
|
||||
{
|
||||
struct rv3028_data *rv3028 = dev_get_drvdata(dev);
|
||||
u8 mode;
|
||||
|
||||
switch(param->param) {
|
||||
u8 mode;
|
||||
case RTC_PARAM_BACKUP_SWITCH_MODE:
|
||||
switch (param->uvalue) {
|
||||
case RTC_BSM_DISABLED:
|
||||
|
@ -107,6 +107,8 @@ static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
|
||||
wdt_pdev->dev.parent = &rtc_pdev->dev;
|
||||
wdt_pdev->dev.platform_data = &wdt_pdata;
|
||||
rc = platform_device_add(wdt_pdev);
|
||||
if (rc)
|
||||
platform_device_put(wdt_pdev);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sys_soc.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
@ -45,14 +46,6 @@
|
||||
#define K3RTC_MIN_OFFSET (-277761)
|
||||
#define K3RTC_MAX_OFFSET (277778)
|
||||
|
||||
/**
|
||||
* struct ti_k3_rtc_soc_data - Private of compatible data for ti-k3-rtc
|
||||
* @unlock_irq_erratum: Has erratum for unlock infinite IRQs (erratum i2327)
|
||||
*/
|
||||
struct ti_k3_rtc_soc_data {
|
||||
const bool unlock_irq_erratum;
|
||||
};
|
||||
|
||||
static const struct regmap_config ti_k3_rtc_regmap_config = {
|
||||
.name = "peripheral-registers",
|
||||
.reg_bits = 32,
|
||||
@ -118,7 +111,6 @@ static const struct reg_field ti_rtc_reg_fields[] = {
|
||||
* @rtc_dev: rtc device
|
||||
* @regmap: rtc mmio regmap
|
||||
* @r_fields: rtc register fields
|
||||
* @soc: SoC compatible match data
|
||||
*/
|
||||
struct ti_k3_rtc {
|
||||
unsigned int irq;
|
||||
@ -127,7 +119,6 @@ struct ti_k3_rtc {
|
||||
struct rtc_device *rtc_dev;
|
||||
struct regmap *regmap;
|
||||
struct regmap_field *r_fields[K3_RTC_MAX_FIELDS];
|
||||
const struct ti_k3_rtc_soc_data *soc;
|
||||
};
|
||||
|
||||
static int k3rtc_field_read(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f)
|
||||
@ -190,11 +181,22 @@ static int k3rtc_unlock_rtc(struct ti_k3_rtc *priv)
|
||||
|
||||
/* Skip fence since we are going to check the unlock bit as fence */
|
||||
ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_UNLOCK], ret,
|
||||
!ret, 2, priv->sync_timeout_us);
|
||||
ret, 2, priv->sync_timeout_us);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the list of SoCs affected by TI's i2327 errata causing the RTC
|
||||
* state-machine to break if not unlocked fast enough during boot. These
|
||||
* SoCs must have the bootloader unlock this device very early in the
|
||||
* boot-flow before we (Linux) can use this device.
|
||||
*/
|
||||
static const struct soc_device_attribute has_erratum_i2327[] = {
|
||||
{ .family = "AM62X", .revision = "SR1.0" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int k3rtc_configure(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
@ -208,7 +210,7 @@ static int k3rtc_configure(struct device *dev)
|
||||
*
|
||||
* In such occurrence, it is assumed that the RTC module is unusable
|
||||
*/
|
||||
if (priv->soc->unlock_irq_erratum) {
|
||||
if (soc_device_match(has_erratum_i2327)) {
|
||||
ret = k3rtc_check_unlocked(priv);
|
||||
/* If there is an error OR if we are locked, return error */
|
||||
if (ret) {
|
||||
@ -513,21 +515,12 @@ static struct nvmem_config ti_k3_rtc_nvmem_config = {
|
||||
|
||||
static int k3rtc_get_32kclk(struct device *dev, struct ti_k3_rtc *priv)
|
||||
{
|
||||
int ret;
|
||||
struct clk *clk;
|
||||
|
||||
clk = devm_clk_get(dev, "osc32k");
|
||||
clk = devm_clk_get_enabled(dev, "osc32k");
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, (void (*)(void *))clk_disable_unprepare, clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->rate_32k = clk_get_rate(clk);
|
||||
|
||||
/* Make sure we are exact 32k clock. Else, try to compensate delay */
|
||||
@ -542,24 +535,19 @@ static int k3rtc_get_32kclk(struct device *dev, struct ti_k3_rtc *priv)
|
||||
*/
|
||||
priv->sync_timeout_us = (u32)(DIV_ROUND_UP_ULL(1000000, priv->rate_32k) * 4);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int k3rtc_get_vbusclk(struct device *dev, struct ti_k3_rtc *priv)
|
||||
{
|
||||
int ret;
|
||||
struct clk *clk;
|
||||
|
||||
/* Note: VBUS isn't a context clock, it is needed for hardware operation */
|
||||
clk = devm_clk_get(dev, "vbus");
|
||||
clk = devm_clk_get_enabled(dev, "vbus");
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_add_action_or_reset(dev, (void (*)(void *))clk_disable_unprepare, clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ti_k3_rtc_probe(struct platform_device *pdev)
|
||||
@ -602,8 +590,6 @@ static int ti_k3_rtc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(priv->rtc_dev))
|
||||
return PTR_ERR(priv->rtc_dev);
|
||||
|
||||
priv->soc = of_device_get_match_data(dev);
|
||||
|
||||
priv->rtc_dev->ops = &ti_k3_rtc_ops;
|
||||
priv->rtc_dev->range_max = (1ULL << 48) - 1; /* 48Bit seconds */
|
||||
ti_k3_rtc_nvmem_config.priv = priv;
|
||||
@ -635,12 +621,8 @@ static int ti_k3_rtc_probe(struct platform_device *pdev)
|
||||
return devm_rtc_nvmem_register(priv->rtc_dev, &ti_k3_rtc_nvmem_config);
|
||||
}
|
||||
|
||||
static const struct ti_k3_rtc_soc_data ti_k3_am62_data = {
|
||||
.unlock_irq_erratum = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id ti_k3_rtc_of_match_table[] = {
|
||||
{.compatible = "ti,am62-rtc", .data = &ti_k3_am62_data},
|
||||
{.compatible = "ti,am62-rtc" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ti_k3_rtc_of_match_table);
|
||||
|
Loading…
Reference in New Issue
Block a user