Hi Simon, On Tue, Dec 30, 2014 at 9:12 AM, Simon Glass <s...@chromium.org> wrote: > On x86 we use CMOS RAM to read and write some settings. Add basic support > for this.
Should we consolidate the cmos support with the existing mc146818.c RTC driver? > 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 > -- Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot