coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pcf8523.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <commonlib/bsd/bcd.h>
4 #include <console/console.h>
5 #include <device/smbus.h>
6 #include <version.h>
7 #include "chip.h"
8 
9 /* Set RTC date from coreboot build date. */
10 static void pcf8523_set_build_date(struct device *dev)
11 {
16 }
17 
18 /* Set RTC date from user defined date (available in e.g. device tree). */
19 static void pcf8523_set_user_date(struct device *dev)
20 {
22  smbus_write_byte(dev, YEAR_REG, bin2bcd(config->user_year));
23  smbus_write_byte(dev, MONTH_REG, bin2bcd(config->user_month));
24  smbus_write_byte(dev, DAY_REG, bin2bcd(config->user_day));
25  smbus_write_byte(dev, WEEKDAY_REG, bin2bcd(config->user_weekday));
26 }
27 
28 static void pcf8523_final(struct device *dev)
29 {
30  /* Read back current RTC date and time and print it to the console. */
31  printk(BIOS_INFO, "%s: Current date %02d.%02d.%02d %02d:%02d:%02d\n",
32  dev->chip_ops->name,
39 }
40 
41 static void pcf8523_init(struct device *dev)
42 {
44  uint8_t reg = 0;
45 
46  if (!(smbus_read_byte(dev, SECOND_REG) & OS_BIT)) {
47  /* Set control registers to a known good value even if no
48  * power loss event was recognized. There were issues with
49  * this RTC in the past where control registers were
50  * corrupted and OS bit was not set. */
51  reg = smbus_read_byte(dev, CTRL_REG_1);
52  reg &= ~(STOP_BIT | CAP_SEL);
53  reg |= ((!!config->cap_sel) << 7);
54  smbus_write_byte(dev, CTRL_REG_1, reg);
55  reg = smbus_read_byte(dev, CTRL_REG_3);
56  reg &= ~PM_MASK;
57  reg |= ((config->power_mode & 0x07) << 5);
58  smbus_write_byte(dev, CTRL_REG_3, reg);
59  reg = smbus_read_byte(dev, TMR_CLKOUT_REG);
60  reg &= ~COF_MASK;
61  reg |= ((config->cof_selection & 0x07) << 3);
63  return;
64  }
65 
66  /* Initialize the RTC fully only if a power-loss event was recognized.
67  * In this case RTC will be set up with default date and time. */
68  smbus_write_byte(dev, CTRL_REG_1, ((!!config->cap_sel) << 7) |
69  ((!!config->second_int_en) << 2) |
70  ((!!config->alarm_int_en) << 1) |
71  (!!config->correction_int_en));
72 
73  smbus_write_byte(dev, CTRL_REG_2, ((!!config->wdt_int_en) << 2) |
74  ((!!config->tmrA_int_en) << 1) |
75  (!!config->tmrB_int_en));
76 
77  smbus_write_byte(dev, CTRL_REG_3, ((config->power_mode & 0x07) << 5) |
78  ((!!config->bat_switch_int_en) << 1) |
79  (!!config->bat_low_int_en));
80 
81  smbus_write_byte(dev, OFFSET_REG, ((!!config->offset_mode) << 7) |
82  (config->offset_val & 0x7f));
83 
84  smbus_write_byte(dev, TMR_CLKOUT_REG, ((!!config->tmrA_int_mode) << 7) |
85  ((!!config->tmrB_int_mode) << 6) |
86  ((config->cof_selection & 0x07) << 3) |
87  ((config->tmrA_mode & 0x03) << 1) |
88  (!!config->tmrB_mode));
89 
90  smbus_write_byte(dev, TMR_A_FREQ_REG, (config->tmrA_prescaler & 0x7));
91 
92  smbus_write_byte(dev, TMR_B_FREQ_REG, (config->tmrB_prescaler & 0x7) |
93  ((config->tmrB_pulse_cfg & 0x7) << 4));
94 
95  /* Before setting the clock stop oscillator. */
96  reg = smbus_read_byte(dev, CTRL_REG_1);
97  reg |= STOP_BIT;
98  smbus_write_byte(dev, CTRL_REG_1, reg);
99  if (config->set_user_date) {
100  /* Set user date defined in device tree. */
101  printk(BIOS_DEBUG, "%s: Set to user date\n",
102  dev->chip_ops->name);
104  } else {
105  /* Set date from coreboot build. */
106  printk(BIOS_DEBUG, "%s: Set to coreboot build date\n",
107  dev->chip_ops->name);
109  }
110  /* Set time to 01:00:00 */
111  smbus_write_byte(dev, HOUR_REG, 1);
112  smbus_write_byte(dev, MINUTE_REG, 0);
113  smbus_write_byte(dev, SECOND_REG, 0);
114  /* Start oscillator again as the clock is set up now */
115  reg &= ~STOP_BIT;
116  smbus_write_byte(dev, CTRL_REG_1, reg);
117 }
118 
119 static struct device_operations pcf8523c_ops = {
121  .set_resources = noop_set_resources,
122  .init = pcf8523_init,
123  .final = pcf8523_final
124 };
125 
126 static void pcf8523_enable(struct device *dev)
127 {
128  dev->ops = &pcf8523c_ops;
129 }
130 
132  CHIP_NAME("PCF8523")
133  .enable_dev = pcf8523_enable
134 };
static uint8_t bin2bcd(uint8_t val)
Definition: bcd.h:13
static uint8_t bcd2bin(uint8_t val)
Definition: bcd.h:8
#define printk(level,...)
Definition: stdlib.h:16
#define CHIP_NAME(X)
Definition: device.h:32
static void noop_read_resources(struct device *dev)
Standard device operations function pointers shims.
Definition: device.h:73
static void noop_set_resources(struct device *dev)
Definition: device.h:74
static int smbus_read_byte(struct device *const dev, u8 addr)
Definition: smbus.h:43
static int smbus_write_byte(struct device *const dev, u8 addr, u8 val)
Definition: smbus.h:48
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
enum board_config config
Definition: memory.c:448
static void pcf8523_set_build_date(struct device *dev)
Definition: pcf8523.c:10
static struct device_operations pcf8523c_ops
Definition: pcf8523.c:119
static void pcf8523_init(struct device *dev)
Definition: pcf8523.c:41
static void pcf8523_final(struct device *dev)
Definition: pcf8523.c:28
static void pcf8523_set_user_date(struct device *dev)
Definition: pcf8523.c:19
struct chip_operations drivers_i2c_pcf8523_ops
Definition: pcf8523.c:131
static void pcf8523_enable(struct device *dev)
Definition: pcf8523.c:126
#define HOUR_REG
Definition: pcf8523.h:18
#define CAP_SEL
Definition: pcf8523.h:11
#define MINUTE_REG
Definition: pcf8523.h:17
#define WEEKDAY_REG
Definition: pcf8523.h:20
#define OS_BIT
Definition: pcf8523.h:16
#define CTRL_REG_3
Definition: pcf8523.h:13
#define PM_MASK
Definition: pcf8523.h:14
#define COF_MASK
Definition: pcf8523.h:29
#define TMR_A_FREQ_REG
Definition: pcf8523.h:30
#define SECOND_REG
Definition: pcf8523.h:15
#define TMR_CLKOUT_REG
Definition: pcf8523.h:28
#define OFFSET_REG
Definition: pcf8523.h:27
#define STOP_BIT
Definition: pcf8523.h:10
#define CTRL_REG_2
Definition: pcf8523.h:12
#define DAY_REG
Definition: pcf8523.h:19
#define CTRL_REG_1
Definition: pcf8523.h:9
#define YEAR_REG
Definition: pcf8523.h:22
#define TMR_B_FREQ_REG
Definition: pcf8523.h:32
#define MONTH_REG
Definition: pcf8523.h:21
unsigned char uint8_t
Definition: stdint.h:8
unsigned char day
Definition: version.h:24
unsigned char year
Definition: version.h:22
unsigned char weekday
Definition: version.h:25
unsigned char month
Definition: version.h:23
const char * name
Definition: device.h:29
void(* read_resources)(struct device *dev)
Definition: device.h:39
Definition: device.h:107
struct chip_operations * chip_ops
Definition: device.h:144
struct device_operations * ops
Definition: device.h:143
DEVTREE_CONST void * chip_info
Definition: device.h:164
const struct bcd_date coreboot_build_date
Definition: version.c:39