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