1*511Sminht /* 2*511Sminht * CDDL HEADER START 3*511Sminht * 4*511Sminht * The contents of this file are subject to the terms of the 5*511Sminht * Common Development and Distribution License, Version 1.0 only 6*511Sminht * (the "License"). You may not use this file except in compliance 7*511Sminht * with the License. 8*511Sminht * 9*511Sminht * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*511Sminht * or http://www.opensolaris.org/os/licensing. 11*511Sminht * See the License for the specific language governing permissions 12*511Sminht * and limitations under the License. 13*511Sminht * 14*511Sminht * When distributing Covered Code, include this CDDL HEADER in each 15*511Sminht * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*511Sminht * If applicable, add the following below this CDDL HEADER, with the 17*511Sminht * fields enclosed by brackets "[]" replaced with your own identifying 18*511Sminht * information: Portions Copyright [yyyy] [name of copyright owner] 19*511Sminht * 20*511Sminht * CDDL HEADER END 21*511Sminht */ 22*511Sminht /* 23*511Sminht * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*511Sminht * Use is subject to license terms. 25*511Sminht */ 26*511Sminht 27*511Sminht #pragma ident "%Z%%M% %I% %E% SMI" 28*511Sminht 29*511Sminht /* 30*511Sminht * tod driver module for TI BQ4802 part 31*511Sminht * 32*511Sminht * Note: The way to access the bq4802's RTC registers is different than 33*511Sminht * the previous RTC devices (m5823, m5819p, ds1287, etc) that we used. 34*511Sminht * The address returns from OBP is mapped directly to the bq4802's RTC 35*511Sminht * registers. To read/write the data from/to the bq4802 registers, one 36*511Sminht * just add the register offset to the base address. 37*511Sminht * To access the previous RTC devices, we write the register index to 38*511Sminht * the address port (v_rtc_addr_reg) then read/write the data from/to 39*511Sminht * the data port (v_rtc_data_reg). 40*511Sminht */ 41*511Sminht 42*511Sminht #include <sys/types.h> 43*511Sminht #include <sys/conf.h> 44*511Sminht #include <sys/kmem.h> 45*511Sminht #include <sys/open.h> 46*511Sminht #include <sys/ddi.h> 47*511Sminht #include <sys/sunddi.h> 48*511Sminht #include <sys/sysmacros.h> 49*511Sminht 50*511Sminht #include <sys/todbq4802.h> 51*511Sminht #include <sys/modctl.h> 52*511Sminht #include <sys/stat.h> 53*511Sminht #include <sys/clock.h> 54*511Sminht #include <sys/reboot.h> 55*511Sminht #include <sys/machsystm.h> 56*511Sminht 57*511Sminht /* 58*511Sminht * tod_ops entry routines 59*511Sminht */ 60*511Sminht static timestruc_t todbq4802_get(void); 61*511Sminht static void todbq4802_set(timestruc_t); 62*511Sminht static uint_t todbq4802_set_watchdog_timer(uint_t); 63*511Sminht static uint_t todbq4802_clear_watchdog_timer(void); 64*511Sminht static void todbq4802_set_power_alarm(timestruc_t); 65*511Sminht static void todbq4802_clear_power_alarm(void); 66*511Sminht static uint64_t todbq4802_get_cpufrequency(void); 67*511Sminht 68*511Sminht extern uint64_t find_cpufrequency(volatile uint8_t *); 69*511Sminht 70*511Sminht /* 71*511Sminht * External variables 72*511Sminht */ 73*511Sminht extern int watchdog_enable; 74*511Sminht extern int watchdog_available; 75*511Sminht extern int boothowto; 76*511Sminht 77*511Sminht /* 78*511Sminht * Global variables 79*511Sminht */ 80*511Sminht int bq4802_debug_flags; 81*511Sminht uint_t bq4802_hrestime_count = 0; 82*511Sminht uint_t bq4802_uip_count = 0; 83*511Sminht 84*511Sminht /* 85*511Sminht * Module linkage information for the kernel. 86*511Sminht */ 87*511Sminht static struct modlmisc modlmisc = { 88*511Sminht &mod_miscops, "tod module for TI BQ4802" 89*511Sminht }; 90*511Sminht 91*511Sminht static struct modlinkage modlinkage = { 92*511Sminht MODREV_1, (void *)&modlmisc, NULL 93*511Sminht }; 94*511Sminht 95*511Sminht static void read_rtc(struct rtc_t *); 96*511Sminht static void write_rtc_time(struct rtc_t *); 97*511Sminht static void write_rtc_alarm(struct rtc_t *); 98*511Sminht 99*511Sminht int 100*511Sminht _init(void) 101*511Sminht { 102*511Sminht if (strcmp(tod_module_name, "todbq4802") == 0) { 103*511Sminht if (v_rtc_addr_reg == NULL) 104*511Sminht cmn_err(CE_PANIC, "addr not set, cannot read RTC\n"); 105*511Sminht 106*511Sminht BQ4802_DATA_REG(RTC_CNTRL) = (RTC_DSE | RTC_HM | RTC_STOP_N); 107*511Sminht 108*511Sminht /* Clear AF flag by reading reg Flags (D) */ 109*511Sminht (void) BQ4802_DATA_REG(RTC_FLAGS); 110*511Sminht 111*511Sminht tod_ops.tod_get = todbq4802_get; 112*511Sminht tod_ops.tod_set = todbq4802_set; 113*511Sminht tod_ops.tod_set_watchdog_timer = 114*511Sminht todbq4802_set_watchdog_timer; 115*511Sminht tod_ops.tod_clear_watchdog_timer = 116*511Sminht todbq4802_clear_watchdog_timer; 117*511Sminht tod_ops.tod_set_power_alarm = todbq4802_set_power_alarm; 118*511Sminht tod_ops.tod_clear_power_alarm = todbq4802_clear_power_alarm; 119*511Sminht tod_ops.tod_get_cpufrequency = todbq4802_get_cpufrequency; 120*511Sminht 121*511Sminht /* 122*511Sminht * check if hardware watchdog timer is available and user 123*511Sminht * enabled it. 124*511Sminht */ 125*511Sminht if (watchdog_enable) { 126*511Sminht if (!watchdog_available) { 127*511Sminht cmn_err(CE_WARN, "bq4802: Hardware watchdog " 128*511Sminht "unavailable"); 129*511Sminht } else if (boothowto & RB_DEBUG) { 130*511Sminht cmn_err(CE_WARN, "bq4802: Hardware watchdog" 131*511Sminht " disabled [debugger]"); 132*511Sminht } 133*511Sminht } 134*511Sminht } 135*511Sminht 136*511Sminht return (mod_install(&modlinkage)); 137*511Sminht } 138*511Sminht 139*511Sminht int 140*511Sminht _fini(void) 141*511Sminht { 142*511Sminht if (strcmp(tod_module_name, "todbq4802") == 0) 143*511Sminht return (EBUSY); 144*511Sminht 145*511Sminht return (mod_remove(&modlinkage)); 146*511Sminht } 147*511Sminht 148*511Sminht /* 149*511Sminht * The loadable-module _info(9E) entry point 150*511Sminht */ 151*511Sminht int 152*511Sminht _info(struct modinfo *modinfop) 153*511Sminht { 154*511Sminht return (mod_info(&modlinkage, modinfop)); 155*511Sminht } 156*511Sminht 157*511Sminht /* 158*511Sminht * Read the current time from the clock chip and convert to UNIX form. 159*511Sminht * Assumes that the year in the clock chip is valid. 160*511Sminht * Must be called with tod_lock held. 161*511Sminht */ 162*511Sminht static timestruc_t 163*511Sminht todbq4802_get(void) 164*511Sminht { 165*511Sminht timestruc_t ts; 166*511Sminht todinfo_t tod; 167*511Sminht struct rtc_t rtc; 168*511Sminht 169*511Sminht ASSERT(MUTEX_HELD(&tod_lock)); 170*511Sminht 171*511Sminht read_rtc(&rtc); 172*511Sminht DPRINTF("todbq4802_get: century=%d year=%d dom=%d hrs=%d min=%d" 173*511Sminht " sec=%d\n", rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, 174*511Sminht rtc.rtc_hrs, rtc.rtc_min, rtc.rtc_sec); 175*511Sminht 176*511Sminht /* 177*511Sminht * tod_year is base 1900 so this code needs to adjust the true 178*511Sminht * year retrieved from the rtc's century and year fields. 179*511Sminht */ 180*511Sminht tod.tod_year = rtc.rtc_year + (rtc.rtc_century * 100) - 1900; 181*511Sminht tod.tod_month = rtc.rtc_mon; 182*511Sminht tod.tod_day = rtc.rtc_dom; 183*511Sminht tod.tod_dow = rtc.rtc_dow; 184*511Sminht tod.tod_hour = rtc.rtc_hrs; 185*511Sminht tod.tod_min = rtc.rtc_min; 186*511Sminht tod.tod_sec = rtc.rtc_sec; 187*511Sminht 188*511Sminht ts.tv_sec = tod_to_utc(tod); 189*511Sminht ts.tv_nsec = 0; 190*511Sminht return (ts); 191*511Sminht } 192*511Sminht 193*511Sminht /* 194*511Sminht * Once every second, the user-accessible clock/calendar 195*511Sminht * locations are updated simultaneously from the internal 196*511Sminht * real-time counters. To prevent reading data in transition, 197*511Sminht * updates to the bq4802 clock registers should be halted. 198*511Sminht * Updating is halted by setting the Update Transfer Inhibit 199*511Sminht * (UTI) bit D3 of the control register E. As long as the 200*511Sminht * UTI bit is 1, updates to user-accessible clock locations are 201*511Sminht * inhibited. Once the frozen clock information is retrieved by 202*511Sminht * reading the appropriate clock memory locations, the UTI 203*511Sminht * bit should be reset to 0 in order to allow updates to occur 204*511Sminht * from the internal counters. Because the internal counters 205*511Sminht * are not halted by setting the UTI bit, reading the clock 206*511Sminht * locations has no effect on clock accuracy. Once the UTI bit 207*511Sminht * is reset to 0, the internal registers update within one 208*511Sminht * second the user-accessible registers with the correct time. 209*511Sminht * A halt command issued during a clock update allows the 210*511Sminht * update to occur before freezing the data. 211*511Sminht */ 212*511Sminht static void 213*511Sminht read_rtc(struct rtc_t *rtc) 214*511Sminht { 215*511Sminht uint8_t reg_cntrl; 216*511Sminht 217*511Sminht /* 218*511Sminht * Freeze 219*511Sminht */ 220*511Sminht reg_cntrl = BQ4802_DATA_REG(RTC_CNTRL); 221*511Sminht BQ4802_DATA_REG(RTC_CNTRL) = (reg_cntrl | RTC_UTI); 222*511Sminht 223*511Sminht rtc->rtc_sec = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_SEC)); 224*511Sminht rtc->rtc_asec = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_ASEC)); 225*511Sminht rtc->rtc_min = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_MIN)); 226*511Sminht rtc->rtc_amin = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_AMIN)); 227*511Sminht rtc->rtc_hrs = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_HRS)); 228*511Sminht rtc->rtc_ahrs = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_AHRS)); 229*511Sminht rtc->rtc_dom = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_DOM)); 230*511Sminht rtc->rtc_adom = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_ADOM)); 231*511Sminht rtc->rtc_dow = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_DOW)); 232*511Sminht rtc->rtc_mon = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_MON)); 233*511Sminht rtc->rtc_year = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_YEAR)); 234*511Sminht rtc->rtc_century = BCD_TO_BYTE(BQ4802_DATA_REG(RTC_CENTURY)); 235*511Sminht 236*511Sminht /* 237*511Sminht * Unfreeze 238*511Sminht */ 239*511Sminht BQ4802_DATA_REG(RTC_CNTRL) = reg_cntrl; 240*511Sminht } 241*511Sminht 242*511Sminht /* 243*511Sminht * Write the specified time into the clock chip. 244*511Sminht * Must be called with tod_lock held. 245*511Sminht */ 246*511Sminht static void 247*511Sminht todbq4802_set(timestruc_t ts) 248*511Sminht { 249*511Sminht struct rtc_t rtc; 250*511Sminht todinfo_t tod = utc_to_tod(ts.tv_sec); 251*511Sminht int year; 252*511Sminht 253*511Sminht ASSERT(MUTEX_HELD(&tod_lock)); 254*511Sminht 255*511Sminht /* tod_year is base 1900 so this code needs to adjust */ 256*511Sminht year = 1900 + tod.tod_year; 257*511Sminht rtc.rtc_year = year % 100; 258*511Sminht rtc.rtc_century = year / 100; 259*511Sminht rtc.rtc_mon = (uint8_t)tod.tod_month; 260*511Sminht rtc.rtc_dom = (uint8_t)tod.tod_day; 261*511Sminht rtc.rtc_dow = (uint8_t)tod.tod_dow; 262*511Sminht rtc.rtc_hrs = (uint8_t)tod.tod_hour; 263*511Sminht rtc.rtc_min = (uint8_t)tod.tod_min; 264*511Sminht rtc.rtc_sec = (uint8_t)tod.tod_sec; 265*511Sminht DPRINTF("todbq4802_set: year=%d dom=%d hrs=%d min=%d sec=%d\n", 266*511Sminht rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs, rtc.rtc_min, rtc.rtc_sec); 267*511Sminht 268*511Sminht write_rtc_time(&rtc); 269*511Sminht } 270*511Sminht 271*511Sminht /* 272*511Sminht * The UTI bit must be used to set the bq4802 clock. 273*511Sminht * Once set, the locations can be written with the desired 274*511Sminht * information in BCD format. Resetting the UTI bit to 0 causes 275*511Sminht * the written values to be transferred to the internal clock 276*511Sminht * counters and allows updates to the user-accessible registers 277*511Sminht * to resume within one second. 278*511Sminht */ 279*511Sminht void 280*511Sminht write_rtc_time(struct rtc_t *rtc) 281*511Sminht { 282*511Sminht uint8_t reg_cntrl; 283*511Sminht 284*511Sminht /* 285*511Sminht * Freeze 286*511Sminht */ 287*511Sminht reg_cntrl = BQ4802_DATA_REG(RTC_CNTRL); 288*511Sminht BQ4802_DATA_REG(RTC_CNTRL) = (reg_cntrl | RTC_UTI); 289*511Sminht 290*511Sminht BQ4802_DATA_REG(RTC_SEC) = BYTE_TO_BCD(rtc->rtc_sec); 291*511Sminht BQ4802_DATA_REG(RTC_MIN) = BYTE_TO_BCD(rtc->rtc_min); 292*511Sminht BQ4802_DATA_REG(RTC_HRS) = BYTE_TO_BCD(rtc->rtc_hrs); 293*511Sminht BQ4802_DATA_REG(RTC_DOM) = BYTE_TO_BCD(rtc->rtc_dom); 294*511Sminht BQ4802_DATA_REG(RTC_DOW) = BYTE_TO_BCD(rtc->rtc_dow); 295*511Sminht BQ4802_DATA_REG(RTC_MON) = BYTE_TO_BCD(rtc->rtc_mon); 296*511Sminht BQ4802_DATA_REG(RTC_YEAR) = BYTE_TO_BCD(rtc->rtc_year); 297*511Sminht BQ4802_DATA_REG(RTC_CENTURY) = BYTE_TO_BCD(rtc->rtc_century); 298*511Sminht 299*511Sminht /* 300*511Sminht * Unfreeze 301*511Sminht */ 302*511Sminht BQ4802_DATA_REG(RTC_CNTRL) = reg_cntrl; 303*511Sminht } 304*511Sminht 305*511Sminht void 306*511Sminht write_rtc_alarm(struct rtc_t *rtc) 307*511Sminht { 308*511Sminht BQ4802_DATA_REG(RTC_ASEC) = BYTE_TO_BCD(rtc->rtc_asec); 309*511Sminht BQ4802_DATA_REG(RTC_AMIN) = BYTE_TO_BCD(rtc->rtc_amin); 310*511Sminht BQ4802_DATA_REG(RTC_AHRS) = BYTE_TO_BCD(rtc->rtc_ahrs); 311*511Sminht BQ4802_DATA_REG(RTC_ADOM) = BYTE_TO_BCD(rtc->rtc_adom); 312*511Sminht } 313*511Sminht 314*511Sminht /* 315*511Sminht * program the rtc registers for alarm to go off at the specified time 316*511Sminht */ 317*511Sminht static void 318*511Sminht todbq4802_set_power_alarm(timestruc_t ts) 319*511Sminht { 320*511Sminht todinfo_t tod; 321*511Sminht uint8_t regc; 322*511Sminht struct rtc_t rtc; 323*511Sminht 324*511Sminht ASSERT(MUTEX_HELD(&tod_lock)); 325*511Sminht tod = utc_to_tod(ts.tv_sec); 326*511Sminht 327*511Sminht /* 328*511Sminht * disable alarms and clear AF flag by reading reg Flags (D) 329*511Sminht */ 330*511Sminht regc = BQ4802_DATA_REG(RTC_ENABLES); 331*511Sminht BQ4802_DATA_REG(RTC_ENABLES) = regc & ~(RTC_AIE | RTC_ABE); 332*511Sminht (void) BQ4802_DATA_REG(RTC_FLAGS); 333*511Sminht 334*511Sminht rtc.rtc_asec = (uint8_t)tod.tod_sec; 335*511Sminht rtc.rtc_amin = (uint8_t)tod.tod_min; 336*511Sminht rtc.rtc_ahrs = (uint8_t)tod.tod_hour; 337*511Sminht rtc.rtc_adom = (uint8_t)tod.tod_day; 338*511Sminht DPRINTF("todbq4802_set_alarm: dom=%d hrs=%d min=%d sec=%d\n", 339*511Sminht rtc.rtc_adom, rtc.rtc_ahrs, rtc.rtc_amin, rtc.rtc_asec); 340*511Sminht 341*511Sminht /* 342*511Sminht * Write alarm values and enable alarm 343*511Sminht */ 344*511Sminht write_rtc_alarm(&rtc); 345*511Sminht 346*511Sminht BQ4802_DATA_REG(RTC_ENABLES) = regc | RTC_AIE | RTC_ABE; 347*511Sminht } 348*511Sminht 349*511Sminht /* 350*511Sminht * clear alarm interrupt 351*511Sminht */ 352*511Sminht static void 353*511Sminht todbq4802_clear_power_alarm(void) 354*511Sminht { 355*511Sminht uint8_t regc; 356*511Sminht 357*511Sminht ASSERT(MUTEX_HELD(&tod_lock)); 358*511Sminht 359*511Sminht regc = BQ4802_DATA_REG(RTC_ENABLES); 360*511Sminht BQ4802_DATA_REG(RTC_ENABLES) = regc & ~(RTC_AIE | RTC_ABE); 361*511Sminht } 362*511Sminht 363*511Sminht /* 364*511Sminht * Determine the cpu frequency by watching the TOD chip rollover twice. 365*511Sminht * Cpu clock rate is determined by computing the ticks added (in tick register) 366*511Sminht * during one second interval on TOD. 367*511Sminht */ 368*511Sminht uint64_t 369*511Sminht todbq4802_get_cpufrequency(void) 370*511Sminht { 371*511Sminht ASSERT(MUTEX_HELD(&tod_lock)); 372*511Sminht return (find_cpufrequency((volatile uint8_t *)v_rtc_addr_reg)); 373*511Sminht } 374*511Sminht 375*511Sminht /*ARGSUSED*/ 376*511Sminht static uint_t 377*511Sminht todbq4802_set_watchdog_timer(uint_t timeoutval) 378*511Sminht { 379*511Sminht ASSERT(MUTEX_HELD(&tod_lock)); 380*511Sminht return (0); 381*511Sminht } 382*511Sminht 383*511Sminht static uint_t 384*511Sminht todbq4802_clear_watchdog_timer(void) 385*511Sminht { 386*511Sminht ASSERT(MUTEX_HELD(&tod_lock)); 387*511Sminht return (0); 388*511Sminht } 389