rtc: Add an RTC driver for the TI TPS65913 PMIC.

The TPS65913 PMIC has an RTC built into it. This change adds
a driver for it which implements the new RTC API.

BUG=chrome-os-partner:33764
BRANCH=None
TEST=Compiles and boots to kernel prompt on ryu. Timestamps for event log
verified across multiple boots.

Change-Id: I49ec9b78afc53f1cbd4be09e448cdae6077fb710
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: c16c11e620c830e7a73a2a24fe4823ccea0f3c39
Original-Change-Id: If1d549ea2361d0de6be75fd24b9e9810a6df7457
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/229414
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9425
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Furquan Shaikh 2014-11-12 16:23:00 -08:00 committed by Patrick Georgi
parent 7f4221c178
commit 8a1ee9bf70
5 changed files with 213 additions and 0 deletions

View File

@ -18,3 +18,4 @@
## ##
source src/drivers/ti/tps65090/Kconfig source src/drivers/ti/tps65090/Kconfig
source src/drivers/ti/tps65913/Kconfig

View File

@ -2,6 +2,7 @@
## This file is part of the coreboot project. ## This file is part of the coreboot project.
## ##
## Copyright (C) 2012 The Chromium OS Authors. ## Copyright (C) 2012 The Chromium OS Authors.
## Copyright 2014 Google Inc.
## ##
## This program is free software; you can redistribute it and/or modify ## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by ## it under the terms of the GNU General Public License as published by
@ -18,3 +19,4 @@
## ##
subdirs-$(CONFIG_DRIVER_TI_TPS65090) += tps65090/ subdirs-$(CONFIG_DRIVER_TI_TPS65090) += tps65090/
subdirs-$(CONFIG_DRIVERS_TI_TPS65913) += tps65913/

View File

@ -0,0 +1,35 @@
##
## This file is part of the coreboot project.
##
## Copyright 2014 Google Inc.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; version 2 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
config DRIVERS_TI_TPS65913
bool "TI TPS65913 support"
default n
config DRIVERS_TI_TPS65913_RTC
bool "TI TPS65913 RTC support"
default n
select DRIVERS_TI_TPS65913
config DRIVERS_TI_TPS65913_RTC_BUS
int "TI TPS65913 RTC bus"
depends on DRIVERS_TI_TPS65913_RTC
config DRIVERS_TI_TPS65913_RTC_ADDR
hex "TI TPS65913 RTC chip address"
depends on DRIVERS_TI_TPS65913_RTC

View File

@ -0,0 +1,20 @@
##
## This file is part of the coreboot project.
##
## Copyright 2014 Google Inc.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; version 2 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
ramstage-$(CONFIG_DRIVERS_TI_TPS65913_RTC) += tps65913rtc.c

View File

