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