1/* Copyright (c) 2005 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 * */ 25 26/* 27 * This file contains routines to write to and read from the I2C bus using 28 * the ACCESS.bus hardware in the SC1200. 29 * */ 30 31/* SUPER IO DEFINITIONS */ 32 33#define INDEX_1 0x15C /* base address 1 selected */ 34#define DATA_1 0x15D 35#define INDEX_2 0x2E /* base address 2 selected */ 36#define DATA_2 0x2F 37#define PCI_INDEX 0xCF8 /* PCI configuration space INDEX */ 38#define PCI_DATA 0xCFC /* PCI configuration space DATA */ 39#define BASE_ADR_MSB_REG 0x60 /* base address MSB register */ 40#define BASE_ADR_LSB_REG 0x61 /* base address LSB register */ 41 42#define SIO_BASE_ADR_15C_15D 0x6000000 43#define SIO_BASE_ADR_2E_2F 0x4000000 44 45/* SUPER IO GLOBALS */ 46 47unsigned short index_reg, data_reg; 48 49/* ACCESS BUS DEFINITIONS */ 50 51#define ACC_I2C_TIMEOUT 1000000 /* Number of reads before timing out */ 52#define ACB1_BASE 0x810 /* ACCESS.bus base addresses */ 53#define ACB2_BASE 0x820 54#define ACBSDA 0 /* ACB serial data */ 55#define ACBST 1 /* ACB status */ 56#define ACBCST 2 /* ACB control status */ 57#define ACBCTL1 3 /* ACB control 1 */ 58#define ACBADDR 4 /* ACB own address */ 59#define ACBCTL2 5 /* ACB control 2 */ 60#define LDN 0x7 /* Logical Device Numbers */ 61#define ACB1_LDN 0x5 62#define ACB2_LDN 0x6 63 64/* INITIAL ACCESS.bus BASE ADDRESS VALUES */ 65 66unsigned short base_address_array[3] = { 0, ACB1_BASE, ACB2_BASE }; 67 68char Freq = 0x71; 69 70/* LOCAL ACCESS.bus FUNCTION DECLARATIONS */ 71 72void acc_i2c_start(unsigned char busnum); 73void acc_i2c_stop(unsigned char busnum); 74void acc_i2c_abort_data(unsigned char busnum); 75void acc_i2c_bus_recovery(unsigned char busnum); 76void acc_i2c_stall_after_start(unsigned char busnum, int state); 77void acc_i2c_send_address(unsigned char busnum, unsigned char cData); 78int acc_i2c_ack(unsigned char busnum, int fPut, int negAck); 79void acc_i2c_stop_clock(unsigned char busnum); 80void acc_i2c_activate_clock(unsigned char busnum); 81void acc_i2c_write_byte(unsigned char busnum, unsigned char cData); 82unsigned char acc_i2c_read_byte(unsigned char busnum, int last_byte); 83void acc_i2c_reset_bus(unsigned char busnum); 84int acc_i2c_request_master(unsigned char busnum); 85void acc_i2c_config(unsigned char busnum, short adr, char freq); 86char acc_i2c_set_freq(unsigned char busnum, char freq); 87unsigned short acc_i2c_set_base_address(unsigned char busnum, short adr); 88 89/* LOCAL HELPER ROUTINES */ 90 91void OsPciReadDWord(int bus, int dev, int func, int address, 92 unsigned long *data); 93int sio_set_index_data_reg(void); 94void sio_write_reg(unsigned char reg, unsigned char data); 95unsigned char sio_read_reg(unsigned char reg); 96 97/*--------------------------------------------------------------------------- 98 * OsPciReadDWord 99 * 100 * This routine reads one double word from the PCI configuration header 101 * defined by 'bus', 'dev', 'func' and 'address' to the double word 102 * pointed to by 'data'. 103 * 104 * Returns : None. 105 *--------------------------------------------------------------------------- 106 */ 107void 108OsPciReadDWord(int bus, int dev, int func, int address, unsigned long *data) 109{ 110 /* 111 * The address of a double word in the Configuration Header is built in 112 * the following way : 113 * {10000000,bus[23:16],device[15:11],function[10:8],address[7:2],00} 114 */ 115 long addr = (0x80000000 | 116 ((bus & 0xff) << 16) | 117 ((dev & 0x1f) << 11) | ((func & 0x7) << 8) | (address & 0xff)); 118 OUTD(PCI_INDEX, addr); 119 *data = IND(PCI_DATA); 120} 121 122/*--------------------------------------------------------------------------- 123 * sio_set_index_data_reg 124 * 125 * This routine checks which index and data registers to use 126 * in order to access the Super I/O registers 127 * 128 * Returns : 1 - OK 129 * 0 - Super I/O disabled or configuration access disabled 130 *--------------------------------------------------------------------------- 131 */ 132int 133sio_set_index_data_reg(void) 134{ 135 unsigned long xbus_expention_bar, io_control_reg1; 136 137 OsPciReadDWord(0, 0x12, 5, 0x10, &xbus_expention_bar); 138 xbus_expention_bar = xbus_expention_bar & 0xfffffffe; 139 io_control_reg1 = IND((unsigned short) xbus_expention_bar); 140 141 if ((io_control_reg1) & (SIO_BASE_ADR_15C_15D)) { 142 index_reg = INDEX_1; 143 data_reg = DATA_1; 144 return (1); 145 } 146 147 if ((io_control_reg1) & (SIO_BASE_ADR_2E_2F)) { 148 index_reg = INDEX_2; 149 data_reg = DATA_2; 150 return (1); 151 } 152 153 return (0); 154} 155 156/*--------------------------------------------------------------------------- 157 * sio_write_reg 158 * 159 * This routine writes 'data' to 'reg' Super I/O register 160 * 161 * Returns : None 162 *--------------------------------------------------------------------------- 163 */ 164void 165sio_write_reg(unsigned char reg, unsigned char data) 166{ 167 OUTB(index_reg, reg); 168 OUTB(data_reg, data); 169} 170 171/*--------------------------------------------------------------------------- 172 * sio_read_reg 173 * 174 * This routine reads data from 'reg' Super I/O register 175 * 176 * Returns : The data read from the requested register 177 *--------------------------------------------------------------------------- 178 */ 179unsigned char 180sio_read_reg(unsigned char reg) 181{ 182 OUTB(index_reg, reg); 183 return INB(data_reg); 184} 185 186/*--------------------------------------------------------------------------- 187 * gfx_i2c_reset 188 * 189 * This routine resets the I2C bus as follows : 190 * · Sets the base address of the ACCESS.bus 191 * · Sets the frequency of the ACCESS.bus 192 * · Resets the ACCESS.bus 193 * 194 * If 'adr' is -1 the address is read from the hardware. 195 * If 'freq' is -1 the frequency is set to 56 clock cycles. 196 *--------------------------------------------------------------------------- 197 */ 198#if GFX_I2C_DYNAMIC 199int 200acc_i2c_reset(unsigned char busnum, short adr, char freq) 201#else 202int 203gfx_i2c_reset(unsigned char busnum, short adr, char freq) 204#endif 205{ 206 if ((busnum != 1) && (busnum != 2)) 207 return GFX_STATUS_BAD_PARAMETER; 208 acc_i2c_config(busnum, adr, freq); 209 if (base_address_array[busnum] == 0) 210 return GFX_STATUS_ERROR; 211 acc_i2c_reset_bus(busnum); 212 return GFX_STATUS_OK; 213} 214 215/*--------------------------------------------------------------------------- 216 * gfx_i2c_select_gpio 217 * 218 * This routine selects which GPIO pins to use. 219 *--------------------------------------------------------------------------- 220 */ 221#if GFX_I2C_DYNAMIC 222int 223acc_i2c_select_gpio(int clock, int data) 224#else 225int 226gfx_i2c_select_gpio(int clock, int data) 227#endif 228{ 229 /* THIS ROUTINE DOES NOT APPLY TO THE ACCESS.bus IMPLEMENTATION. */ 230 231 return (GFX_STATUS_OK); 232} 233 234/*--------------------------------------------------------------------------- 235 * gfx_i2c_write 236 * 237 * This routine writes data to the specified I2C address. 238 * busnum - ACCESS.bus number (1 or 2). 239 *--------------------------------------------------------------------------- 240 */ 241#if GFX_I2C_DYNAMIC 242int 243acc_i2c_write(unsigned char busnum, unsigned char chipadr, 244 unsigned char subadr, unsigned char bytes, unsigned char *data) 245#else 246int 247gfx_i2c_write(unsigned char busnum, unsigned char chipadr, 248 unsigned char subadr, unsigned char bytes, unsigned char *data) 249#endif 250{ 251 int loop = 0; 252 253 if ((busnum != 1) && (busnum != 2)) 254 return GFX_STATUS_BAD_PARAMETER; 255 256 /* REQUEST MASTER */ 257 258 if (!acc_i2c_request_master(busnum)) 259 return (GFX_STATUS_ERROR); 260 261 /* WRITE ADDRESS COMMAND */ 262 263 acc_i2c_ack(busnum, 1, 0); 264 acc_i2c_stall_after_start(busnum, 1); 265 acc_i2c_send_address(busnum, (unsigned char) (chipadr & 0xFE)); 266 acc_i2c_stall_after_start(busnum, 0); 267 if (!acc_i2c_ack(busnum, 0, 0)) 268 return (GFX_STATUS_ERROR); 269 270 /* WRITE COMMAND */ 271 272 acc_i2c_write_byte(busnum, subadr); 273 if (!acc_i2c_ack(busnum, 0, 0)) 274 return (GFX_STATUS_ERROR); 275 276 /* WRITE DATA */ 277 278 for (loop = 0; loop < bytes; loop++) { 279 acc_i2c_write_byte(busnum, *data); 280 if (loop < (bytes - 1)) 281 data += sizeof(unsigned char); 282 if (!acc_i2c_ack(busnum, 0, 0)) 283 return (GFX_STATUS_ERROR); 284 } 285 data -= (bytes - 1); 286 acc_i2c_stop(busnum); 287 288 return GFX_STATUS_OK; 289} 290 291/*--------------------------------------------------------------------------- 292 * gfx_i2c_read 293 * 294 * This routine reads data from the specified I2C address. 295 * busnum - ACCESS.bus number (1 or 2). 296 *--------------------------------------------------------------------------- 297 */ 298#if GFX_I2C_DYNAMIC 299int 300acc_i2c_read(unsigned char busnum, unsigned char chipadr, 301 unsigned char subadr, unsigned char bytes, unsigned char *data) 302#else 303int 304gfx_i2c_read(unsigned char busnum, unsigned char chipadr, 305 unsigned char subadr, unsigned char bytes, unsigned char *data) 306#endif 307{ 308 unsigned char bytesRead; 309 310 if ((busnum != 1) && (busnum != 2)) 311 return GFX_STATUS_BAD_PARAMETER; 312 313 if (bytes == 0) 314 return GFX_STATUS_OK; 315 316 /* REQUEST MASTER */ 317 318 if (!acc_i2c_request_master(busnum)) 319 return (GFX_STATUS_ERROR); 320 321 /* WRITE ADDRESS COMMAND */ 322 323 acc_i2c_ack(busnum, 1, 0); 324 acc_i2c_stall_after_start(busnum, 1); 325 acc_i2c_send_address(busnum, (unsigned char) (chipadr & 0xFE)); 326 acc_i2c_stall_after_start(busnum, 0); 327 if (!acc_i2c_ack(busnum, 0, 0)) 328 return (GFX_STATUS_ERROR); 329 330 /* WRITE COMMAND */ 331 332 acc_i2c_write_byte(busnum, subadr); 333 if (!acc_i2c_ack(busnum, 0, 0)) 334 return (GFX_STATUS_ERROR); 335 336 /* START THE READ */ 337 338 acc_i2c_start(busnum); 339 340 /* WRITE ADDRESS COMMAND */ 341 342 acc_i2c_ack(busnum, 1, 1); 343 acc_i2c_stall_after_start(busnum, 1); 344 acc_i2c_send_address(busnum, (unsigned char) (chipadr | 0x01)); 345 346 /* IF LAST BYTE */ 347 348 if (bytes == 1) 349 acc_i2c_ack(busnum, 1, 1); 350 else 351 acc_i2c_ack(busnum, 1, 0); 352 353 acc_i2c_stall_after_start(busnum, 0); 354 355 if (!acc_i2c_ack(busnum, 0, 0)) 356 return (GFX_STATUS_ERROR); 357 358 /* READ COMMAND */ 359 360 for (bytesRead = 0; bytesRead < bytes; bytesRead += 1) { 361 if (bytesRead < (bytes - 2)) { 362 data[bytesRead] = acc_i2c_read_byte(busnum, 0); 363 acc_i2c_ack(busnum, 1, 0); 364 } 365 else if (bytesRead == (bytes - 2)) { /* TWO BYTES LEFT */ 366 acc_i2c_ack(busnum, 1, 1); 367 data[bytesRead] = acc_i2c_read_byte(busnum, 0); 368 acc_i2c_ack(busnum, 1, 1); 369 } 370 else { /* LAST BYTE */ 371 372 data[bytesRead] = acc_i2c_read_byte(busnum, 1); 373 acc_i2c_stop(busnum); 374 } 375 376 /* WHILE NOT LAST BYTE */ 377 378 if ((!(bytesRead == (bytes - 1))) && (!acc_i2c_ack(busnum, 0, 0))) 379 return (bytesRead); 380 } 381 382 return GFX_STATUS_OK; 383} 384 385/*--------------------------------------------------------------------------- 386 * gfx_i2c_init 387 * 388 * This routine initializes the use of the ACCESS.BUS. 389 *--------------------------------------------------------------------------- 390 */ 391#if GFX_I2C_DYNAMIC 392int 393acc_i2c_init(void) 394#else 395int 396gfx_i2c_init(void) 397#endif 398{ 399 /* ### ADD ### THIS ROUTINE IS NOT YET IMPLEMENTED FOR ACCESS.bus */ 400 return (GFX_STATUS_OK); 401} 402 403/*--------------------------------------------------------------------------- 404 * gfx_i2c_cleanup 405 * 406 * This routine ends the use of the ACCESS.BUS. 407 *--------------------------------------------------------------------------- 408 */ 409#if GFX_I2C_DYNAMIC 410void 411acc_i2c_cleanup(void) 412#else 413void 414gfx_i2c_cleanup(void) 415#endif 416{ 417 /* ### ADD ### THIS ROUTINE IS NOT YET IMPLEMENTED FOR ACCESS.bus */ 418} 419 420/*--------------------------------------------------------*/ 421/* LOCAL ROUTINES SPECIFIC TO ACCESS.bus IMPLEMENTATION */ 422/*--------------------------------------------------------*/ 423 424/*--------------------------------------------------------------------------- 425 * acc_i2c_reset_bus 426 * 427 * This routine resets the I2C bus. 428 *--------------------------------------------------------------------------- 429 */ 430void 431acc_i2c_reset_bus(unsigned char busnum) 432{ 433 unsigned char reg; 434 unsigned short bus_base_address = base_address_array[busnum]; 435 436 /* Disable the ACCESS.bus device and */ 437 /* Configure the SCL frequency */ 438 OUTB((unsigned short) (bus_base_address + ACBCTL2), 439 (unsigned char) (Freq & 0xFE)); 440 441 /* Configure no interrupt mode (polling) and */ 442 /* Disable global call address */ 443 OUTB((unsigned short) (bus_base_address + ACBCTL1), 0x0); 444 445 /* Disable slave address */ 446 OUTB((unsigned short) (bus_base_address + ACBADDR), 0x0); 447 448 /* Enable the ACCESS.bus device */ 449 reg = INB((unsigned short) (bus_base_address + ACBCTL2)); 450 reg |= 0x01; 451 OUTB((unsigned short) (bus_base_address + ACBCTL2), reg); 452 453 /* Issue STOP event */ 454 455 acc_i2c_stop(busnum); 456 457 /* Clear NEGACK, STASTR and BER bits */ 458 OUTB((unsigned short) (bus_base_address + ACBST), 0x38); 459 460 /* Clear BB (BUS BUSY) bit */ 461 reg = INB((unsigned short) (bus_base_address + ACBCST)); 462 reg |= 0x02; 463 OUTB((unsigned short) (bus_base_address + ACBCST), reg); 464} 465 466/*--------------------------------------------------------------------------- 467 * acc_i2c_start 468 * 469 * This routine starts a transfer on the I2C bus. 470 *--------------------------------------------------------------------------- 471 */ 472void 473acc_i2c_start(unsigned char busnum) 474{ 475 unsigned char reg; 476 unsigned short bus_base_address = base_address_array[busnum]; 477 478 reg = INB((unsigned short) (bus_base_address + ACBCTL1)); 479 reg |= 0x01; 480 OUTB((unsigned short) (bus_base_address + ACBCTL1), reg); 481} 482 483/*--------------------------------------------------------------------------- 484 * acc_i2c_stop 485 * 486 * This routine stops a transfer on the I2C bus. 487 *--------------------------------------------------------------------------- 488 */ 489void 490acc_i2c_stop(unsigned char busnum) 491{ 492 unsigned char reg; 493 unsigned short bus_base_address = base_address_array[busnum]; 494 495 reg = INB((unsigned short) (bus_base_address + ACBCTL1)); 496 reg |= 0x02; 497 OUTB((unsigned short) (bus_base_address + ACBCTL1), reg); 498} 499 500/*--------------------------------------------------------------------------- 501 * acc_i2c_abort_data 502 *--------------------------------------------------------------------------- 503 */ 504void 505acc_i2c_abort_data(unsigned char busnum) 506{ 507 unsigned char reg; 508 unsigned short bus_base_address = base_address_array[busnum]; 509 510 acc_i2c_stop(busnum); 511 reg = INB((unsigned short) (bus_base_address + ACBCTL1)); 512 reg |= 0x10; 513 OUTB((unsigned short) (bus_base_address + ACBCTL1), reg); 514} 515 516/*--------------------------------------------------------------------------- 517 * acc_i2c_bus_recovery 518 *--------------------------------------------------------------------------- 519 */ 520void 521acc_i2c_bus_recovery(unsigned char busnum) 522{ 523 acc_i2c_abort_data(busnum); 524 acc_i2c_reset_bus(busnum); 525} 526 527/*--------------------------------------------------------------------------- 528 * acc_i2c_stall_after_start 529 *--------------------------------------------------------------------------- 530 */ 531void 532acc_i2c_stall_after_start(unsigned char busnum, int state) 533{ 534 unsigned char reg; 535 unsigned short bus_base_address = base_address_array[busnum]; 536 537 reg = INB((unsigned short) (bus_base_address + ACBCTL1)); 538 if (state) 539 reg |= 0x80; 540 else 541 reg &= 0x7F; 542 OUTB((unsigned short) (bus_base_address + ACBCTL1), reg); 543 544 if (!state) { 545 reg = INB((unsigned short) (bus_base_address + ACBST)); 546 reg |= 0x08; 547 OUTB((unsigned short) (bus_base_address + ACBST), reg); 548 } 549} 550 551/*--------------------------------------------------------------------------- 552 * acc_i2c_send_address 553 *--------------------------------------------------------------------------- 554 */ 555void 556acc_i2c_send_address(unsigned char busnum, unsigned char cData) 557{ 558 unsigned char reg; 559 unsigned short bus_base_address = base_address_array[busnum]; 560 unsigned long timeout = 0; 561 562 /* WRITE THE DATA */ 563 564 OUTB((unsigned short) (bus_base_address + ACBSDA), cData); 565 while (1) { 566 reg = INB((unsigned short) (bus_base_address + ACBST)); 567 if ((reg & 0x38) != 0) /* check STASTR, BER and NEGACK */ 568 break; 569 if (timeout++ == ACC_I2C_TIMEOUT) { 570 acc_i2c_bus_recovery(busnum); 571 return; 572 } 573 } 574 575 /* CHECK FOR BUS ERROR */ 576 577 if (reg & 0x20) { 578 acc_i2c_bus_recovery(busnum); 579 return; 580 } 581 582 /* CHECK NEGATIVE ACKNOWLEDGE */ 583 584 if (reg & 0x10) { 585 acc_i2c_abort_data(busnum); 586 return; 587 } 588 589} 590 591/*--------------------------------------------------------------------------- 592 * acc_i2c_ack 593 * 594 * This routine looks for acknowledge on the I2C bus. 595 *--------------------------------------------------------------------------- 596 */ 597int 598acc_i2c_ack(unsigned char busnum, int fPut, int negAck) 599{ 600 unsigned char reg; 601 unsigned short bus_base_address = base_address_array[busnum]; 602 unsigned long timeout = 0; 603 604 if (fPut) { /* read operation */ 605 if (!negAck) { 606 /* Push Ack onto I2C bus */ 607 reg = INB((unsigned short) (bus_base_address + ACBCTL1)); 608 reg &= 0xE7; 609 OUTB((unsigned short) (bus_base_address + ACBCTL1), reg); 610 } 611 else { 612 /* Push negAck onto I2C bus */ 613 reg = INB((unsigned short) (bus_base_address + ACBCTL1)); 614 reg |= 0x10; 615 OUTB((unsigned short) (bus_base_address + ACBCTL1), reg); 616 } 617 } 618 else { /* write operation */ 619 /* Receive Ack from I2C bus */ 620 while (1) { 621 reg = INB((unsigned short) (bus_base_address + ACBST)); 622 if ((reg & 0x70) != 0) /* check SDAST, BER and NEGACK */ 623 break; 624 if (timeout++ == ACC_I2C_TIMEOUT) { 625 acc_i2c_bus_recovery(busnum); 626 return (0); 627 } 628 } 629 630 /* CHECK FOR BUS ERROR */ 631 632 if (reg & 0x20) { 633 acc_i2c_bus_recovery(busnum); 634 return (0); 635 } 636 637 /* CHECK NEGATIVE ACKNOWLEDGE */ 638 639 if (reg & 0x10) { 640 acc_i2c_abort_data(busnum); 641 return (0); 642 } 643 } 644 return (1); 645} 646 647/*--------------------------------------------------------------------------- 648 * acc_i2c_stop_clock 649 * 650 * This routine stops the ACCESS.bus clock. 651 *--------------------------------------------------------------------------- 652 */ 653void 654acc_i2c_stop_clock(unsigned char busnum) 655{ 656 unsigned char reg; 657 unsigned short bus_base_address = base_address_array[busnum]; 658 659 reg = INB((unsigned short) (bus_base_address + ACBCTL2)); 660 reg &= ~0x01; 661 OUTB((unsigned short) (bus_base_address + ACBCTL2), reg); 662} 663 664/*--------------------------------------------------------------------------- 665 * acc_i2c_activate_clock 666 * 667 * This routine activates the ACCESS.bus clock. 668 *--------------------------------------------------------------------------- 669 */ 670void 671acc_i2c_activate_clock(unsigned char busnum) 672{ 673 unsigned char reg; 674 unsigned short bus_base_address = base_address_array[busnum]; 675 676 reg = INB((unsigned short) (bus_base_address + ACBCTL2)); 677 reg |= 0x01; 678 OUTB((unsigned short) (bus_base_address + ACBCTL2), reg); 679} 680 681/*--------------------------------------------------------------------------- 682 * acc_i2c_write_byte 683 * 684 * This routine writes a byte to the I2C bus 685 *--------------------------------------------------------------------------- 686 */ 687void 688acc_i2c_write_byte(unsigned char busnum, unsigned char cData) 689{ 690 unsigned char reg; 691 unsigned short bus_base_address = base_address_array[busnum]; 692 unsigned long timeout = 0; 693 694 while (1) { 695 reg = INB((unsigned short) (bus_base_address + ACBST)); 696 if (reg & 0x70) 697 break; 698 if (timeout++ == ACC_I2C_TIMEOUT) { 699 acc_i2c_bus_recovery(busnum); 700 return; 701 } 702 } 703 704 /* CHECK FOR BUS ERROR */ 705 706 if (reg & 0x20) { 707 acc_i2c_bus_recovery(busnum); 708 return; 709 } 710 711 /* CHECK NEGATIVE ACKNOWLEDGE */ 712 713 if (reg & 0x10) { 714 acc_i2c_abort_data(busnum); 715 return; 716 } 717 718 /* WRITE THE DATA */ 719 720 OUTB((unsigned short) (bus_base_address + ACBSDA), cData); 721} 722 723/*--------------------------------------------------------------------------- 724 * acc_i2c_read_byte 725 * 726 * This routine reads a byte from the I2C bus 727 *--------------------------------------------------------------------------- 728 */ 729unsigned char 730acc_i2c_read_byte(unsigned char busnum, int last_byte) 731{ 732 unsigned char cData, reg; 733 unsigned short bus_base_address = base_address_array[busnum]; 734 unsigned long timeout = 0; 735 736 while (1) { 737 reg = INB((unsigned short) (bus_base_address + ACBST)); 738 if (reg & 0x60) 739 break; 740 if (timeout++ == ACC_I2C_TIMEOUT) { 741 acc_i2c_bus_recovery(busnum); 742 return (0xEF); 743 } 744 } 745 746 /* CHECK FOR BUS ERROR */ 747 748 if (reg & 0x20) { 749 acc_i2c_bus_recovery(busnum); 750 return (0xEE); 751 } 752 753 /* READ DATA */ 754 if (last_byte) 755 acc_i2c_stop_clock(busnum); 756 cData = INB((unsigned short) (bus_base_address + ACBSDA)); 757 if (last_byte) 758 acc_i2c_activate_clock(busnum); 759 760 return (cData); 761} 762 763/*--------------------------------------------------------------------------- 764 * acc_i2c_request_master 765 *--------------------------------------------------------------------------- 766 */ 767int 768acc_i2c_request_master(unsigned char busnum) 769{ 770 unsigned char reg; 771 unsigned short bus_base_address = base_address_array[busnum]; 772 unsigned long timeout = 0; 773 774 acc_i2c_start(busnum); 775 while (1) { 776 reg = INB((unsigned short) (bus_base_address + ACBST)); 777 if (reg & 0x60) 778 break; 779 if (timeout++ == ACC_I2C_TIMEOUT) { 780 acc_i2c_bus_recovery(busnum); 781 return (0); 782 } 783 } 784 785 /* CHECK FOR BUS ERROR */ 786 787 if (reg & 0x20) { 788 acc_i2c_abort_data(busnum); 789 return (0); 790 } 791 792 /* CHECK NEGATIVE ACKNOWLEDGE */ 793 794 if (reg & 0x10) { 795 acc_i2c_abort_data(busnum); 796 return (0); 797 } 798 return (1); 799} 800 801/*--------------------------------------------------------*/ 802/* LOCAL ROUTINES SPECIFIC TO ACCESS.bus INITIALIZATION */ 803/*--------------------------------------------------------*/ 804 805/*---------------------------------------------------------------------------- 806 * acc_i2c_config 807 * 808 * This routine configures the I2C bus 809 *---------------------------------------------------------------------------- 810 */ 811void 812acc_i2c_config(unsigned char busnum, short adr, char freq) 813{ 814 base_address_array[busnum] = acc_i2c_set_base_address(busnum, adr); 815 Freq = acc_i2c_set_freq(busnum, freq); 816} 817 818/*---------------------------------------------------------------------------- 819 * acc_i2c_set_freq 820 * 821 * This routine sets the frequency of the I2C bus 822 *---------------------------------------------------------------------------- 823 */ 824char 825acc_i2c_set_freq(unsigned char busnum, char freq) 826{ 827 unsigned short bus_base_address = base_address_array[busnum]; 828 829 OUTB((unsigned short) (bus_base_address + ACBCTL2), 0x0); 830 831 if (freq == -1) 832 freq = 0x71; 833 else { 834 freq = freq << 1; 835 freq |= 0x01; 836 } 837 838 OUTB((unsigned short) (bus_base_address + ACBCTL2), freq); 839 return (freq); 840} 841 842/*--------------------------------------------------------------------------- 843 * acc_i2c_set_base_address 844 * 845 * This routine sets the base address of the I2C bus 846 *--------------------------------------------------------------------------- 847 */ 848unsigned short 849acc_i2c_set_base_address(unsigned char busnum, short adr) 850{ 851 unsigned short ab_base_addr; 852 853 /* Get Super I/O Index and Data registers */ 854 if (!sio_set_index_data_reg()) 855 return (0); 856 857 /* Configure LDN to current ACB */ 858 if (busnum == 1) 859 sio_write_reg(LDN, ACB1_LDN); 860 if (busnum == 2) 861 sio_write_reg(LDN, ACB2_LDN); 862 863 if (adr == -1) { 864 /* Get ACCESS.bus base address */ 865 ab_base_addr = sio_read_reg(BASE_ADR_MSB_REG); 866 ab_base_addr = ab_base_addr << 8; 867 ab_base_addr |= sio_read_reg(BASE_ADR_LSB_REG); 868 if (ab_base_addr != 0) 869 return ab_base_addr; 870 else 871 adr = (busnum == 1 ? ACB1_BASE : ACB2_BASE); 872 } 873 874 /* Set ACCESS.bus base address */ 875 sio_write_reg(BASE_ADR_LSB_REG, (unsigned char) (adr & 0xFF)); 876 sio_write_reg(BASE_ADR_MSB_REG, (unsigned char) (adr >> 8)); 877 878 return adr; 879} 880 881/* END OF FILE */ 882