mc146818.cc revision 5606
15392Sgblack@eecs.umich.edu/* 25392Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 35392Sgblack@eecs.umich.edu * All rights reserved. 45392Sgblack@eecs.umich.edu * 55392Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 65392Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 75392Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 85392Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 95392Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 105392Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 115392Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 125392Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 135392Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145392Sgblack@eecs.umich.edu * this software without specific prior written permission. 155392Sgblack@eecs.umich.edu * 165392Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175392Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185392Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195392Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205392Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215392Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225392Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235392Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245392Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255392Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265392Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275392Sgblack@eecs.umich.edu * 285392Sgblack@eecs.umich.edu * Authors: Ali Saidi 295392Sgblack@eecs.umich.edu * Andrew Schultz 305392Sgblack@eecs.umich.edu * Miguel Serrano 315392Sgblack@eecs.umich.edu */ 325392Sgblack@eecs.umich.edu 335392Sgblack@eecs.umich.edu#include <sys/time.h> 345392Sgblack@eecs.umich.edu#include <time.h> 355392Sgblack@eecs.umich.edu 365392Sgblack@eecs.umich.edu#include <string> 375392Sgblack@eecs.umich.edu 385392Sgblack@eecs.umich.edu#include "base/time.hh" 395392Sgblack@eecs.umich.edu#include "base/trace.hh" 405392Sgblack@eecs.umich.edu#include "dev/mc146818.hh" 415392Sgblack@eecs.umich.edu#include "dev/rtcreg.h" 425392Sgblack@eecs.umich.edu 435392Sgblack@eecs.umich.eduusing namespace std; 445392Sgblack@eecs.umich.edu 455606Snate@binkert.orgMC146818::MC146818(EventManager *em, const string &n, const struct tm time, 465606Snate@binkert.org bool bcd, Tick frequency) 475606Snate@binkert.org : EventManager(em), _name(n), event(this, frequency) 485392Sgblack@eecs.umich.edu{ 495392Sgblack@eecs.umich.edu memset(clock_data, 0, sizeof(clock_data)); 505392Sgblack@eecs.umich.edu stat_regA = RTCA_32768HZ | RTCA_1024HZ; 515392Sgblack@eecs.umich.edu stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 525392Sgblack@eecs.umich.edu 535392Sgblack@eecs.umich.edu year = time.tm_year; 545392Sgblack@eecs.umich.edu 555392Sgblack@eecs.umich.edu if (bcd) { 565392Sgblack@eecs.umich.edu // The datasheet says that the year field can be either BCD or 575392Sgblack@eecs.umich.edu // years since 1900. Linux seems to be happy with years since 585392Sgblack@eecs.umich.edu // 1900. 595392Sgblack@eecs.umich.edu year = year % 100; 605392Sgblack@eecs.umich.edu int tens = year / 10; 615392Sgblack@eecs.umich.edu int ones = year % 10; 625392Sgblack@eecs.umich.edu year = (tens << 4) + ones; 635392Sgblack@eecs.umich.edu } 645392Sgblack@eecs.umich.edu 655392Sgblack@eecs.umich.edu // Unix is 0-11 for month, data seet says start at 1 665392Sgblack@eecs.umich.edu mon = time.tm_mon + 1; 675392Sgblack@eecs.umich.edu mday = time.tm_mday; 685392Sgblack@eecs.umich.edu hour = time.tm_hour; 695392Sgblack@eecs.umich.edu min = time.tm_min; 705392Sgblack@eecs.umich.edu sec = time.tm_sec; 715392Sgblack@eecs.umich.edu 725392Sgblack@eecs.umich.edu // Datasheet says 1 is sunday 735392Sgblack@eecs.umich.edu wday = time.tm_wday + 1; 745392Sgblack@eecs.umich.edu 755392Sgblack@eecs.umich.edu DPRINTFN("Real-time clock set to %s", asctime(&time)); 765392Sgblack@eecs.umich.edu} 775392Sgblack@eecs.umich.edu 785606Snate@binkert.orgMC146818::~MC146818() 795606Snate@binkert.org{ 805606Snate@binkert.org} 815606Snate@binkert.org 825392Sgblack@eecs.umich.eduvoid 835392Sgblack@eecs.umich.eduMC146818::writeData(const uint8_t addr, const uint8_t data) 845392Sgblack@eecs.umich.edu{ 855392Sgblack@eecs.umich.edu if (addr < RTC_STAT_REGA) 865392Sgblack@eecs.umich.edu clock_data[addr] = data; 875392Sgblack@eecs.umich.edu else { 885392Sgblack@eecs.umich.edu switch (addr) { 895392Sgblack@eecs.umich.edu case RTC_STAT_REGA: 905392Sgblack@eecs.umich.edu if (data != (RTCA_32768HZ | RTCA_1024HZ)) 915392Sgblack@eecs.umich.edu panic("Unimplemented RTC register A value write!\n"); 925392Sgblack@eecs.umich.edu stat_regA = data; 935392Sgblack@eecs.umich.edu break; 945392Sgblack@eecs.umich.edu case RTC_STAT_REGB: 955392Sgblack@eecs.umich.edu if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 965392Sgblack@eecs.umich.edu panic("Write to RTC reg B bits that are not implemented!\n"); 975392Sgblack@eecs.umich.edu 985392Sgblack@eecs.umich.edu if (data & RTCB_PRDC_IE) { 995392Sgblack@eecs.umich.edu if (!event.scheduled()) 1005392Sgblack@eecs.umich.edu event.scheduleIntr(); 1015392Sgblack@eecs.umich.edu } else { 1025392Sgblack@eecs.umich.edu if (event.scheduled()) 1035606Snate@binkert.org deschedule(event); 1045392Sgblack@eecs.umich.edu } 1055392Sgblack@eecs.umich.edu stat_regB = data; 1065392Sgblack@eecs.umich.edu break; 1075392Sgblack@eecs.umich.edu case RTC_STAT_REGC: 1085392Sgblack@eecs.umich.edu case RTC_STAT_REGD: 1095392Sgblack@eecs.umich.edu panic("RTC status registers C and D are not implemented.\n"); 1105392Sgblack@eecs.umich.edu break; 1115392Sgblack@eecs.umich.edu } 1125392Sgblack@eecs.umich.edu } 1135392Sgblack@eecs.umich.edu} 1145392Sgblack@eecs.umich.edu 1155392Sgblack@eecs.umich.eduuint8_t 1165392Sgblack@eecs.umich.eduMC146818::readData(uint8_t addr) 1175392Sgblack@eecs.umich.edu{ 1185392Sgblack@eecs.umich.edu if (addr < RTC_STAT_REGA) 1195392Sgblack@eecs.umich.edu return clock_data[addr]; 1205392Sgblack@eecs.umich.edu else { 1215392Sgblack@eecs.umich.edu switch (addr) { 1225392Sgblack@eecs.umich.edu case RTC_STAT_REGA: 1235392Sgblack@eecs.umich.edu // toggle UIP bit for linux 1245392Sgblack@eecs.umich.edu stat_regA ^= RTCA_UIP; 1255392Sgblack@eecs.umich.edu return stat_regA; 1265392Sgblack@eecs.umich.edu break; 1275392Sgblack@eecs.umich.edu case RTC_STAT_REGB: 1285392Sgblack@eecs.umich.edu return stat_regB; 1295392Sgblack@eecs.umich.edu break; 1305392Sgblack@eecs.umich.edu case RTC_STAT_REGC: 1315392Sgblack@eecs.umich.edu case RTC_STAT_REGD: 1325392Sgblack@eecs.umich.edu return 0x00; 1335392Sgblack@eecs.umich.edu break; 1345392Sgblack@eecs.umich.edu default: 1355392Sgblack@eecs.umich.edu panic("Shouldn't be here"); 1365392Sgblack@eecs.umich.edu } 1375392Sgblack@eecs.umich.edu } 1385392Sgblack@eecs.umich.edu} 1395392Sgblack@eecs.umich.edu 1405392Sgblack@eecs.umich.eduvoid 1415392Sgblack@eecs.umich.eduMC146818::serialize(const string &base, ostream &os) 1425392Sgblack@eecs.umich.edu{ 1435392Sgblack@eecs.umich.edu arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); 1445392Sgblack@eecs.umich.edu paramOut(os, base + ".stat_regA", stat_regA); 1455392Sgblack@eecs.umich.edu paramOut(os, base + ".stat_regB", stat_regB); 1465392Sgblack@eecs.umich.edu} 1475392Sgblack@eecs.umich.edu 1485392Sgblack@eecs.umich.eduvoid 1495392Sgblack@eecs.umich.eduMC146818::unserialize(const string &base, Checkpoint *cp, 1505392Sgblack@eecs.umich.edu const string §ion) 1515392Sgblack@eecs.umich.edu{ 1525392Sgblack@eecs.umich.edu arrayParamIn(cp, section, base + ".clock_data", clock_data, 1535392Sgblack@eecs.umich.edu sizeof(clock_data)); 1545392Sgblack@eecs.umich.edu paramIn(cp, section, base + ".stat_regA", stat_regA); 1555392Sgblack@eecs.umich.edu paramIn(cp, section, base + ".stat_regB", stat_regB); 1565392Sgblack@eecs.umich.edu 1575392Sgblack@eecs.umich.edu // We're not unserializing the event here, but we need to 1585392Sgblack@eecs.umich.edu // rescehedule the event since curTick was moved forward by the 1595392Sgblack@eecs.umich.edu // checkpoint 1605606Snate@binkert.org reschedule(event, curTick + event.interval); 1615392Sgblack@eecs.umich.edu} 1625392Sgblack@eecs.umich.edu 1635392Sgblack@eecs.umich.eduMC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i) 1645606Snate@binkert.org : parent(_parent), interval(i) 1655392Sgblack@eecs.umich.edu{ 1665392Sgblack@eecs.umich.edu DPRINTF(MC146818, "RTC Event Initilizing\n"); 1675606Snate@binkert.org parent->schedule(this, curTick + interval); 1685392Sgblack@eecs.umich.edu} 1695392Sgblack@eecs.umich.edu 1705392Sgblack@eecs.umich.eduvoid 1715392Sgblack@eecs.umich.eduMC146818::RTCEvent::scheduleIntr() 1725392Sgblack@eecs.umich.edu{ 1735606Snate@binkert.org parent->schedule(this, curTick + interval); 1745392Sgblack@eecs.umich.edu} 1755392Sgblack@eecs.umich.edu 1765392Sgblack@eecs.umich.eduvoid 1775392Sgblack@eecs.umich.eduMC146818::RTCEvent::process() 1785392Sgblack@eecs.umich.edu{ 1795392Sgblack@eecs.umich.edu DPRINTF(MC146818, "RTC Timer Interrupt\n"); 1805606Snate@binkert.org parent->schedule(this, curTick + interval); 1815392Sgblack@eecs.umich.edu parent->handleEvent(); 1825392Sgblack@eecs.umich.edu} 1835392Sgblack@eecs.umich.edu 1845392Sgblack@eecs.umich.educonst char * 1855392Sgblack@eecs.umich.eduMC146818::RTCEvent::description() const 1865392Sgblack@eecs.umich.edu{ 1875392Sgblack@eecs.umich.edu return "RTC interrupt"; 1885392Sgblack@eecs.umich.edu} 189