Merge tag 'mfd-next-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "Core Frameworks:
   - Set 'struct device' fwnode when registering a new device

  New Drivers:
   - Add support for ROHM BD70528 PMIC

  New Device Support:
   - Add support for LP87561 4-Phase Regulator to TI LP87565 PMIC
   - Add support for RK809 and RK817 to Rockchip RK808
   - Add support for Lid Angle to ChromeOS core
   - Add support for CS47L15 CODEC to Madera core
   - Add support for CS47L92 CODEC to Madera core
   - Add support for ChromeOS (legacy) Accelerometers in ChromeOS core
   - Add support for Add Intel Elkhart Lake PCH to Intel LPSS

  New Functionality:
   - Provide regulator supply information when registering; madera-core
   - Additional Device Tree support; lp87565, madera, cros-ec, rohm,bd71837-pmic
   - Allow over-riding power button press via Device Tree; rohm-bd718x7
   - Differentiate between running processors; cros_ec_dev

  Fix-ups:
   - Big header file update; cros_ec_commands.h
   - Split header per-subsystem; rohm-bd718x7
   - Remove superfluous code; menelaus, cs5535-mfd, cs47lXX-tables
   - Trivial; sorting, coding style; intel-lpss-pci
   - Only remove Power Off functionality if set locally; rk808
   - Make use for Power Off Prepare(); rk808
   - Fix spelling mistake in header guards; stmfx
   - Properly free IDA resources
   - SPDX fixups; cs47lXX-tables, madera
   - Error path fixups; hi655x-pmic

  Bug Fixes:
   - Add missing break in case() statement
   - Repair undefined behaviour when not initialising variables; arizona-core, madera-core
   - Fix reference to Device Tree documentation; madera"

* tag 'mfd-next-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (45 commits)
  mfd: hi655x-pmic: Fix missing return value check for devm_regmap_init_mmio_clk
  mfd: madera: Fixup SPDX headers
  mfd: madera: Remove some unused registers and fix some defaults
  mfd: intel-lpss: Release IDA resources
  mfd: intel-lpss: Add Intel Elkhart Lake PCH PCI IDs
  mfd: cs5535-mfd: Remove ifdef OLPC noise
  mfd: stmfx: Fix macro definition spelling
  dt-bindings: mfd: Add link to ROHM BD71847 Datasheet
  MAINAINERS: Swap words in INTEL PMIC MULTIFUNCTION DEVICE DRIVERS
  mfd: cros_ec_dev: Register cros_ec_accel_legacy driver as a subdevice
  mfd: rk808: Prepare rk805 for poweroff
  mfd: rk808: Check pm_power_off pointer
  mfd: cros_ec: differentiate SCP from EC by feature bit
  dt-bindings: Add binding for cros-ec-rpmsg
  mfd: madera: Add Madera core support for CS47L92
  mfd: madera: Add Madera core support for CS47L15
  mfd: madera: Update DT bindings to add additional CODECs
  mfd: madera: Add supply mapping for MICVDD
  mfd: madera: Fix potential uninitialised use of variable
  mfd: madera: Fix bad reference to pinctrl.txt file
  ...
此提交包含在:
Linus Torvalds
2019-07-15 20:18:40 -07:00
當前提交 8de262531f
共有 57 個檔案被更改,包括 7525 行新增550 行删除

查看文件

@@ -374,11 +374,11 @@ config RTC_DRV_MAX77686
will be called rtc-max77686.
config RTC_DRV_RK808
tristate "Rockchip RK805/RK808/RK818 RTC"
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
depends on MFD_RK808
help
If you say yes here you will get support for the
RTC of RK805, RK808 and RK818 PMIC.
RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC.
This driver can also be built as a module. If so, the module
will be called rk808-rtc.
@@ -498,6 +498,14 @@ config RTC_DRV_M41T80_WDT
help
If you say Y here you will get support for the
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
config RTC_DRV_BD70528
tristate "ROHM BD70528 PMIC RTC"
help
If you say Y here you will get support for the RTC
on ROHM BD70528 Power Management IC.
This driver can also be built as a module. If so, the module
will be called rtc-bd70528.
config RTC_DRV_BQ32K
tristate "TI BQ32000"