@ -0,0 +1,155 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2014 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <bcd.h>
#include <console/console.h>
#include <device/i2c.h>
#include <rtc.h>
#include <stdint.h>
enum TPS65913_RTC_REG {
TPS65913_SECONDS_REG = 0x00,
TPS65913_MINUTES_REG = 0x01,
TPS65913_HOURS_REG = 0x02,
TPS65913_DAYS_REG = 0x03,
TPS65913_MONTHS_REG = 0x04,
TPS65913_YEARS_REG = 0x05,
TPS65913_WEEKS_REG = 0x06,
TPS65913_RTC_CTRL_REG = 0x10,
TPS65913_RTC_STATUS_REG = 0x11,
TPS65913_RTC_INTERRUPS_REG = 0x12,
};
enum {
TPS65913_RTC_CTRL_STOP = (1 << 0),
TPS65913_RTC_CTRL_GET_TIME = (1 << 6),
TPS65913_RTC_STATUS_RUN = (1 << 1),
TPS65913_RTC_RUNNING = (1 << 1),
TPS65913_RTC_FROZEN = (0 << 1),
};
static inline uint8_t tps65913_read(enum TPS65913_RTC_REG reg)
{
uint8_t val;
i2c_readb(CONFIG_DRIVERS_TI_TPS65913_RTC_BUS,
CONFIG_DRIVERS_TI_TPS65913_RTC_ADDR, reg, &val);
return val;
}
static inline void tps65913_write(enum TPS65913_RTC_REG reg, uint8_t val)
{
i2c_writeb(CONFIG_DRIVERS_TI_TPS65913_RTC_BUS,
CONFIG_DRIVERS_TI_TPS65913_RTC_ADDR, reg, val);
}
static void tps65913_rtc_ctrl_clear(uint8_t bit)
{
uint8_t control = tps65913_read(TPS65913_RTC_CTRL_REG);
control &= ~bit;
tps65913_write(TPS65913_RTC_CTRL_REG, control);
}
static void tps65913_rtc_ctrl_set(uint8_t bit)
{
uint8_t control = tps65913_read(TPS65913_RTC_CTRL_REG);
control |= TPS65913_RTC_CTRL_GET_TIME;
tps65913_write(TPS65913_RTC_CTRL_REG, control);
}
static int tps65913_is_rtc_running(void)
{
uint8_t status = tps65913_read(TPS65913_RTC_STATUS_REG);
return ((status & TPS65913_RTC_STATUS_RUN) == TPS65913_RTC_RUNNING);
}
/*
* This function ensures that current time is copied to shadow registers. Then a
* normal read on TC registers reads from the shadow instead of current TC
* registers. This helps prevent the accidental change in counters while
* reading. In order to ensure that the current TC registers are copied into
* shadow registers, GET_TIME bit needs to be set to 0 and then to 1.
*/
static void tps65913_rtc_shadow(void)
{
tps65913_rtc_ctrl_clear(TPS65913_RTC_CTRL_GET_TIME);
tps65913_rtc_ctrl_set(TPS65913_RTC_CTRL_GET_TIME);
}
static int tps65913_rtc_stop(void)
{
/* Clearing stop bit freezes RTC */
tps65913_rtc_ctrl_clear(TPS65913_RTC_CTRL_STOP);
if (tps65913_is_rtc_running()) {
printk(BIOS_ERR, "Could not stop RTC\n");
return 1;
}
return 0;
}
static int tps65913_rtc_start(void)
{
/* Setting stop bit starts RTC */
tps65913_rtc_ctrl_set(TPS65913_RTC_CTRL_STOP);
if (!tps65913_is_rtc_running()) {
printk(BIOS_ERR, "Could not start RTC\n");
return 1;
}
return 0;
}
int rtc_set(const struct rtc_time *time)
{
/* Before setting the time, ensure that rtc is stopped */
if (tps65913_rtc_stop())
return 1;
tps65913_write(TPS65913_SECONDS_REG, bin2bcd(time->sec));
tps65913_write(TPS65913_MINUTES_REG, bin2bcd(time->min));
tps65913_write(TPS65913_HOURS_REG, bin2bcd(time->hour));
tps65913_write(TPS65913_DAYS_REG, bin2bcd(time->mday));
tps65913_write(TPS65913_MONTHS_REG, bin2bcd(time->mon));
tps65913_write(TPS65913_YEARS_REG, bin2bcd(time->year));
/* Re-start rtc */
if (tps65913_rtc_start())
return 1;
return 0;
}
int rtc_get(struct rtc_time *time)
{
tps65913_rtc_shadow();
time->sec = bcd2bin(tps65913_read(TPS65913_SECONDS_REG) & 0x7f);
time->min = bcd2bin(tps65913_read(TPS65913_MINUTES_REG) & 0x7f);
time->hour = bcd2bin(tps65913_read(TPS65913_HOURS_REG) & 0x3f);
time->mday = bcd2bin(tps65913_read(TPS65913_DAYS_REG) & 0x3f);
time->mon = bcd2bin(tps65913_read(TPS65913_MONTHS_REG) & 0x1f);
time->year = bcd2bin(tps65913_read(TPS65913_YEARS_REG) & 0xff);
return 0;
}