1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Xicor RTC/EEPROM driver File: dev_smbus_x1227eeprom.c 5 * 6 * This module contains a CFE driver for a Xicor X1227 SMBus 7 * real-time-clock & EEPROM module. The only functionality 8 * we currently export is the EEPROM, for use as environment 9 * storage. 10 * 11 * Author: Mitch Lichtenberg 12 * 13 ********************************************************************* 14 * 15 * Copyright 2000,2001,2002,2003 16 * Broadcom Corporation. All rights reserved. 17 * 18 * This software is furnished under license and may be used and 19 * copied only in accordance with the following terms and 20 * conditions. Subject to these conditions, you may download, 21 * copy, install, use, modify and distribute modified or unmodified 22 * copies of this software in source and/or binary form. No title 23 * or ownership is transferred hereby. 24 * 25 * 1) Any source code used, modified or distributed must reproduce 26 * and retain this copyright notice and list of conditions 27 * as they appear in the source file. 28 * 29 * 2) No right is granted to use any trade name, trademark, or 30 * logo of Broadcom Corporation. The "Broadcom Corporation" 31 * name may not be used to endorse or promote products derived 32 * from this software without the prior written permission of 33 * Broadcom Corporation. 34 * 35 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 36 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 37 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 38 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 39 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 40 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 41 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 43 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 46 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 47 * THE POSSIBILITY OF SUCH DAMAGE. 48 ********************************************************************* */ 49 50 51#include "cfe.h" 52#include "cfe_smbus.h" 53 54/* 55 * XXX: The X1227 is a superset of the X1240/X1241 except that its 56 * EEPROM is 512 bytes and thus the block-protect bits cover smaller 57 * ranges. The drivers should be unified. 58 */ 59 60/* ********************************************************************* 61 * Xicor X1227 RTC constants 62 ********************************************************************* */ 63/* 64 * Register bits 65 */ 66 67#define X1227REG_SR_BAT 0x80 /* currently on battery power */ 68#define X1227REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */ 69#define X1227REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */ 70#define X1227REG_SR_RTCF 0x01 /* clock failed */ 71#define X1227REG_BL_BP2 0x80 /* block protect 2 */ 72#define X1227REG_BL_BP1 0x40 /* block protect 1 */ 73#define X1227REG_BL_BP0 0x20 /* block protect 0 */ 74#define X1227REG_BL_WD1 0x10 75#define X1227REG_BL_WD0 0x08 76#define X1227REG_HR_MIL 0x80 /* military time format */ 77 78/* 79 * Register numbers 80 */ 81 82#define X1227REG_BL 0x10 /* block protect bits */ 83#define X1227REG_INT 0x11 /* */ 84#define X1227REG_SC 0x30 /* Seconds */ 85#define X1227REG_MN 0x31 /* Minutes */ 86#define X1227REG_HR 0x32 /* Hours */ 87#define X1227REG_DT 0x33 /* Day of month */ 88#define X1227REG_MO 0x34 /* Month */ 89#define X1227REG_YR 0x35 /* Year */ 90#define X1227REG_DW 0x36 /* Day of Week */ 91#define X1227REG_Y2K 0x37 /* Year 2K */ 92#define X1227REG_SR 0x3F /* Status register */ 93 94#define X1227_CCR_ADDRESS 0x6F 95#define X1227_ARRAY_ADDRESS 0x57 96 97#define X1227_EEPROM_SIZE 512 98 99/* ********************************************************************* 100 * Forward Declarations 101 ********************************************************************* */ 102 103static void sb1250_x1227eeprom_probe(cfe_driver_t *drv, 104 unsigned long probe_a, unsigned long probe_b, 105 void *probe_ptr); 106 107 108static int sb1250_x1227eeprom_open(cfe_devctx_t *ctx); 109static int sb1250_x1227eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 110static int sb1250_x1227eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); 111static int sb1250_x1227eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 112static int sb1250_x1227eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 113static int sb1250_x1227eeprom_close(cfe_devctx_t *ctx); 114 115/* ********************************************************************* 116 * Dispatch tables 117 ********************************************************************* */ 118 119const static cfe_devdisp_t sb1250_x1227eeprom_dispatch = { 120 sb1250_x1227eeprom_open, 121 sb1250_x1227eeprom_read, 122 sb1250_x1227eeprom_inpstat, 123 sb1250_x1227eeprom_write, 124 sb1250_x1227eeprom_ioctl, 125 sb1250_x1227eeprom_close, 126 NULL, 127 NULL 128}; 129 130const cfe_driver_t smbus_x1227eeprom = { 131 "Xicor X1227 EEPROM", 132 "eeprom", 133 CFE_DEV_NVRAM, 134 &sb1250_x1227eeprom_dispatch, 135 sb1250_x1227eeprom_probe 136}; 137 138typedef struct sb1250_x1227eeprom_s { 139 cfe_smbus_channel_t *smbus_channel; 140 int env_offset; 141 int env_size; 142} sb1250_x1227eeprom_t; 143 144 145 146 147/* ********************************************************************* 148 * smbus_readrtc(chan,slaveaddr,devaddr) 149 * 150 * Read a byte from the chip. The 'slaveaddr' parameter determines 151 * whether we're reading from the RTC section or the EEPROM section. 152 * 153 * Input parameters: 154 * chan - SMBus channel 155 * slaveaddr - SMBus slave address 156 * devaddr - byte with in the X1227 device to read 157 * 158 * Return value: 159 * 0 if ok 160 * else -1 161 ********************************************************************* */ 162 163static int smbus_readrtc(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr) 164{ 165 uint8_t buf[2]; 166 int err; 167 168 /* 169 * Write the device address to the controller. There are two 170 * parts, the high part goes in the "CMD" field, and the 171 * low part is the data field. 172 */ 173 174 buf[0] = (devaddr >> 8) & 0x07; 175 buf[1] = (devaddr & 0xFF); 176 177 err = SMBUS_WRITE(chan,slaveaddr,buf,2); 178 if (err < 0) return err; 179 180 /* 181 * Read the data byte 182 */ 183 184 err = SMBUS_READ(chan,slaveaddr,buf,1); 185 if (err < 0) return err; 186 187 return (buf[0]); 188} 189 190/* ********************************************************************* 191 * smbus_writertc(chan,slaveaddr,devaddr,b) 192 * 193 * write a byte from the chip. The 'slaveaddr' parameter determines 194 * whethe we're writing to the RTC section or the EEPROM section. 195 * 196 * Input parameters: 197 * chan - SMBus channel 198 * slaveaddr - SMBus slave address 199 * devaddr - byte with in the X1227 device to read 200 * b - byte to write 201 * 202 * Return value: 203 * 0 if ok 204 * else -1 205 ********************************************************************* */ 206 207 208static int smbus_writertc(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr,int b) 209{ 210 uint8_t buf[3]; 211 int err; 212 int64_t timer; 213 214 215 /* 216 * Write the data to the controller 217 */ 218 219 220 buf[0] = (devaddr >> 8) & 0x07; 221 buf[1] = (devaddr & 0xFF); 222 buf[2] = b; 223 224 err = SMBUS_WRITE(chan,slaveaddr,buf,3); 225 if (err < 0) return err; 226 227 /* 228 * Pound on the device with a current address read 229 * to poll for the write complete 230 */ 231 232 TIMER_SET(timer,50); 233 err = -1; 234 235 while (!TIMER_EXPIRED(timer)) { 236 POLL(); 237 238 err = SMBUS_READ(chan,slaveaddr,buf,1); 239 if (err == 0) break; 240 } 241 242 return err; 243} 244 245 246/* ********************************************************************* 247 * sb1250_x1227eeprom_probe(drv,a,b,ptr) 248 * 249 * Probe routine for this driver. This routine creates the 250 * local device context and attaches it to the driver list 251 * within CFE. 252 * 253 * Input parameters: 254 * drv - driver handle 255 * a,b - probe hints (longs) 256 * ptr - probe hint (pointer) 257 * 258 * Return value: 259 * nothing 260 ********************************************************************* */ 261 262static void sb1250_x1227eeprom_probe(cfe_driver_t *drv, 263 unsigned long probe_a, unsigned long probe_b, 264 void *probe_ptr) 265{ 266 sb1250_x1227eeprom_t *softc; 267 char descr[80]; 268 269 softc = (sb1250_x1227eeprom_t *) KMALLOC(sizeof(sb1250_x1227eeprom_t),0); 270 271 /* 272 * Probe_a is the SMBus channel number 273 * Probe_b is the SMBus device offset 274 * Probe_ptr is unused. 275 */ 276 277 softc->smbus_channel = SMBUS_CHANNEL((int)probe_a); 278 softc->env_offset = 0; 279 softc->env_size = X1227_EEPROM_SIZE; 280 281 xsprintf(descr,"%s on SMBus channel %d dev 0x%02X", 282 drv->drv_description,probe_a,X1227_ARRAY_ADDRESS); 283 cfe_attach(drv,softc,NULL,descr); 284} 285 286 287 288/* ********************************************************************* 289 * sb1250_x1227eeprom_open(ctx) 290 * 291 * Open this device. For the X1227, we do a quick test 292 * read to be sure the device is out there. 293 * 294 * Input parameters: 295 * ctx - device context (can obtain our softc here) 296 * 297 * Return value: 298 * 0 if ok 299 * else error code 300 ********************************************************************* */ 301 302static int sb1250_x1227eeprom_open(cfe_devctx_t *ctx) 303{ 304 sb1250_x1227eeprom_t *softc = ctx->dev_softc; 305 int b; 306 int64_t timer; 307 308 /* 309 * Try to read byte 0 from the device. If it does not 310 * respond, fail the open. We may need to do this for 311 * up to 300ms in case the X1227 is busy wiggling its 312 * RESET line. 313 */ 314 315 TIMER_SET(timer,300); 316 while (!TIMER_EXPIRED(timer)) { 317 POLL(); 318 b = smbus_readrtc(softc->smbus_channel, 319 X1227_ARRAY_ADDRESS, 320 0); 321 if (b >= 0) break; /* read is ok */ 322 } 323 324 /* 325 * See if the watchdog is enabled. If it is, turn it off. 326 */ 327 328 b = smbus_readrtc(softc->smbus_channel, 329 X1227_CCR_ADDRESS, 330 X1227REG_BL); 331 332 if (b != (X1227REG_BL_WD1 | X1227REG_BL_WD0)) { 333 334 smbus_writertc(softc->smbus_channel, 335 X1227_CCR_ADDRESS, 336 X1227REG_SR, 337 X1227REG_SR_WEL); 338 339 smbus_writertc(softc->smbus_channel, 340 X1227_CCR_ADDRESS, 341 X1227REG_SR, 342 X1227REG_SR_WEL | X1227REG_SR_RWEL); 343 344 smbus_writertc(softc->smbus_channel, 345 X1227_CCR_ADDRESS, 346 X1227REG_BL, 347 (X1227REG_BL_WD1 | X1227REG_BL_WD0)); 348 349 smbus_writertc(softc->smbus_channel, 350 X1227_CCR_ADDRESS, 351 X1227REG_SR, 352 0); 353 } 354 355 356 357 return (b < 0) ? -1 : 0; 358} 359 360/* ********************************************************************* 361 * sb1250_x1227eeprom_read(ctx,buffer) 362 * 363 * Read bytes from the device. 364 * 365 * Input parameters: 366 * ctx - device context (can obtain our softc here) 367 * buffer - buffer descriptor (target buffer, length, offset) 368 * 369 * Return value: 370 * number of bytes read 371 * -1 if an error occured 372 ********************************************************************* */ 373 374static int sb1250_x1227eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 375{ 376 sb1250_x1227eeprom_t *softc = ctx->dev_softc; 377 hsaddr_t bptr; 378 int blen; 379 int idx; 380 int b = 0; 381 382 bptr = buffer->buf_ptr; 383 blen = buffer->buf_length; 384 385 if ((buffer->buf_offset + blen) > X1227_EEPROM_SIZE) return -1; 386 387 idx = (int) buffer->buf_offset; 388 389 while (blen > 0) { 390 b = smbus_readrtc(softc->smbus_channel, 391 X1227_ARRAY_ADDRESS, 392 idx); 393 if (b < 0) break; 394 hs_write8(bptr,(unsigned char) b); 395 bptr++; 396 blen--; 397 idx++; 398 } 399 400 buffer->buf_retlen = bptr - buffer->buf_ptr; 401 return (b < 0) ? -1 : 0; 402} 403 404/* ********************************************************************* 405 * sb1250_x1227eeprom_inpstat(ctx,inpstat) 406 * 407 * Test input (read) status for the device 408 * 409 * Input parameters: 410 * ctx - device context (can obtain our softc here) 411 * inpstat - input status descriptor to receive value 412 * 413 * Return value: 414 * 0 if ok 415 * -1 if an error occured 416 ********************************************************************* */ 417 418static int sb1250_x1227eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) 419{ 420 inpstat->inp_status = 1; 421 422 return 0; 423} 424 425/* ********************************************************************* 426 * sb1250_x1227eeprom_write(ctx,buffer) 427 * 428 * Write bytes from the device. 429 * 430 * Input parameters: 431 * ctx - device context (can obtain our softc here) 432 * buffer - buffer descriptor (target buffer, length, offset) 433 * 434 * Return value: 435 * number of bytes read 436 * -1 if an error occured 437 ********************************************************************* */ 438 439static int sb1250_x1227eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 440{ 441 sb1250_x1227eeprom_t *softc = ctx->dev_softc; 442 hsaddr_t bptr; 443 int blen; 444 int idx; 445 int b = 0; 446 447 bptr = buffer->buf_ptr; 448 blen = buffer->buf_length; 449 450 if ((buffer->buf_offset + blen) > X1227_EEPROM_SIZE) return -1; 451 452 idx = (int) buffer->buf_offset; 453 454 smbus_writertc(softc->smbus_channel, 455 X1227_CCR_ADDRESS, 456 X1227REG_SR, 457 X1227REG_SR_WEL); 458 459 460 while (blen > 0) { 461 b = hs_read8(bptr); 462 bptr++; 463 b = smbus_writertc(softc->smbus_channel, 464 X1227_ARRAY_ADDRESS, 465 idx, 466 b); 467 if (b < 0) break; 468 blen--; 469 idx++; 470 } 471 472 smbus_writertc(softc->smbus_channel, 473 X1227_CCR_ADDRESS, 474 X1227REG_SR, 475 0); 476 477 buffer->buf_retlen = bptr - buffer->buf_ptr; 478 return (b < 0) ? -1 : 0; 479} 480 481/* ********************************************************************* 482 * sb1250_x1227eeprom_ioctl(ctx,buffer) 483 * 484 * Perform miscellaneous I/O control operations on the device. 485 * 486 * Input parameters: 487 * ctx - device context (can obtain our softc here) 488 * buffer - buffer descriptor (target buffer, length, offset) 489 * 490 * Return value: 491 * number of bytes read 492 * -1 if an error occured 493 ********************************************************************* */ 494 495static int sb1250_x1227eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 496{ 497 sb1250_x1227eeprom_t *softc = ctx->dev_softc; 498 nvram_info_t info; 499 500 switch ((int)buffer->buf_ioctlcmd) { 501 case IOCTL_NVRAM_GETINFO: 502 if (buffer->buf_length != sizeof(nvram_info_t)) return -1; 503 info.nvram_offset = softc->env_offset; 504 info.nvram_size = softc->env_size; 505 info.nvram_eraseflg = FALSE; 506 buffer->buf_retlen = sizeof(nvram_info_t); 507 hs_memcpy_to_hs(buffer->buf_ptr,&info,sizeof(info)); 508 return 0; 509 default: 510 return -1; 511 } 512} 513 514/* ********************************************************************* 515 * sb1250_x1227eeprom_close(ctx,buffer) 516 * 517 * Close the device. 518 * 519 * Input parameters: 520 * ctx - device context (can obtain our softc here) 521 * 522 * Return value: 523 * 0 if ok 524 * -1 if an error occured 525 ********************************************************************* */ 526 527static int sb1250_x1227eeprom_close(cfe_devctx_t *ctx) 528{ 529 return 0; 530} 531 532 533