查看文件

@@ -38,6 +38,7 @@ obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o
obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o
obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o

500
drivers/rtc/rtc-bd70528.c 一般檔案
查看文件

@@ -0,0 +1,500 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Copyright (C) 2018 ROHM Semiconductors
//
// RTC driver for ROHM BD70528 PMIC
#include <linux/bcd.h>
#include <linux/mfd/rohm-bd70528.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
/*
* We read regs RTC_SEC => RTC_YEAR
* this struct is ordered according to chip registers.
* Keep it u8 only to avoid padding issues.
*/
struct bd70528_rtc_day {
u8 sec;
u8 min;
u8 hour;
} __packed;
struct bd70528_rtc_data {
struct bd70528_rtc_day time;
u8 week;
u8 day;
u8 month;
u8 year;
} __packed;
struct bd70528_rtc_wake {
struct bd70528_rtc_day time;
u8 ctrl;
} __packed;
struct bd70528_rtc_alm {
struct bd70528_rtc_data data;
u8 alm_mask;
u8 alm_repeat;
} __packed;
struct bd70528_rtc {
struct rohm_regmap_dev *mfd;
struct device *dev;
};
static int bd70528_set_wake(struct rohm_regmap_dev *bd70528,
int enable, int *old_state)
{
int ret;
unsigned int ctrl_reg;
ret = regmap_read(bd70528->regmap, BD70528_REG_WAKE_EN, &ctrl_reg);
if (ret)
return ret;
if (old_state) {
if (ctrl_reg & BD70528_MASK_WAKE_EN)
*old_state |= BD70528_WAKE_STATE_BIT;
else
*old_state &= ~BD70528_WAKE_STATE_BIT;
if (!enable == !(*old_state & BD70528_WAKE_STATE_BIT))
return 0;
}
if (enable)
ctrl_reg |= BD70528_MASK_WAKE_EN;
else
ctrl_reg &= ~BD70528_MASK_WAKE_EN;
return regmap_write(bd70528->regmap, BD70528_REG_WAKE_EN,
ctrl_reg);
}
static int bd70528_set_elapsed_tmr(struct rohm_regmap_dev *bd70528,
int enable, int *old_state)
{
int ret;
unsigned int ctrl_reg;
/*
* TBD
* What is the purpose of elapsed timer ?
* Is the timeout registers counting down, or is the disable - re-enable
* going to restart the elapsed-time counting? If counting is restarted
* the timeout should be decreased by the amount of time that has
* elapsed since starting the timer. Maybe we should store the monotonic
* clock value when timer is started so that if RTC is set while timer
* is armed we could do the compensation. This is a hack if RTC/system
* clk are drifting. OTOH, RTC controlled via I2C is in any case
* inaccurate...
*/
ret = regmap_read(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
&ctrl_reg);
if (ret)
return ret;
if (old_state) {
if (ctrl_reg & BD70528_MASK_ELAPSED_TIMER_EN)
*old_state |= BD70528_ELAPSED_STATE_BIT;
else
*old_state &= ~BD70528_ELAPSED_STATE_BIT;
if ((!enable) == (!(*old_state & BD70528_ELAPSED_STATE_BIT)))
return 0;
}
if (enable)
ctrl_reg |= BD70528_MASK_ELAPSED_TIMER_EN;
else
ctrl_reg &= ~BD70528_MASK_ELAPSED_TIMER_EN;
return regmap_write(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
ctrl_reg);
}
static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
int *old_state)
{
int ret;
ret = bd70528_wdt_set(r->mfd, new_state & BD70528_WDT_STATE_BIT,
old_state);
if (ret) {
dev_err(r->dev,
"Failed to disable WDG for RTC setting (%d)\n", ret);
return ret;
}
ret = bd70528_set_elapsed_tmr(r->mfd,
new_state & BD70528_ELAPSED_STATE_BIT,
old_state);
if (ret) {
dev_err(r->dev,
"Failed to disable 'elapsed timer' for RTC setting\n");
return ret;
}
ret = bd70528_set_wake(r->mfd, new_state & BD70528_WAKE_STATE_BIT,
old_state);
if (ret) {
dev_err(r->dev,
"Failed to disable 'wake timer' for RTC setting\n");
return ret;
}
return ret;
}
static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r,
int old_state)
{
return bd70528_set_rtc_based_timers(r, old_state, NULL);
}
static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r,
int *old_state)
{
return bd70528_set_rtc_based_timers(r, 0, old_state);
}
static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d)
{
d->sec &= ~BD70528_MASK_RTC_SEC;
d->min &= ~BD70528_MASK_RTC_MINUTE;
d->hour &= ~BD70528_MASK_RTC_HOUR;
d->sec |= bin2bcd(t->tm_sec);
d->min |= bin2bcd(t->tm_min);
d->hour |= bin2bcd(t->tm_hour);
}
static inline void tm2rtc(struct rtc_time *t, struct bd70528_rtc_data *r)
{
r->day &= ~BD70528_MASK_RTC_DAY;
r->week &= ~BD70528_MASK_RTC_WEEK;
r->month &= ~BD70528_MASK_RTC_MONTH;
/*
* PM and 24H bits are not used by Wake - thus we clear them
* here and not in tmday2rtc() which is also used by wake.
*/
r->time.hour &= ~(BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H);
tmday2rtc(t, &r->time);
/*
* We do always set time in 24H mode.
*/
r->time.hour |= BD70528_MASK_RTC_HOUR_24H;
r->day |= bin2bcd(t->tm_mday);
r->week |= bin2bcd(t->tm_wday);
r->month |= bin2bcd(t->tm_mon + 1);
r->year = bin2bcd(t->tm_year - 100);
}
static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t)
{
t->tm_sec = bcd2bin(r->time.sec & BD70528_MASK_RTC_SEC);
t->tm_min = bcd2bin(r->time.min & BD70528_MASK_RTC_MINUTE);
t->tm_hour = bcd2bin(r->time.hour & BD70528_MASK_RTC_HOUR);
/*
* If RTC is in 12H mode, then bit BD70528_MASK_RTC_HOUR_PM
* is not BCD value but tells whether it is AM or PM
*/
if (!(r->time.hour & BD70528_MASK_RTC_HOUR_24H)) {
t->tm_hour %= 12;
if (r->time.hour & BD70528_MASK_RTC_HOUR_PM)
t->tm_hour += 12;
}
t->tm_mday = bcd2bin(r->day & BD70528_MASK_RTC_DAY);
t->tm_mon = bcd2bin(r->month & BD70528_MASK_RTC_MONTH) - 1;
t->tm_year = 100 + bcd2bin(r->year & BD70528_MASK_RTC_YEAR);
t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK);
}
static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
{
struct bd70528_rtc_wake wake;
struct bd70528_rtc_alm alm;
int ret;
struct bd70528_rtc *r = dev_get_drvdata(dev);
struct rohm_regmap_dev *bd70528 = r->mfd;
ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_WAKE_START,
&wake, sizeof(wake));
if (ret) {
dev_err(dev, "Failed to read wake regs\n");
return ret;
}
ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START,
&alm, sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
}
tm2rtc(&a->time, &alm.data);
tmday2rtc(&a->time, &wake.time);
if (a->enabled) {
alm.alm_mask &= ~BD70528_MASK_ALM_EN;
wake.ctrl |= BD70528_MASK_WAKE_EN;
} else {
alm.alm_mask |= BD70528_MASK_ALM_EN;
wake.ctrl &= ~BD70528_MASK_WAKE_EN;
}
ret = regmap_bulk_write(bd70528->regmap,
BD70528_REG_RTC_WAKE_START, &wake,
sizeof(wake));
if (ret) {
dev_err(dev, "Failed to set wake time\n");
return ret;
}
ret = regmap_bulk_write(bd70528->regmap, BD70528_REG_RTC_ALM_START,
&alm, sizeof(alm));
if (ret)
dev_err(dev, "Failed to set alarm time\n");
return ret;
}
static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)
{
struct bd70528_rtc_alm alm;
int ret;
struct bd70528_rtc *r = dev_get_drvdata(dev);
struct rohm_regmap_dev *bd70528 = r->mfd;
ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START,
&alm, sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
}
rtc2tm(&alm.data, &a->time);
a->time.tm_mday = -1;
a->time.tm_mon = -1;
a->time.tm_year = -1;
a->enabled = !(alm.alm_mask & BD70528_MASK_ALM_EN);
a->pending = 0;
return 0;
}
static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
{
int ret, tmpret, old_states;
struct bd70528_rtc_data rtc_data;
struct bd70528_rtc *r = dev_get_drvdata(dev);
struct rohm_regmap_dev *bd70528 = r->mfd;
ret = bd70528_disable_rtc_based_timers(r, &old_states);
if (ret)
return ret;
tmpret = regmap_bulk_read(bd70528->regmap,
BD70528_REG_RTC_START, &rtc_data,
sizeof(rtc_data));
if (tmpret) {
dev_err(dev, "Failed to read RTC time registers\n");
goto renable_out;
}
tm2rtc(t, &rtc_data);
tmpret = regmap_bulk_write(bd70528->regmap,
BD70528_REG_RTC_START, &rtc_data,
sizeof(rtc_data));
if (tmpret) {
dev_err(dev, "Failed to set RTC time\n");
goto renable_out;
}
renable_out:
ret = bd70528_re_enable_rtc_based_timers(r, old_states);
if (tmpret)
ret = tmpret;
return ret;
}
static int bd70528_set_time(struct device *dev, struct rtc_time *t)
{
int ret;
struct bd70528_rtc *r = dev_get_drvdata(dev);
bd70528_wdt_lock(r->mfd);
ret = bd70528_set_time_locked(dev, t);
bd70528_wdt_unlock(r->mfd);
return ret;
}
static int bd70528_get_time(struct device *dev, struct rtc_time *t)
{
struct bd70528_rtc *r = dev_get_drvdata(dev);
struct rohm_regmap_dev *bd70528 = r->mfd;
struct bd70528_rtc_data rtc_data;
int ret;
/* read the RTC date and time registers all at once */
ret = regmap_bulk_read(bd70528->regmap,
BD70528_REG_RTC_START, &rtc_data,
sizeof(rtc_data));
if (ret) {
dev_err(dev, "Failed to read RTC time (err %d)\n", ret);
return ret;
}
rtc2tm(&rtc_data, t);
return 0;
}
static int bd70528_alm_enable(struct device *dev, unsigned int enabled)
{
int ret;
unsigned int enableval = BD70528_MASK_ALM_EN;
struct bd70528_rtc *r = dev_get_drvdata(dev);
if (enabled)
enableval = 0;
bd70528_wdt_lock(r->mfd);
ret = bd70528_set_wake(r->mfd, enabled, NULL);
if (ret) {
dev_err(dev, "Failed to change wake state\n");
goto out_unlock;
}
ret = regmap_update_bits(r->mfd->regmap, BD70528_REG_RTC_ALM_MASK,
BD70528_MASK_ALM_EN, enableval);
if (ret)
dev_err(dev, "Failed to change alarm state\n");
out_unlock:
bd70528_wdt_unlock(r->mfd);
return ret;
}
static const struct rtc_class_ops bd70528_rtc_ops = {
.read_time = bd70528_get_time,
.set_time = bd70528_set_time,
.read_alarm = bd70528_read_alarm,
.set_alarm = bd70528_set_alarm,
.alarm_irq_enable = bd70528_alm_enable,
};
static irqreturn_t alm_hndlr(int irq, void *data)
{
struct rtc_device *rtc = data;
rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF | RTC_PF);
return IRQ_HANDLED;
}
static int bd70528_probe(struct platform_device *pdev)
{
struct bd70528_rtc *bd_rtc;
struct rohm_regmap_dev *mfd;
int ret;
struct rtc_device *rtc;
int irq;
unsigned int hr;
mfd = dev_get_drvdata(pdev->dev.parent);
if (!mfd) {
dev_err(&pdev->dev, "No MFD driver data\n");
return -EINVAL;
}
bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL);
if (!bd_rtc)
return -ENOMEM;
bd_rtc->mfd = mfd;
bd_rtc->dev = &pdev->dev;
irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm");
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get irq\n");
return irq;
}
platform_set_drvdata(pdev, bd_rtc);
ret = regmap_read(mfd->regmap, BD70528_REG_RTC_HOUR, &hr);
if (ret) {
dev_err(&pdev->dev, "Failed to reag RTC clock\n");
return ret;
}
if (!(hr & BD70528_MASK_RTC_HOUR_24H)) {
struct rtc_time t;
ret = bd70528_get_time(&pdev->dev, &t);
if (!ret)
ret = bd70528_set_time(&pdev->dev, &t);
if (ret) {
dev_err(&pdev->dev,
"Setting 24H clock for RTC failed\n");
return ret;
}
}
device_set_wakeup_capable(&pdev->dev, true);
device_wakeup_enable(&pdev->dev);
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc)) {
dev_err(&pdev->dev, "RTC device creation failed\n");
return PTR_ERR(rtc);
}
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
rtc->ops = &bd70528_rtc_ops;
/* Request alarm IRQ prior to registerig the RTC */
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr,
IRQF_ONESHOT, "bd70528-rtc", rtc);
if (ret)
return ret;
/*
* BD70528 irq controller is not touching the main mask register.
* So enable the RTC block interrupts at main level. We can just
* leave them enabled as irq-controller should disable irqs
* from sub-registers when IRQ is disabled or freed.
*/
ret = regmap_update_bits(mfd->regmap,
BD70528_REG_INT_MAIN_MASK,
BD70528_INT_RTC_MASK, 0);
if (ret) {
dev_err(&pdev->dev, "Failed to enable RTC interrupts\n");
return ret;
}
ret = rtc_register_device(rtc);
if (ret)
dev_err(&pdev->dev, "Registering RTC failed\n");
return ret;
}
static struct platform_driver bd70528_rtc = {
.driver = {
.name = "bd70528-rtc"
},
.probe = bd70528_probe,
};
module_platform_driver(bd70528_rtc);
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("BD70528 RTC driver");
MODULE_LICENSE("GPL");

