diff options
author | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2016-03-11 20:22:28 -0800 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2016-04-19 18:34:18 +0200 |
commit | 86ddd732bd82b84724883b1f1579e18790611fe5 (patch) | |
tree | e52c4c88ceb7e14fd415031c56997d8c4054116e /src/drivers/pc80/mc146818rtc.c | |
parent | 3812597c668b795d4fc85578021e501f2a56f6b9 (diff) | |
download | coreboot-86ddd732bd82b84724883b1f1579e18790611fe5.tar.xz |
kbuild: Allow drivers to fit src/drivers/[X]/[Y]/ scheme
Reorder drivers to fit src/drivers/[X]/[Y]/ scheme to make
them pluggable.
Also, fix up the following driver subdirectories by switching
to the src/drivers/[X]/[Y]/ scheme as these are hard requirements
for the main change:
* drivers/intel
* drivers/pc80
* drivers/dec
Change-Id: I455d3089a317181d5b99bf658df759ec728a5f6b
Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-on: https://review.coreboot.org/14047
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/drivers/pc80/mc146818rtc.c')
-rw-r--r-- | src/drivers/pc80/mc146818rtc.c | 397 |
1 files changed, 0 insertions, 397 deletions
diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c deleted file mode 100644 index 6c39f812b9..0000000000 --- a/src/drivers/pc80/mc146818rtc.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering - * - * 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. - */ - -#include <arch/acpi.h> -#include <bcd.h> -#include <stdint.h> -#include <version.h> -#include <console/console.h> -#include <pc80/mc146818rtc.h> -#include <boot/coreboot_tables.h> -#include <rtc.h> -#include <string.h> -#include <cbfs.h> - -/* There's no way around this include guard. option_table.h is autogenerated */ -#if CONFIG_USE_OPTION_TABLE -#include "option_table.h" -#else -#define LB_CKS_RANGE_START 0 -#define LB_CKS_RANGE_END 0 -#define LB_CKS_LOC 0 -#endif - -#include <smp/spinlock.h> - -#if (defined(__PRE_RAM__) && \ -IS_ENABLED(CONFIG_HAVE_ROMSTAGE_NVRAM_CBFS_SPINLOCK)) - #define LOCK_NVRAM_CBFS_SPINLOCK spin_lock(romstage_nvram_cbfs_lock()); - #define UNLOCK_NVRAM_CBFS_SPINLOCK spin_unlock(romstage_nvram_cbfs_lock()); -#else - #define LOCK_NVRAM_CBFS_SPINLOCK - #define UNLOCK_NVRAM_CBFS_SPINLOCK -#endif - -static void cmos_reset_date(void) -{ - /* Now setup a default date equals to the build date */ - struct rtc_time time = { - .sec = 0, - .min = 0, - .hour = 1, - .mday = bcd2bin(coreboot_build_date.day), - .mon = bcd2bin(coreboot_build_date.month), - .year = (bcd2bin(coreboot_build_date.century) * 100) + - bcd2bin(coreboot_build_date.year), - .wday = bcd2bin(coreboot_build_date.weekday) - }; - rtc_set(&time); -} - -static int cmos_checksum_valid(int range_start, int range_end, int cks_loc) -{ - if (IS_ENABLED(CONFIG_STATIC_OPTION_TABLE)) - return 1; - - int i; - u16 sum, old_sum; - sum = 0; - for (i = range_start; i <= range_end; i++) - sum += cmos_read(i); - old_sum = ((cmos_read(cks_loc) << 8) | cmos_read(cks_loc + 1)) & - 0x0ffff; - return sum == old_sum; -} - -static void cmos_set_checksum(int range_start, int range_end, int cks_loc) -{ - int i; - u16 sum; - sum = 0; - for (i = range_start; i <= range_end; i++) - sum += cmos_read(i); - cmos_write(((sum >> 8) & 0x0ff), cks_loc); - cmos_write(((sum >> 0) & 0x0ff), cks_loc + 1); -} - -#define RTC_CONTROL_DEFAULT (RTC_24H) -#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) - -#ifndef __SMM__ -void cmos_init(bool invalid) -{ - bool cmos_invalid = invalid; - bool checksum_invalid = false; - bool clear_cmos; - size_t i; - uint8_t x; - -#ifndef __PRE_RAM__ - /* - * Avoid clearing pending interrupts and resetting the RTC control - * register in the resume path because the Linux kernel relies on - * this to know if it should restart the RTC timer queue if the wake - * was due to the RTC alarm. - */ - if (acpi_is_wakeup_s3()) - return; -#endif /* __PRE_RAM__ */ - - printk(BIOS_DEBUG, "RTC Init\n"); - - if (IS_ENABLED(CONFIG_USE_OPTION_TABLE)) { - /* See if there has been a CMOS power problem. */ - x = cmos_read(RTC_VALID); - cmos_invalid = !(x & RTC_VRT); - - /* See if there is a CMOS checksum error */ - checksum_invalid = !cmos_checksum_valid(PC_CKS_RANGE_START, - PC_CKS_RANGE_END, PC_CKS_LOC); - - clear_cmos = false; - } else { - clear_cmos = true; - } - - if (invalid || cmos_invalid || checksum_invalid) { - if (clear_cmos) { - cmos_write(0, 0x01); - cmos_write(0, 0x03); - cmos_write(0, 0x05); - for (i = 10; i < 128; i++) - cmos_write(0, i); - } - - if (cmos_invalid) - cmos_reset_date(); - - printk(BIOS_WARNING, "RTC:%s%s%s%s\n", - invalid ? " Clear requested":"", - cmos_invalid ? " Power Problem":"", - checksum_invalid ? " Checksum invalid":"", - clear_cmos ? " zeroing cmos":""); - } - - /* Setup the real time clock */ - cmos_write(RTC_CONTROL_DEFAULT, RTC_CONTROL); - /* Setup the frequency it operates at */ - cmos_write(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT); - /* Ensure all reserved bits are 0 in register D */ - cmos_write(RTC_VRT, RTC_VALID); - - if (IS_ENABLED(CONFIG_USE_OPTION_TABLE)) { - /* See if there is a LB CMOS checksum error */ - checksum_invalid = !cmos_checksum_valid(LB_CKS_RANGE_START, - LB_CKS_RANGE_END,LB_CKS_LOC); - if (checksum_invalid) - printk(BIOS_DEBUG, "RTC: coreboot checksum invalid\n"); - - /* Make certain we have a valid checksum */ - cmos_set_checksum(PC_CKS_RANGE_START, PC_CKS_RANGE_END, PC_CKS_LOC); - } - - /* Clear any pending interrupts */ - cmos_read(RTC_INTR_FLAGS); -} -#endif /* __SMM__ */ - - -/* - * This routine returns the value of the requested bits. - * input bit = bit count from the beginning of the cmos image - * length = number of bits to include in the value - * ret = a character pointer to where the value is to be returned - * returns CB_SUCCESS = successful, cb_err code if an error occurred - */ -static enum cb_err get_cmos_value(unsigned long bit, unsigned long length, - void *vret) -{ - unsigned char *ret; - unsigned long byte,byte_bit; - unsigned long i; - unsigned char uchar; - - /* - * The table is checked when it is built to ensure all - * values are valid. - */ - ret = vret; - byte = bit / 8; /* find the byte where the data starts */ - byte_bit = bit % 8; /* find the bit in the byte where the data starts */ - if (length < 9) { /* one byte or less */ - uchar = cmos_read(byte); /* load the byte */ - uchar >>= byte_bit; /* shift the bits to byte align */ - /* clear unspecified bits */ - ret[0] = uchar & ((1 << length) - 1); - } else { /* more that one byte so transfer the whole bytes */ - for (i = 0; length; i++, length -= 8, byte++) { - /* load the byte */ - ret[i] = cmos_read(byte); - } - } - return CB_SUCCESS; -} - -enum cb_err get_option(void *dest, const char *name) -{ - struct cmos_option_table *ct; - struct cmos_entries *ce; - size_t namelen; - int found = 0; - - if (!IS_ENABLED(CONFIG_USE_OPTION_TABLE)) - return CB_CMOS_OTABLE_DISABLED; - - LOCK_NVRAM_CBFS_SPINLOCK - - /* Figure out how long name is */ - namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); - - /* find the requested entry record */ - ct = cbfs_boot_map_with_leak("cmos_layout.bin", - CBFS_COMPONENT_CMOS_LAYOUT, NULL); - if (!ct) { - printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. " - "Options are disabled\n"); - - UNLOCK_NVRAM_CBFS_SPINLOCK - return CB_CMOS_LAYOUT_NOT_FOUND; - } - ce = (struct cmos_entries*)((unsigned char *)ct + ct->header_length); - for(; ce->tag == LB_TAG_OPTION; - ce = (struct cmos_entries*)((unsigned char *)ce + ce->size)) { - if (memcmp(ce->name, name, namelen) == 0) { - found = 1; - break; - } - } - if (!found) { - printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name); - UNLOCK_NVRAM_CBFS_SPINLOCK - return CB_CMOS_OPTION_NOT_FOUND; - } - - if (get_cmos_value(ce->bit, ce->length, dest) != CB_SUCCESS) { - UNLOCK_NVRAM_CBFS_SPINLOCK - return CB_CMOS_ACCESS_ERROR; - } - if (!cmos_checksum_valid(LB_CKS_RANGE_START, LB_CKS_RANGE_END, LB_CKS_LOC)) { - UNLOCK_NVRAM_CBFS_SPINLOCK - return CB_CMOS_CHECKSUM_INVALID; - } - UNLOCK_NVRAM_CBFS_SPINLOCK - return CB_SUCCESS; -} - -static enum cb_err set_cmos_value(unsigned long bit, unsigned long length, - void *vret) -{ - unsigned char *ret; - unsigned long byte,byte_bit; - unsigned long i; - unsigned char uchar, mask; - unsigned int chksum_update_needed = 0; - - ret = vret; - byte = bit / 8; /* find the byte where the data starts */ - byte_bit = bit % 8; /* find the bit where the data starts */ - if (length <= 8) { /* one byte or less */ - mask = (1 << length) - 1; - mask <<= byte_bit; - - uchar = cmos_read(byte); - uchar &= ~mask; - uchar |= (ret[0] << byte_bit); - cmos_write(uchar, byte); - if (byte >= LB_CKS_RANGE_START && byte <= LB_CKS_RANGE_END) - chksum_update_needed = 1; - } else { /* more that one byte so transfer the whole bytes */ - if (byte_bit || length % 8) - return CB_ERR_ARG; - - for (i = 0; length; i++, length -= 8, byte++) - cmos_write(ret[i], byte); - if (byte >= LB_CKS_RANGE_START && - byte <= LB_CKS_RANGE_END) - chksum_update_needed = 1; - } - - if (chksum_update_needed) { - cmos_set_checksum(LB_CKS_RANGE_START, LB_CKS_RANGE_END, - LB_CKS_LOC); - } - return CB_SUCCESS; -} - - -enum cb_err set_option(const char *name, void *value) -{ - struct cmos_option_table *ct; - struct cmos_entries *ce; - unsigned long length; - size_t namelen; - int found = 0; - - if (!IS_ENABLED(CONFIG_USE_OPTION_TABLE)) - return CB_CMOS_OTABLE_DISABLED; - - /* Figure out how long name is */ - namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); - - /* find the requested entry record */ - ct = cbfs_boot_map_with_leak("cmos_layout.bin", - CBFS_COMPONENT_CMOS_LAYOUT, NULL); - if (!ct) { - printk(BIOS_ERR, "cmos_layout.bin could not be found. " - "Options are disabled\n"); - return CB_CMOS_LAYOUT_NOT_FOUND; - } - ce = (struct cmos_entries*)((unsigned char *)ct + ct->header_length); - for(; ce->tag == LB_TAG_OPTION; - ce = (struct cmos_entries*)((unsigned char *)ce + ce->size)) { - if (memcmp(ce->name, name, namelen) == 0) { - found = 1; - break; - } - } - if (!found) { - printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name); - return CB_CMOS_OPTION_NOT_FOUND; - } - - length = ce->length; - if (ce->config == 's') { - length = MAX(strlen((const char *)value) * 8, ce->length - 8); - /* make sure the string is null terminated */ - if (set_cmos_value(ce->bit + ce->length - 8, 8, &(u8[]){0}) - != CB_SUCCESS) - return (CB_CMOS_ACCESS_ERROR); - } - - if (set_cmos_value(ce->bit, length, value) != CB_SUCCESS) - return (CB_CMOS_ACCESS_ERROR); - - return CB_SUCCESS; -} - -/* - * If the CMOS is cleared, the rtc_reg has the invalid date. That - * hurts some OSes. Even if we don't set USE_OPTION_TABLE, we need - * to make sure the date is valid. - */ -void cmos_check_update_date() -{ - u8 year, century; - - /* Assume hardware always supports RTC_CLK_ALTCENTURY. */ - century = cmos_read(RTC_CLK_ALTCENTURY); - year = cmos_read(RTC_CLK_YEAR); - - /* - * TODO: If century is 0xFF, 100% that the cmos is cleared. - * Other than that, so far rtc_year is the only entry to check - * if the date is valid. - */ - if (century > 0x99 || year > 0x99) /* Invalid date */ - cmos_reset_date(); -} - -int rtc_set(const struct rtc_time *time){ - cmos_write(bin2bcd(time->sec), RTC_CLK_SECOND); - cmos_write(bin2bcd(time->min), RTC_CLK_MINUTE); - cmos_write(bin2bcd(time->hour), RTC_CLK_HOUR); - cmos_write(bin2bcd(time->mday), RTC_CLK_DAYOFMONTH); - cmos_write(bin2bcd(time->mon), RTC_CLK_MONTH); - cmos_write(bin2bcd(time->year % 100), RTC_CLK_YEAR); - /* Same assumption as above: We always have RTC_CLK_ALTCENTURY */ - cmos_write(bin2bcd(time->year / 100), RTC_CLK_ALTCENTURY); - cmos_write(bin2bcd(time->wday + 1), RTC_CLK_DAYOFWEEK); - return 0; -} - -int rtc_get(struct rtc_time *time) -{ - time->sec = bcd2bin(cmos_read(RTC_CLK_SECOND)); - time->min = bcd2bin(cmos_read(RTC_CLK_MINUTE)); - time->hour = bcd2bin(cmos_read(RTC_CLK_HOUR)); - time->mday = bcd2bin(cmos_read(RTC_CLK_DAYOFMONTH)); - time->mon = bcd2bin(cmos_read(RTC_CLK_MONTH)); - time->year = bcd2bin(cmos_read(RTC_CLK_YEAR)); - /* Same assumption as above: We always have RTC_CLK_ALTCENTURY */ - time->year += bcd2bin(cmos_read(RTC_CLK_ALTCENTURY)) * 100; - time->wday = bcd2bin(cmos_read(RTC_CLK_DAYOFWEEK)) - 1; - return 0; -} |