// SPDX-License-Identifier: GPL-2.0-only #include #include #include #include #include #include #include #include struct abracon { struct rtc_device rtc; struct i2c_client *client; }; static inline struct abracon *to_abracon_priv(struct rtc_device *rtcdev) { return container_of(rtcdev, struct abracon, rtc); } static int abracon_get_time(struct rtc_device *rtcdev, struct rtc_time *t) { struct abracon *abracon = to_abracon_priv(rtcdev); struct i2c_client *client = abracon->client; u8 cp[7] = {}; u8 reg = 8; struct i2c_msg msg[2] = {}; int ret; msg[0].addr = client->addr; msg[0].buf = ® msg[0].len = 1; msg[1].addr = client->addr; msg[1].flags = I2C_M_RD; msg[1].buf = cp; msg[1].len = 7; ret = i2c_transfer(client->adapter, msg, 2); if (ret != 2) return -EIO; t->tm_sec = bcd2bin(cp[0]); t->tm_min = bcd2bin(cp[1]); t->tm_hour = bcd2bin(cp[2]); t->tm_mday = bcd2bin(cp[3]); t->tm_wday = bcd2bin(cp[4]); t->tm_mon = bcd2bin(cp[5]); t->tm_year = bcd2bin(cp[6]) + 100; return rtc_valid_tm(t); } static int abracon_set_time(struct rtc_device *rtcdev, struct rtc_time *t) { struct abracon *abracon = to_abracon_priv(rtcdev); struct i2c_client *client = abracon->client; u8 cp[8] = {}; int ret; cp[0] = 8; cp[1] = bin2bcd(t->tm_sec); cp[2] = bin2bcd(t->tm_min); cp[3] = bin2bcd(t->tm_hour); cp[4] = bin2bcd(t->tm_mday); cp[5] = bin2bcd(t->tm_wday); cp[6] = bin2bcd(t->tm_mon); cp[7] = bin2bcd(t->tm_year - 100); ret = i2c_master_send(client, cp, 8); if (ret != 8) return -EIO; return 0; } static const struct rtc_class_ops ds13xx_rtc_ops = { .read_time = abracon_get_time, .set_time = abracon_set_time, }; static int abracon_probe(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct abracon *abracon; abracon = xzalloc(sizeof(*abracon)); abracon->client = client; abracon->rtc.ops = &ds13xx_rtc_ops; abracon->rtc.dev = dev; return rtc_register(&abracon->rtc); }; static struct platform_device_id abracon_id[] = { { "ab-rtcmc-32.768khz-eoz9-s3", 0 }, { } }; static struct driver abracon_driver = { .name = "rtc-abracon", .probe = abracon_probe, .id_table = abracon_id, }; device_i2c_driver(abracon_driver);