On x86 we use CMOS RAM to read and write some settings. Add basic support for this.
Signed-off-by: Simon Glass <s...@chromium.org> --- arch/x86/include/asm/cmos.h | 181 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 arch/x86/include/asm/cmos.h diff --git a/arch/x86/include/asm/cmos.h b/arch/x86/include/asm/cmos.h new file mode 100644 index 0000000..9e16301 --- /dev/null +++ b/arch/x86/include/asm/cmos.h @@ -0,0 +1,181 @@ +/* + * Taken from Coreboot mc146818rtc.h + * TODO: This should be an RTC driver + + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __ASM_CMOS_H +#define __ASM_CMOS_H + +#include <asm/io.h> + +#define RTC_BASE_PORT 0x70 + +#define RTC_PORT(x) (RTC_BASE_PORT + (x)) + +/* Control registers - Moto names */ +#define RTC_REG_A 10 +#define RTC_REG_B 11 +#define RTC_REG_C 12 +#define RTC_REG_D 13 + + +/* register details */ +#define RTC_FREQ_SELECT RTC_REG_A + +/* + * update-in-progress - set to "1" 244 microsecs before RTC goes off the bus, + * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete, + * totalling to a max high interval of 2.228 ms. + */ +#define RTC_UIP 0x80 +#define RTC_DIV_CTL 0x70 +/* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */ +#define RTC_REF_CLCK_4MHZ 0x00 +#define RTC_REF_CLCK_1MHZ 0x10 +#define RTC_REF_CLCK_32KHZ 0x20 +/* 2 values for divider stage reset, others for "testing purposes only" */ +#define RTC_DIV_RESET1 0x60 +#define RTC_DIV_RESET2 0x70 +/* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */ +#define RTC_RATE_SELECT 0x0f +#define RTC_RATE_NONE 0x00 +#define RTC_RATE_32786HZ 0x01 +#define RTC_RATE_16384HZ 0x02 +#define RTC_RATE_8192HZ 0x03 +#define RTC_RATE_4096HZ 0x04 +#define RTC_RATE_2048HZ 0x05 +#define RTC_RATE_1024HZ 0x06 +#define RTC_RATE_512HZ 0x07 +#define RTC_RATE_256HZ 0x08 +#define RTC_RATE_128HZ 0x09 +#define RTC_RATE_64HZ 0x0a +#define RTC_RATE_32HZ 0x0b +#define RTC_RATE_16HZ 0x0c +#define RTC_RATE_8HZ 0x0d +#define RTC_RATE_4HZ 0x0e +#define RTC_RATE_2HZ 0x0f + +/**********************************************************************/ +#define RTC_CONTROL RTC_REG_B +#define RTC_SET 0x80 /* disable updates for clock setting */ +#define RTC_PIE 0x40 /* periodic interrupt enable */ +#define RTC_AIE 0x20 /* alarm interrupt enable */ +#define RTC_UIE 0x10 /* update-finished interrupt enable */ +#define RTC_SQWE 0x08 /* enable square-wave output */ +#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ +#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ +#define RTC_DST_EN 0x01 /* auto switch DST - works for USA only */ + +/**********************************************************************/ +#define RTC_INTR_FLAGS RTC_REG_C +/* caution - cleared by read */ +#define RTC_IRQF 0x80 /* any of the following 3 is active */ +#define RTC_PF 0x40 +#define RTC_AF 0x20 +#define RTC_UF 0x10 + +/**********************************************************************/ +#define RTC_VALID RTC_REG_D +#define RTC_VRT 0x80 /* valid RAM and time */ +/**********************************************************************/ + +/* Date and Time in RTC CMOS */ +#define RTC_CLK_SECOND 0 +#define RTC_CLK_SECOND_ALARM 1 +#define RTC_CLK_MINUTE 2 +#define RTC_CLK_MINUTE_ALARM 3 +#define RTC_CLK_HOUR 4 +#define RTC_CLK_HOUR_ALARM 5 +#define RTC_CLK_DAYOFWEEK 6 +#define RTC_CLK_DAYOFMONTH 7 +#define RTC_CLK_MONTH 8 +#define RTC_CLK_YEAR 9 +#define RTC_CLK_ALTCENTURY 0x32 + +/* On PCs, the checksum is built only over bytes 16..45 */ +#define PC_CKS_RANGE_START 16 +#define PC_CKS_RANGE_END 45 +#define PC_CKS_LOC 46 + +static inline unsigned char cmos_read(unsigned char addr) +{ + int offs = 0; + + if (addr >= 128) { + offs = 2; + addr -= 128; + } + outb(addr, RTC_BASE_PORT + offs + 0); + + return inb(RTC_BASE_PORT + offs + 1); +} + +static inline void cmos_write_inner(unsigned char val, unsigned char addr) +{ + int offs = 0; + + if (addr >= 128) { + offs = 2; + addr -= 128; + } + outb(addr, RTC_BASE_PORT + offs + 0); + + outb(val, RTC_BASE_PORT + offs + 1); +} + +static inline void cmos_write(unsigned char val, unsigned char addr) +{ + int control_state = cmos_read(RTC_CONTROL); + + /* + * There are various places where RTC bits might be hiding, eg. the + * Century / AltCentury byte. So to be safe, disable RTC before + * changing any value. + */ + if ((addr != RTC_CONTROL) && !(control_state & RTC_SET)) + cmos_write_inner(control_state | RTC_SET, RTC_CONTROL); + cmos_write_inner(val, addr); + + /* reset to prior configuration */ + if ((addr != RTC_CONTROL) && !(control_state & RTC_SET)) + cmos_write_inner(control_state, RTC_CONTROL); +} + +static inline void cmos_disable_rtc(void) +{ + int control_state = cmos_read(RTC_CONTROL); + + cmos_write(control_state | RTC_SET, RTC_CONTROL); +} + +static inline void cmos_enable_rtc(void) +{ + int control_state = cmos_read(RTC_CONTROL); + + cmos_write(control_state & ~RTC_SET, RTC_CONTROL); +} + +static inline u32 cmos_read32(u8 offset) +{ + u32 value = 0; + int i; + + for (i = 0; i < sizeof(value); i++) + value |= cmos_read(offset + i) << (i << 3); + + return value; +} + +static inline void cmos_write32(u8 offset, u32 value) +{ + int i; + + for (i = 0; i < sizeof(value); i++) + cmos_write((value >> (i << 3)) & 0xff, offset + i); +} + +#endif -- 2.2.0.rc0.207.ga3a616c _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot