1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * DS1743W RTC driver File: dev_ds1743wclock.c 5 * 6 * This module contains a CFE driver for a DS1743W generic bus 7 * real-time-clock. 8 * 9 * Author: Mitch Lichtenberg 10 * 11 ********************************************************************* 12 * 13 * Copyright 2000,2001,2002,2003 14 * Broadcom Corporation. All rights reserved. 15 * 16 * This software is furnished under license and may be used and 17 * copied only in accordance with the following terms and 18 * conditions. Subject to these conditions, you may download, 19 * copy, install, use, modify and distribute modified or unmodified 20 * copies of this software in source and/or binary form. No title 21 * or ownership is transferred hereby. 22 * 23 * 1) Any source code used, modified or distributed must reproduce 24 * and retain this copyright notice and list of conditions 25 * as they appear in the source file. 26 * 27 * 2) No right is granted to use any trade name, trademark, or 28 * logo of Broadcom Corporation. The "Broadcom Corporation" 29 * name may not be used to endorse or promote products derived 30 * from this software without the prior written permission of 31 * Broadcom Corporation. 32 * 33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 45 * THE POSSIBILITY OF SUCH DAMAGE. 46 ********************************************************************* */ 47 48#include "cfe.h" 49#include "lib_physio.h" 50 51 52/* ********************************************************************* 53 * Constants 54 ********************************************************************* */ 55 56#define M_DS1743_BF 0x80 57#define M_DS1743_FT 0x40 58#define M_DS1743_OSC 0x80 59#define M_DS1743_W 0x80 60#define M_DS1743_R 0x40 61 62#define M_DS1743_MONTH 0x1F 63#define M_DS1743_DATE 0x3F 64#define M_DS1743_DAY 0x03 65#define M_DS1743_MINUTE 0x7F 66#define M_DS1743_SECOND 0x7F 67#define M_DS1743_CENTURY 0x3F 68 69 70#define DS1743_NVRAM_SIZE 0x1FF8 71 72#define DS1743_CONTROL 0x1FF8 73#define DS1743_CENTURY 0x1FF8 74#define DS1743_SECOND 0x1FF9 75#define DS1743_MINUTE 0x1FFA 76#define DS1743_HOUR 0x1FFB 77#define DS1743_DAY 0x1FFC 78#define DS1743_DATE 0x1FFD 79#define DS1743_MONTH 0x1FFE 80#define DS1743_YEAR 0x1FFF 81 82#define BCD(x) (((x) % 10) + (((x) / 10) << 4)) 83#define SET_TIME 0x00 84#define SET_DATE 0x01 85 86#if ENDIAN_BIG 87#define WRITECSR(p,v) phys_write8((p)^3,(v)) 88#define READCSR(p) phys_read8((p)^3) 89#elif ENDIAN_LITTLE 90#define WRITECSR(p,v) phys_write8((p),(v)) 91#define READCSR(p) phys_read8((p)) 92#else 93#error "dev_ds1743: system endian not set" 94#endif 95 96/* ********************************************************************* 97 * Forward declarations 98 ********************************************************************* */ 99 100static void ds1743_clock_probe(cfe_driver_t *drv, 101 unsigned long probe_a, unsigned long probe_b, 102 void *probe_ptr); 103 104static int ds1743_clock_open(cfe_devctx_t *ctx); 105static int ds1743_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 106static int ds1743_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); 107static int ds1743_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 108static int ds1743_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 109static int ds1743_clock_close(cfe_devctx_t *ctx); 110 111 112/* ********************************************************************* 113 * Device dispatch 114 ********************************************************************* */ 115 116const static cfe_devdisp_t ds1743_clock_dispatch = { 117 ds1743_clock_open, 118 ds1743_clock_read, 119 ds1743_clock_inpstat, 120 ds1743_clock_write, 121 ds1743_clock_ioctl, 122 ds1743_clock_close, 123 NULL, 124 NULL 125}; 126 127const cfe_driver_t ds1743_clock = { 128 "Dallas DS1743 RTC", 129 "clock", 130 CFE_DEV_CLOCK, 131 &ds1743_clock_dispatch, 132 ds1743_clock_probe 133}; 134 135 136/* ********************************************************************* 137 * Structures 138 ********************************************************************* */ 139typedef struct ds1743_clock_s { 140 physaddr_t clock_base; 141} ds1743_clock_t; 142 143/* ********************************************************************* 144 * ds1743_clock_probe(drv,a,b,ptr) 145 * 146 * Probe routine for this driver. This routine creates the 147 * local device context and attaches it to the driver list 148 * within CFE. 149 * 150 * Input parameters: 151 * drv - driver handle 152 * a,b - probe hints (longs) 153 * ptr - probe hint (pointer) 154 * 155 * Return value: 156 * nothing 157 ********************************************************************* */ 158 159static void ds1743_clock_probe(cfe_driver_t *drv, 160 unsigned long probe_a, unsigned long probe_b, 161 void *probe_ptr) 162{ 163 ds1743_clock_t *softc; 164 char descr[80]; 165 166 softc = (ds1743_clock_t *) KMALLOC(sizeof(ds1743_clock_t),0); 167 168 /* 169 * Probe_a is the clock base address 170 * Probe_b is unused. 171 * Probe_ptr is unused. 172 */ 173 174 softc->clock_base = probe_a; 175 176 xsprintf(descr,"%s at 0x%X", 177 drv->drv_description,(uint32_t)probe_a); 178 cfe_attach(drv,softc,NULL,descr); 179 180} 181 182/* ********************************************************************* 183 * ds1743_clock_open(ctx) 184 * 185 * Open this device. For the DS1743, we do a quick test 186 * read to be sure the device is out there. 187 * 188 * Input parameters: 189 * ctx - device context (can obtain our softc here) 190 * 191 * Return value: 192 * 0 if ok 193 * else error code 194 ********************************************************************* */ 195 196static int ds1743_clock_open(cfe_devctx_t *ctx) 197{ 198 ds1743_clock_t *softc = ctx->dev_softc; 199 physaddr_t clockbase; 200 201 clockbase = softc->clock_base; 202 203 /* Make sure battery is still good and RTC valid */ 204 if (!(READCSR(clockbase+DS1743_DAY) & M_DS1743_BF)) { 205 printf("Warning: Battery has failed. Clock setting is not accurate.\n"); 206 } 207 208 209 return 0; 210} 211 212/* ********************************************************************* 213 * ds1743_clock_read(ctx,buffer) 214 * 215 * Read time/date from the RTC. Read a total of 8 bytes in this format: 216 * hour-minute-second-month-day-year1-year2 217 * 218 * Input parameters: 219 * ctx - device context (can obtain our softc here) 220 * buffer - buffer descriptor (target buffer, length, offset) 221 * 222 * Return value: 223 * number of bytes read 224 * -1 if an error occured 225 ********************************************************************* */ 226 227static int ds1743_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 228{ 229 230 ds1743_clock_t *softc = ctx->dev_softc; 231 hsaddr_t bptr; 232 uint8_t b; 233 physaddr_t clockbase; 234 uint8_t byte; 235 236 clockbase = softc->clock_base; 237 238 bptr = buffer->buf_ptr; 239 240 byte = (uint8_t) (READCSR(clockbase+DS1743_CONTROL) & 0xFF); 241 WRITECSR(clockbase+DS1743_CONTROL,M_DS1743_R | byte); 242 243 b = READCSR(clockbase+DS1743_HOUR); hs_write8(bptr,b); bptr++; 244 b = READCSR(clockbase+DS1743_MINUTE); hs_write8(bptr,b); bptr++; 245 b = READCSR(clockbase+DS1743_SECOND); hs_write8(bptr,b); bptr++; 246 b = READCSR(clockbase+DS1743_MONTH) & M_DS1743_MONTH; hs_write8(bptr,b); bptr++; 247 b = READCSR(clockbase+DS1743_DATE) & M_DS1743_DATE; hs_write8(bptr,b); bptr++; 248 b = READCSR(clockbase+DS1743_YEAR); hs_write8(bptr,b); bptr++; 249 b = READCSR(clockbase+DS1743_CENTURY) & M_DS1743_CENTURY; hs_write8(bptr,b); bptr++; 250 251 byte = (uint8_t) (READCSR(clockbase+DS1743_CONTROL) & 0xFF); 252 WRITECSR(clockbase+DS1743_CONTROL,~M_DS1743_R & byte); 253 254 buffer->buf_retlen = 8; 255 return 0; 256} 257 258/* ********************************************************************* 259 * ds1743_clock_write(ctx,buffer) 260 * 261 * Write time/date to the RTC. Write in this format: 262 * hour-minute-second-month-day-year1-year2-(time/date flag) 263 * 264 * Input parameters: 265 * ctx - device context (can obtain our softc here) 266 * buffer - buffer descriptor (target buffer, length, offset) 267 * 268 * Return value: 269 * number of bytes written 270 * -1 if an error occured 271 ********************************************************************* */ 272 273static int ds1743_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 274{ 275 ds1743_clock_t *softc = ctx->dev_softc; 276 uint8_t byte; 277 hsaddr_t bptr; 278 uint8_t hr,min,sec; 279 uint8_t mo,day,yr,y2k; 280 uint8_t timeDateFlag; 281 physaddr_t clockbase; 282 283 clockbase = softc->clock_base; 284 285 bptr = buffer->buf_ptr; 286 287 /* Set SET bit */ 288 byte = (uint8_t) (READCSR(clockbase+DS1743_CONTROL) & 0xFF); 289 WRITECSR(clockbase+DS1743_CONTROL,M_DS1743_W | byte); 290 291 timeDateFlag = hs_read8(bptr + 7); 292 293 /* write time or date */ 294 if(timeDateFlag == SET_TIME) { 295 296 hr = (uint8_t) hs_read8(bptr); 297 WRITECSR(clockbase+DS1743_HOUR,BCD(hr)); 298 299 min = (uint8_t) hs_read8(bptr+1); 300 WRITECSR(clockbase+DS1743_MINUTE,BCD(min)); 301 302 sec = (uint8_t) hs_read8(bptr+2); 303 WRITECSR(clockbase+DS1743_SECOND,BCD(sec)); 304 305 buffer->buf_retlen = 3; 306 } 307 else if(timeDateFlag == SET_DATE) { 308 uint8_t byte; 309 310 mo = (uint8_t) hs_read8(bptr+3); 311 WRITECSR(clockbase+DS1743_MONTH,BCD(mo)); 312 313 day = (uint8_t) hs_read8(bptr+4); 314 WRITECSR(clockbase+DS1743_DATE,BCD(day)); 315 316 yr = (uint8_t) hs_read8(bptr+5); 317 WRITECSR(clockbase+DS1743_YEAR,BCD(yr)); 318 319 y2k = (uint8_t) hs_read8(bptr+6); 320 byte = READCSR(clockbase+DS1743_CENTURY); 321 byte &= ~M_DS1743_CENTURY; 322 byte |= (y2k & M_DS1743_CENTURY); 323 WRITECSR(clockbase+DS1743_CENTURY, byte); 324 325 buffer->buf_retlen = 4; 326 } 327 else { 328 return -1; 329 } 330 331 /* clear SET bit */ 332 byte = (uint8_t) (READCSR(clockbase+DS1743_CONTROL) & 0xFF); 333 WRITECSR(clockbase+DS1743_CONTROL,~M_DS1743_W & byte); 334 335 return 0; 336} 337 338/* ********************************************************************* 339 * ds1743_clock_inpstat(ctx,inpstat) 340 * 341 * Test input (read) status for the device 342 * 343 * Input parameters: 344 * ctx - device context (can obtain our softc here) 345 * inpstat - input status descriptor to receive value 346 * 347 * Return value: 348 * 0 if ok 349 * -1 if an error occured 350 ********************************************************************* */ 351 352static int ds1743_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) 353{ 354 inpstat->inp_status = 1; 355 356 return 0; 357} 358 359/* ********************************************************************* 360 * ds1743_clock_ioctl(ctx,buffer) 361 * 362 * Perform miscellaneous I/O control operations on the device. 363 * 364 * Input parameters: 365 * ctx - device context (can obtain our softc here) 366 * buffer - buffer descriptor (target buffer, length, offset) 367 * 368 * Return value: 369 * number of bytes read 370 * -1 if an error occured 371 ********************************************************************* */ 372 373static int ds1743_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 374{ 375 return 0; 376} 377 378/* ********************************************************************* 379 * ds1743_clock_close(ctx,buffer) 380 * 381 * Close the device. 382 * 383 * Input parameters: 384 * ctx - device context (can obtain our softc here) 385 * 386 * Return value: 387 * 0 if ok 388 * -1 if an error occured 389 ********************************************************************* */ 390 391static int ds1743_clock_close(cfe_devctx_t *ctx) 392{ 393 return 0; 394} 395 396 397 398/* ********************************************************************* 399 * Forward Declarations 400 ********************************************************************* */ 401 402static void ds1743_nvram_probe(cfe_driver_t *drv, 403 unsigned long probe_a, unsigned long probe_b, 404 void *probe_ptr); 405 406 407static int ds1743_nvram_open(cfe_devctx_t *ctx); 408static int ds1743_nvram_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 409static int ds1743_nvram_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); 410static int ds1743_nvram_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 411static int ds1743_nvram_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 412static int ds1743_nvram_close(cfe_devctx_t *ctx); 413 414/* ********************************************************************* 415 * Dispatch tables 416 ********************************************************************* */ 417 418const static cfe_devdisp_t ds1743_nvram_dispatch = { 419 ds1743_nvram_open, 420 ds1743_nvram_read, 421 ds1743_nvram_inpstat, 422 ds1743_nvram_write, 423 ds1743_nvram_ioctl, 424 ds1743_nvram_close, 425 NULL, 426 NULL 427}; 428 429const cfe_driver_t ds1743_nvram = { 430 "Dallas DS1743 NVRAM", 431 "nvram", 432 CFE_DEV_NVRAM, 433 &ds1743_nvram_dispatch, 434 ds1743_nvram_probe 435}; 436 437typedef struct ds1743_nvram_s { 438 int base_addr; 439 int dev_size; 440 int env_offset; 441 int env_size; 442 volatile unsigned char* data; /* NV region */ 443} ds1743_nvram_t; 444 445 446 447/* ********************************************************************* 448 * ds1743_nvram_probe(drv,a,b,ptr) 449 * 450 * Probe routine for this driver. This routine creates the 451 * local device context and attaches it to the driver list 452 * within CFE. 453 * 454 * Input parameters: 455 * drv - driver handle 456 * a,b - probe hints (longs) 457 * ptr - probe hint (pointer) 458 * 459 * Return value: 460 * nothing 461 ********************************************************************* */ 462static void ds1743_nvram_probe(cfe_driver_t *drv, 463 unsigned long probe_a, unsigned long probe_b, 464 void *probe_ptr) 465{ 466 ds1743_nvram_t *softc; 467 char descr[80]; 468 469 softc = (ds1743_nvram_t *) KMALLOC(sizeof(ds1743_nvram_t),0); 470 471 /* 472 * Probe_a is the NVRAM base address. 473 * Probe_b is unused 474 * Probe_ptr is unused. 475 */ 476 477 softc->base_addr = (int)probe_a; 478 softc->dev_size = DS1743_NVRAM_SIZE; 479 softc->env_offset = 0; 480 softc->env_size = softc->dev_size; 481 softc->data = (volatile unsigned char*) UNCADDR(softc->base_addr); 482 /* PHYS_TO_XKSEG_UNCACHED(softc->base_addr); */ 483 484 xsprintf(descr,"%s at %x size %dKB", 485 drv->drv_description, 486 softc->base_addr, 487 softc->dev_size / 1024 ); 488 489 cfe_attach(drv,softc,NULL,descr); 490} 491 492 493 494/* ********************************************************************* 495 * ds1743_nvram_open(ctx) 496 * 497 * Open this device. For the X1240, we do a quick test 498 * read to be sure the device is out there. 499 * 500 * Input parameters: 501 * ctx - device context (can obtain our softc here) 502 * 503 * Return value: 504 * 0 if ok 505 * else error code 506 ********************************************************************* */ 507 508static int ds1743_nvram_open(cfe_devctx_t *ctx) 509{ 510 return 0; 511} 512 513/* ********************************************************************* 514 * ds1743_nvram_read(ctx,buffer) 515 * 516 * Read bytes from the device. 517 * 518 * Input parameters: 519 * ctx - device context (can obtain our softc here) 520 * buffer - buffer descriptor (target buffer, length, offset) 521 * 522 * Return value: 523 * number of bytes read 524 * -1 if an error occured 525 ********************************************************************* */ 526 527static int ds1743_nvram_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 528{ 529 ds1743_nvram_t *softc = ctx->dev_softc; 530 hsaddr_t bptr; 531 int blen; 532 int idx; 533 int b = 0; 534 535 bptr = buffer->buf_ptr; 536 blen = buffer->buf_length; 537 538 if ((buffer->buf_offset + blen) > softc->dev_size) return -1; 539 540 idx = (int) buffer->buf_offset; 541 542 while (blen > 0) { 543 b = softc->data[idx]; 544 hs_write8(bptr,(unsigned char) b); 545 bptr++; 546 blen--; 547 idx++; 548 } 549 550 buffer->buf_retlen = bptr - buffer->buf_ptr; 551 return (b < 0) ? -1 : 0; 552} 553 554/* ********************************************************************* 555 * ds1743_nvram_inpstat(ctx,inpstat) 556 * 557 * Test input (read) status for the device 558 * 559 * Input parameters: 560 * ctx - device context (can obtain our softc here) 561 * inpstat - input status descriptor to receive value 562 * 563 * Return value: 564 * 0 if ok 565 * -1 if an error occured 566 ********************************************************************* */ 567 568static int ds1743_nvram_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) 569{ 570 inpstat->inp_status = 1; 571 572 return 0; 573} 574 575/* ********************************************************************* 576 * ds1743_nvram_write(ctx,buffer) 577 * 578 * Write bytes from the device. 579 * 580 * Input parameters: 581 * ctx - device context (can obtain our softc here) 582 * buffer - buffer descriptor (target buffer, length, offset) 583 * 584 * Return value: 585 * number of bytes read 586 * -1 if an error occured 587 ********************************************************************* */ 588 589static int ds1743_nvram_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 590{ 591 ds1743_nvram_t *softc = ctx->dev_softc; 592 hsaddr_t bptr; 593 int blen; 594 int idx; 595 int b = 0; 596 597 bptr = buffer->buf_ptr; 598 blen = buffer->buf_length; 599 600 if ((buffer->buf_offset + blen) > softc->dev_size) return -1; 601 602 idx = (int) buffer->buf_offset; 603 604 while (blen > 0) { 605 b = hs_read8(bptr); 606 bptr++; 607 softc->data[idx] = b; 608 blen--; 609 idx++; 610 } 611 612 buffer->buf_retlen = bptr - buffer->buf_ptr; 613 return (b < 0) ? -1 : 0; 614} 615 616/* ********************************************************************* 617 * ds1743_nvram_ioctl(ctx,buffer) 618 * 619 * Perform miscellaneous I/O control operations on the device. 620 * 621 * Input parameters: 622 * ctx - device context (can obtain our softc here) 623 * buffer - buffer descriptor (target buffer, length, offset) 624 * 625 * Return value: 626 * number of bytes read 627 * -1 if an error occured 628 ********************************************************************* */ 629 630static int ds1743_nvram_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 631{ 632 ds1743_nvram_t *softc = ctx->dev_softc; 633 nvram_info_t info; 634 635 switch ((int)buffer->buf_ioctlcmd) { 636 case IOCTL_NVRAM_GETINFO: 637 if (buffer->buf_length != sizeof(nvram_info_t)) return -1; 638 info.nvram_offset = softc->env_offset; 639 info.nvram_size = softc->env_size; 640 info.nvram_eraseflg = FALSE; 641 hs_memcpy_to_hs(buffer->buf_ptr,&info,sizeof(info)); 642 buffer->buf_retlen = sizeof(nvram_info_t); 643 return 0; 644 default: 645 return -1; 646 } 647} 648 649/* ********************************************************************* 650 * ds1743_nvram_close(ctx,buffer) 651 * 652 * Close the device. 653 * 654 * Input parameters: 655 * ctx - device context (can obtain our softc here) 656 * 657 * Return value: 658 * 0 if ok 659 * -1 if an error occured 660 ********************************************************************* */ 661 662static int ds1743_nvram_close(cfe_devctx_t *ctx) 663{ 664 return 0; 665} 666 667 668