diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-vegman-kernel-add-RTC-driver-for-PCHC620.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-vegman-kernel-add-RTC-driver-for-PCHC620.patch | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-vegman-kernel-add-RTC-driver-for-PCHC620.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-vegman-kernel-add-RTC-driver-for-PCHC620.patch new file mode 100644 index 000000000..1622a01e5 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-vegman-kernel-add-RTC-driver-for-PCHC620.patch @@ -0,0 +1,205 @@ +From b80e1dea7595519edbabf3e12b6d31f0e128f901 Mon Sep 17 00:00:00 2001 +From: Ivan Mikhaylov <i.mikhaylov@yadro.com> +Date: Mon, 12 Jul 2021 10:46:22 +0300 +Subject: [PATCH] vegman: kernel: add RTC driver for PCHC620 + +Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com> +--- + drivers/rtc/Kconfig | 10 +++ + drivers/rtc/Makefile | 1 + + drivers/rtc/rtc-pchc620.c | 150 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 161 insertions(+) + create mode 100644 drivers/rtc/rtc-pchc620.c + +diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig +index 1adf9f815652..79aba84dd19f 100644 +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -564,6 +564,16 @@ config RTC_DRV_PALMAS + This driver can also be built as a module. If so, the module + will be called rtc-palma. + ++config RTC_DRV_PCHC620 ++ tristate "PCH C620 RTC driver" ++ help ++ If you say yes here you get support for the Intel C620 Series PCH ++ built-in read-only RTC. This driver is not for in-system use on x86, ++ but rather is for external access over I2C from a BMC. ++ ++ This driver can also be built as a module. If so, the module ++ will be called rtc-pchc620. ++ + config RTC_DRV_TPS6586X + tristate "TI TPS6586X RTC driver" + depends on MFD_TPS6586X +diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile +index 4ac8f19fb631..87ab76563a59 100644 +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -118,6 +118,7 @@ obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o + obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o + obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o + obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o ++obj-$(CONFIG_RTC_DRV_PCHC620) += rtc-pchc620.o + obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o + obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o + obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o +diff --git a/drivers/rtc/rtc-pchc620.c b/drivers/rtc/rtc-pchc620.c +new file mode 100644 +index 000000000000..a944b327ca67 +--- /dev/null ++++ b/drivers/rtc/rtc-pchc620.c +@@ -0,0 +1,150 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * RTC driver for PCHC620 ++ * Copyright (C) 2021 YADRO ++ */ ++ ++#include <linux/i2c.h> ++#include <linux/slab.h> ++#include <linux/rtc.h> ++#include <linux/bcd.h> ++#include <linux/module.h> ++#include <linux/regmap.h> ++ ++#define PCH_REG_FORCE_OFF 0x00 ++#define PCH_REG_SC 0x09 ++#define PCH_REG_MN 0x0a ++#define PCH_REG_HR 0x0b ++#define PCH_REG_DW 0x0c ++#define PCH_REG_DM 0x0d ++#define PCH_REG_MO 0x0e ++#define PCH_REG_YR 0x0f ++ ++#define NUM_TIME_REGS (PCH_REG_YR - PCH_REG_SC + 1) ++ ++struct pch { ++ struct rtc_device *rtc; ++ struct regmap *regmap; ++}; ++ ++static int pchc620_rtc_read_time(struct device *dev, struct rtc_time *tm) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct pch *pch = i2c_get_clientdata(client); ++ unsigned char rtc_data[NUM_TIME_REGS] = {0}; ++ int rc; ++ ++ rc = regmap_bulk_read(pch->regmap, PCH_REG_SC, rtc_data, NUM_TIME_REGS); ++ if (rc < 0) { ++ dev_err(dev, "Fail to read time reg(%d)\n", rc); ++ return rc; ++ } ++ ++ tm->tm_sec = bcd2bin(rtc_data[0]); ++ tm->tm_min = bcd2bin(rtc_data[1]); ++ tm->tm_hour = bcd2bin(rtc_data[2]); ++ tm->tm_wday = rtc_data[3]; ++ tm->tm_mday = bcd2bin(rtc_data[4]); ++ tm->tm_mon = bcd2bin(rtc_data[5]) - 1; ++ tm->tm_year = bcd2bin(rtc_data[6]) + 100; ++ ++ return 0; ++} ++ ++static ssize_t pch_force_off(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct pch *pch = i2c_get_clientdata(client); ++ unsigned long val; ++ int rc; ++ ++ if (kstrtoul(buf, 10, &val)) ++ return -EINVAL; ++ ++ if (val) { ++ /* 0x02 host force off */ ++ rc = regmap_write(pch->regmap, PCH_REG_FORCE_OFF, 0x2); ++ if (rc < 0) { ++ dev_err(dev, "Fail to read time reg(%d)\n", rc); ++ return rc; ++ } ++ } ++ ++ return 0; ++} ++static DEVICE_ATTR(force_off, S_IWUSR | S_IWGRP, NULL, pch_force_off); ++ ++static const struct rtc_class_ops pchc620_rtc_ops = { ++ .read_time = pchc620_rtc_read_time, ++}; ++ ++static const struct regmap_config pchc620_rtc_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .use_single_read = true, ++}; ++ ++static int pchc620_rtc_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pch *pch; ++ int rc; ++ ++ pch = devm_kzalloc(&client->dev, sizeof(*pch), GFP_KERNEL); ++ if (!pch) ++ return -ENOMEM; ++ ++ pch->regmap = devm_regmap_init_i2c(client, &pchc620_rtc_regmap_config); ++ if (IS_ERR(pch->regmap)) { ++ dev_err(&client->dev, "regmap_init failed\n"); ++ return PTR_ERR(pch->regmap); ++ } ++ ++ i2c_set_clientdata(client, pch); ++ ++ pch->rtc = devm_rtc_device_register(&client->dev, "pch-rtc", ++ &pchc620_rtc_ops, THIS_MODULE); ++ if (IS_ERR(pch->rtc)) ++ return PTR_ERR(pch->rtc); ++ ++ rc = sysfs_create_file(&client->dev.kobj, &dev_attr_force_off.attr); ++ if (rc) ++ return rc; ++ ++ return 0; ++} ++ ++static int pchc620_rtc_remove(struct i2c_client *client) ++{ ++ sysfs_remove_file(&client->dev.kobj, &dev_attr_force_off.attr); ++ return 0; ++} ++ ++static const struct i2c_device_id pchc620_rtc_id[] = { ++ { "pchc620-rtc", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, pchc620_rtc_id); ++ ++static const struct of_device_id pchc620_rtc_of_match[] = { ++ { .compatible = "rtc,pchc620", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pchc620_rtc_of_match); ++ ++static struct i2c_driver pchc620_rtc_driver = { ++ .driver = { ++ .name = "pchc620-rtc", ++ .of_match_table = pchc620_rtc_of_match, ++ }, ++ .probe = pchc620_rtc_probe, ++ .remove = pchc620_rtc_remove, ++ .id_table = pchc620_rtc_id, ++}; ++module_i2c_driver(pchc620_rtc_driver); ++ ++MODULE_DESCRIPTION("RTC PCHC620 driver"); ++MODULE_AUTHOR("Ivan Mikhaylov <i.mikhaylov@yadro.com>"); ++MODULE_LICENSE("GPL"); +-- +2.31.1 + |