查看文件

@@ -42,9 +42,18 @@
#define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1)
#define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1)
struct rk_rtc_compat_reg {
unsigned int ctrl_reg;
unsigned int status_reg;
unsigned int alarm_seconds_reg;
unsigned int int_reg;
unsigned int seconds_reg;
};
struct rk808_rtc {
struct rk808 *rk808;
struct rtc_device *rtc;
struct rk_rtc_compat_reg *creg;
int irq;
};
@@ -93,7 +102,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
int ret;
/* Force an update of the shadowed registers right now */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
BIT_RTC_CTRL_REG_RTC_GET_TIME,
BIT_RTC_CTRL_REG_RTC_GET_TIME);
if (ret) {
@@ -107,7 +116,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
* 32khz. If we clear the GET_TIME bit here, the time of i2c transfer
* certainly more than 31.25us: 16 * 2.5us at 400kHz bus frequency.
*/
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
BIT_RTC_CTRL_REG_RTC_GET_TIME,
0);
if (ret) {
@@ -115,7 +124,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
return ret;
}
ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG,
ret = regmap_bulk_read(rk808->regmap, rk808_rtc->creg->seconds_reg,
rtc_data, NUM_TIME_REGS);
if (ret) {
dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret);
@@ -154,7 +163,7 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_data[6] = bin2bcd(tm->tm_wday);
/* Stop RTC while updating the RTC registers */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
BIT_RTC_CTRL_REG_STOP_RTC_M,
BIT_RTC_CTRL_REG_STOP_RTC_M);
if (ret) {
@@ -162,14 +171,14 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
return ret;
}
ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG,
ret = regmap_bulk_write(rk808->regmap, rk808_rtc->creg->seconds_reg,
rtc_data, NUM_TIME_REGS);
if (ret) {
dev_err(dev, "Failed to bull write rtc_data: %d\n", ret);
return ret;
}
/* Start RTC again */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
BIT_RTC_CTRL_REG_STOP_RTC_M, 0);
if (ret) {
dev_err(dev, "Failed to update RTC control: %d\n", ret);
@@ -187,8 +196,13 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
uint32_t int_reg;
int ret;
ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG,
ret = regmap_bulk_read(rk808->regmap,
rk808_rtc->creg->alarm_seconds_reg,
alrm_data, NUM_ALARM_REGS);
if (ret) {
dev_err(dev, "Failed to read RTC alarm date REG: %d\n", ret);
return ret;
}
alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK);
alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK);
@@ -198,7 +212,7 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
rockchip_to_gregorian(&alrm->time);
ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
ret = regmap_read(rk808->regmap, rk808_rtc->creg->int_reg, &int_reg);
if (ret) {
dev_err(dev, "Failed to read RTC INT REG: %d\n", ret);
return ret;
@@ -217,7 +231,7 @@ static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc)
struct rk808 *rk808 = rk808_rtc->rk808;
int ret;
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0);
return ret;
@@ -228,7 +242,7 @@ static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc)
struct rk808 *rk808 = rk808_rtc->rk808;
int ret;
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
@@ -258,7 +272,8 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG,
ret = regmap_bulk_write(rk808->regmap,
rk808_rtc->creg->alarm_seconds_reg,
alrm_data, NUM_ALARM_REGS);
if (ret) {
dev_err(dev, "Failed to bulk write: %d\n", ret);
@@ -302,7 +317,7 @@ static irqreturn_t rk808_alarm_irq(int irq, void *data)
struct i2c_client *client = rk808->i2c;
int ret;
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg,
RTC_STATUS_MASK);
if (ret) {
dev_err(&client->dev,
@@ -353,6 +368,22 @@ static int rk808_rtc_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops,
rk808_rtc_suspend, rk808_rtc_resume);
static struct rk_rtc_compat_reg rk808_creg = {
.ctrl_reg = RK808_RTC_CTRL_REG,
.status_reg = RK808_RTC_STATUS_REG,
.alarm_seconds_reg = RK808_ALARM_SECONDS_REG,
.int_reg = RK808_RTC_INT_REG,
.seconds_reg = RK808_SECONDS_REG,
};
static struct rk_rtc_compat_reg rk817_creg = {
.ctrl_reg = RK817_RTC_CTRL_REG,
.status_reg = RK817_RTC_STATUS_REG,
.alarm_seconds_reg = RK817_ALARM_SECONDS_REG,
.int_reg = RK817_RTC_INT_REG,
.seconds_reg = RK817_SECONDS_REG,
};
static int rk808_rtc_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
@@ -363,11 +394,20 @@ static int rk808_rtc_probe(struct platform_device *pdev)
if (rk808_rtc == NULL)
return -ENOMEM;
switch (rk808->variant) {
case RK809_ID:
case RK817_ID:
rk808_rtc->creg = &rk817_creg;
break;
default:
rk808_rtc->creg = &rk808_creg;
break;
}
platform_set_drvdata(pdev, rk808_rtc);
rk808_rtc->rk808 = rk808;
/* start rtc running by default, and use shadowed timer. */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
BIT_RTC_CTRL_REG_STOP_RTC_M |
BIT_RTC_CTRL_REG_RTC_READSEL_M,
BIT_RTC_CTRL_REG_RTC_READSEL_M);
@@ -377,7 +417,7 @@ static int rk808_rtc_probe(struct platform_device *pdev)
return ret;
}
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg,
RTC_STATUS_MASK);
if (ret) {
dev_err(&pdev->dev,