1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/i2c_gpio.c,v 1.1 2002/12/10 15:12:26 alanh Exp $ */ 2/* 3 * $Workfile: i2c_gpio.c $ 4 * 5 * This file contains routines to write to and read from the I2C bus using 6 * the GPIO pins of the CS5530. 7 * 8 * NSC_LIC_ALTERNATIVE_PREAMBLE 9 * 10 * Revision 1.0 11 * 12 * National Semiconductor Alternative GPL-BSD License 13 * 14 * National Semiconductor Corporation licenses this software 15 * ("Software"): 16 * 17 * Durango 18 * 19 * under one of the two following licenses, depending on how the 20 * Software is received by the Licensee. 21 * 22 * If this Software is received as part of the Linux Framebuffer or 23 * other GPL licensed software, then the GPL license designated 24 * NSC_LIC_GPL applies to this Software; in all other circumstances 25 * then the BSD-style license designated NSC_LIC_BSD shall apply. 26 * 27 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */ 28 29/* NSC_LIC_BSD 30 * 31 * National Semiconductor Corporation Open Source License for Durango 32 * 33 * (BSD License with Export Notice) 34 * 35 * Copyright (c) 1999-2001 36 * National Semiconductor Corporation. 37 * All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 43 * * Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 46 * * Redistributions in binary form must reproduce the above 47 * copyright notice, this list of conditions and the following 48 * disclaimer in the documentation and/or other materials provided 49 * with the distribution. 50 * 51 * * Neither the name of the National Semiconductor Corporation nor 52 * the names of its contributors may be used to endorse or promote 53 * products derived from this software without specific prior 54 * written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 57 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 58 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 59 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 60 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 61 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 63 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 64 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 65 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 66 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 68 * OF SUCH DAMAGE. 69 * 70 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 71 * YOUR JURISDICTION. It is licensee's responsibility to comply with 72 * any export regulations applicable in licensee's jurisdiction. Under 73 * CURRENT (2001) U.S. export regulations this software 74 * is eligible for export from the U.S. and can be downloaded by or 75 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 76 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 77 * Syria, Sudan, Afghanistan and any other country to which the U.S. 78 * has embargoed goods and services. 79 * 80 * END_NSC_LIC_BSD */ 81 82/* NSC_LIC_GPL 83 * 84 * National Semiconductor Corporation Gnu General Public License for Durango 85 * 86 * (GPL License with Export Notice) 87 * 88 * Copyright (c) 1999-2001 89 * National Semiconductor Corporation. 90 * All rights reserved. 91 * 92 * Redistribution and use in source and binary forms, with or without 93 * modification, are permitted under the terms of the GNU General 94 * Public License as published by the Free Software Foundation; either 95 * version 2 of the License, or (at your option) any later version 96 * 97 * In addition to the terms of the GNU General Public License, neither 98 * the name of the National Semiconductor Corporation nor the names of 99 * its contributors may be used to endorse or promote products derived 100 * from this software without specific prior written permission. 101 * 102 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 103 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 104 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 105 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 106 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 107 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 108 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 109 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 110 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 111 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 112 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 113 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 114 * OF SUCH DAMAGE. See the GNU General Public License for more details. 115 * 116 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 117 * YOUR JURISDICTION. It is licensee's responsibility to comply with 118 * any export regulations applicable in licensee's jurisdiction. Under 119 * CURRENT (2001) U.S. export regulations this software 120 * is eligible for export from the U.S. and can be downloaded by or 121 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 122 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 123 * Syria, Sudan, Afghanistan and any other country to which the U.S. 124 * has embargoed goods and services. 125 * 126 * You should have received a copy of the GNU General Public License 127 * along with this file; if not, write to the Free Software Foundation, 128 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 129 * 130 * END_NSC_LIC_GPL */ 131 132/* STATIC VARIABLES TO STORE WHAT GPIO PINS TO USE */ 133 134int gpio_clock = 0; 135int gpio_data = 0; 136 137static int g_initialized = 0; 138 139#define I2CWRITE 0x00 /* Write address */ 140#define I2CREAD 0x01 /* Read address */ 141 142#define I2CACK 0x00 /* Ack value */ 143#define I2CNACK 0x01 /* Not - ack value */ 144 145#define CS5530_ID (0x80000000 | (0x00<<16) | (0x12<<11) | (0<<8) | 0x00) 146#define CS5530_GPIO (0x80000000 | (0x00<<16) | (0x12<<11) | (0<<8) | 0x90) 147#define SDA 0x0800 148#define SCL 0x0400 149#define SDADIR 0x0008 150#define SCLDIR 0x0004 151 152int I2C_init(void); 153void I2C_cleanup(void); 154 155int I2C_Read(unsigned char address, unsigned int reg, unsigned long *p_value, 156 unsigned int bytes); 157int I2C_Write(unsigned char address, unsigned int reg, unsigned long value, 158 unsigned int bytes); 159int I2CAL_init(void); 160void I2CAL_cleanup(void); 161 162void I2CAL_output_clock(int state); 163void I2CAL_output_data(int state); 164unsigned char I2CAL_input_data(void); 165 166void I2CAL_set_data_for_input(void); 167void I2CAL_set_data_for_output(void); 168 169void SendI2CStart(void); 170void SendI2CData(unsigned char inData); 171 172unsigned char ReceiveI2CAck(void); 173void SendI2CStop(void); 174void SendI2CNack(void); 175void SendI2CAck(void); 176unsigned char ReceiveI2CData(void); 177 178int gpio_i2c_reset(unsigned char busnum, short adr, char freq); 179int gpio_i2c_write(unsigned char busnum, unsigned char chipadr, 180 unsigned char subadr, unsigned char bytes, 181 unsigned char *data); 182int gpio_i2c_read(unsigned char busnum, unsigned char chipadr, 183 unsigned char subadr, unsigned char bytes, 184 unsigned char *data); 185int gpio_i2c_select_gpio(int clock, int data); 186int gpio_i2c_init(void); 187void gpio_i2c_cleanup(void); 188 189/* ### ADD ### ANY LOCAL ROUTINE DEFINITIONS SPECIFIC TO GPIO */ 190 191/*--------------------------------------------------------------------------- 192 * gfx_i2c_reset 193 * 194 * This routine resets the I2C bus. 195 *--------------------------------------------------------------------------- 196 */ 197 198#if GFX_I2C_DYNAMIC 199int 200gpio_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 /* ### ADD ### Any code needed to reset the state of the GPIOs. */ 207 return GFX_STATUS_OK; 208} 209 210/*--------------------------------------------------------------------------- 211 * gfx_i2c_select_gpio 212 * 213 * This routine selects which GPIO pins to use. 214 *--------------------------------------------------------------------------- 215 */ 216#if GFX_I2C_DYNAMIC 217int 218gpio_i2c_select_gpio(int clock, int data) 219#else 220int 221gfx_i2c_select_gpio(int clock, int data) 222#endif 223{ 224 gpio_clock = clock; 225 gpio_data = data; 226 return (0); 227} 228 229/*--------------------------------------------------------------------------- 230 * gfx_i2c_write 231 * 232 * This routine writes data to the specified I2C address. 233 *--------------------------------------------------------------------------- 234 */ 235#if GFX_I2C_DYNAMIC 236int 237gpio_i2c_write(unsigned char busnum, unsigned char address, unsigned char reg, 238 unsigned char bytes, unsigned char *value) 239#else 240int 241gfx_i2c_write(unsigned char busnum, unsigned char address, unsigned char reg, 242 unsigned char bytes, unsigned char *value) 243#endif 244{ 245 /* ### ADD ### CODE TO WRITE BYTE TO I2B BUS */ 246 247 int restart_count = 0; 248 249 while (restart_count++ < 5) { 250 /* set the access pointer register. */ 251 /* The address is shifted left by one to make room for Read/Write bit */ 252 SendI2CStart(); 253 SendI2CData((char)((address << 1) | I2CWRITE)); 254 if (!ReceiveI2CAck()) { 255 SendI2CStop(); 256 gfx_delay_milliseconds(10); 257 continue; 258 } 259 SendI2CData((unsigned char)reg); 260 if (!ReceiveI2CAck()) { 261 SendI2CStop(); 262 gfx_delay_milliseconds(10); 263 continue; 264 } 265 266 /* write the first byte */ 267 SendI2CData(*value); 268 if (!ReceiveI2CAck()) { 269 SendI2CStop(); 270 gfx_delay_milliseconds(10); 271 continue; 272 } 273 274 /* write the second byte. */ 275 if (bytes == 2) { 276 SendI2CData(*(value + 1)); 277 if (!ReceiveI2CAck()) { 278 SendI2CStop(); 279 gfx_delay_milliseconds(10); 280 continue; 281 } 282 } 283 284 /* done. */ 285 SendI2CStop(); 286 287 return 0; 288 } 289 290 return (0); 291 292} 293 294/*--------------------------------------------------------------------------- 295 * gfx_i2c_read 296 * 297 * This routine reads data from the specified I2C address. 298 *--------------------------------------------------------------------------- 299 */ 300#if GFX_I2C_DYNAMIC 301int 302gpio_i2c_read(unsigned char busnum, unsigned char address, unsigned char reg, 303 unsigned char bytes, unsigned char *p_value) 304#else 305int 306gfx_i2c_read(unsigned char busnum, unsigned char address, unsigned char reg, 307 unsigned char bytes, unsigned char *p_value) 308#endif 309{ 310 /* ### ADD ### CODE TO WRITE BYTE TO I2B BUS */ 311 /* For now return clock and data pins */ 312 313 int restart_count = 0; 314 315 if (!p_value) 316 return (1); 317 318 while (restart_count++ < 5) { 319 /* set the access pointer register. */ 320 /* The address is shifted left by one to make room for Read/Write bit */ 321 SendI2CStart(); 322 SendI2CData((char)((address << 1) | I2CWRITE)); 323 if (!ReceiveI2CAck()) { 324 SendI2CStop(); 325 gfx_delay_milliseconds(10); 326 continue; 327 } 328 SendI2CData((unsigned char)(reg & 0xFF)); 329 SendI2CNack(); 330 331 /* read the first data byte. */ 332 SendI2CStart(); 333 SendI2CData((char)((address << 1) | I2CREAD)); 334 if (!ReceiveI2CAck()) { 335 SendI2CStop(); 336 gfx_delay_milliseconds(10); 337 continue; 338 } 339 *p_value = ReceiveI2CData(); 340 341 /* read the second byte. */ 342 if (bytes == 2) { 343 SendI2CAck(); 344 *(p_value + 1) = ReceiveI2CData(); 345 } 346 347 /* done. */ 348 SendI2CNack(); 349 SendI2CStop(); 350 351 return 0; 352 } 353 354 return (1); 355} 356 357/* Added i2c/gpio code to test fs451 chip. */ 358 359/* 360//---------------------------------------------------------------------- 361// 362// void SendI2CStart(void) 363// 364// Sends an I2C start signal on the bus. 365// 366//---------------------------------------------------------------------- 367*/ 368void 369SendI2CStart(void) 370{ 371 I2CAL_output_data(1); 372 I2CAL_output_clock(1); 373 I2CAL_output_data(0); 374 I2CAL_output_clock(0); 375} 376 377/* 378//---------------------------------------------------------------------- 379// 380// void SendI2CStop(void) 381// 382// Sends an I2C stop signal on the bus. 383// 384//---------------------------------------------------------------------- 385*/ 386void 387SendI2CStop(void) 388{ 389 I2CAL_output_data(0); 390 I2CAL_output_clock(1); 391 I2CAL_output_data(1); 392} 393 394/* 395//---------------------------------------------------------------------- 396// 397// void SendI2CAck(void) 398// 399// Sends the Ack signal on the I2C bus. 400// 401//---------------------------------------------------------------------- 402*/ 403void 404SendI2CAck(void) 405{ 406 I2CAL_output_data(0); 407 I2CAL_output_clock(1); 408 I2CAL_output_clock(0); 409} 410 411/* 412//---------------------------------------------------------------------- 413// 414// void SendI2CNack(void) 415// 416// Sends the Nt-Ack signal on the I2C bus. 417// 418//---------------------------------------------------------------------- 419*/ 420void 421SendI2CNack(void) 422{ 423 I2CAL_output_data(1); 424 I2CAL_output_clock(1); 425 I2CAL_output_clock(0); 426} 427 428/* 429//---------------------------------------------------------------------- 430// 431// UInt8 SendI2CData( UInt8 inData ) 432// 433// Sends a byte of data on the I2C bus and returns the TRUE if the slave ACK'd 434// the data. 435// 436// Input: inData - the byte of data to send 437// Output: (return) - TRUE (1) if ACK was received, FALSE (0) if not 438// 439//---------------------------------------------------------------------- 440*/ 441void 442SendI2CData(unsigned char inData) 443{ 444 unsigned char bit; 445 446 /* Send all 8 bits of data byte, MSB to LSB */ 447 for (bit = 0x80; bit != 0; bit >>= 1) { 448 if (inData & bit) 449 I2CAL_output_data(1); 450 else 451 I2CAL_output_data(0); 452 453 I2CAL_output_clock(1); 454 I2CAL_output_clock(0); 455 } 456} 457 458/* 459//---------------------------------------------------------------------- 460// 461// UInt8 ReceiveI2CAck( ) 462// 463// Receives the Ack (or Nack) from the slave. 464// 465// Output: (return) - TRUE (1) if ACK was received, FALSE (0) if not 466// 467//---------------------------------------------------------------------- 468*/ 469unsigned char 470ReceiveI2CAck(void) 471{ 472 unsigned char bit; 473 474 /* Test for Ack/Nack */ 475 I2CAL_set_data_for_input(); 476 I2CAL_output_data(1); 477 I2CAL_output_clock(1); 478 bit = I2CAL_input_data(); 479 I2CAL_output_clock(0); 480 I2CAL_set_data_for_output(); 481 return !bit; 482} 483 484/* 485//---------------------------------------------------------------------- 486// 487// unsigned char ReceiveI2CData(void) 488// 489// Receives a byte of data from the I2C bus. 490// 491// Output: (return) - The data byte recehved from the bus 492// 493//---------------------------------------------------------------------- 494*/ 495unsigned char 496ReceiveI2CData(void) 497{ 498 unsigned char data = 0; 499 unsigned char x; 500 501 /* make sure the data line is released */ 502 I2CAL_set_data_for_input(); 503 I2CAL_output_data(1); 504 505 /* shift in the data */ 506 for (x = 0; x < 8; x++) { 507 /* shift the data left */ 508 I2CAL_output_clock(1); 509 data <<= 1; 510 data |= I2CAL_input_data(); 511 I2CAL_output_clock(0); 512 } 513 514 I2CAL_set_data_for_output(); 515 I2CAL_output_data(1); 516 return data; 517} 518 519/* 520//---------------------------------------------------------------------- 521// 522// void I2C_init(void) 523// 524// This routine initializes the I2C interface. Clients of the I2C.c 525// will call this routine before calling any other routine in the I2C.c 526// 527//---------------------------------------------------------------------- 528*/ 529 530#if GFX_I2C_DYNAMIC 531int 532gpio_i2c_init(void) 533#else 534int 535gfx_i2c_init(void) 536#endif 537{ 538 int errc; 539 540 /* init I2CAL */ 541 errc = I2CAL_init(); 542 if (errc) 543 return errc; 544 545 /* set the clock and data lines to the proper states */ 546 I2CAL_output_clock(1); 547 I2CAL_output_data(1); 548 I2CAL_set_data_for_output(); 549 550 SendI2CStart(); 551 SendI2CStop(); 552 SendI2CStop(); 553 554 g_initialized = 1; 555 556 return 0; 557} 558 559/* 560//---------------------------------------------------------------------- 561// 562// void I2C_cleanup(void) 563// 564// This routine disables the I2C interface. Clients of the I2C.c will not 565// call any other I2C routine after calling this routine. 566// 567//---------------------------------------------------------------------- 568*/ 569 570#if GFX_I2C_DYNAMIC 571void 572gpio_i2c_cleanup(void) 573#else 574void 575gfx_i2c_cleanup(void) 576#endif 577{ 578 if (g_initialized) { 579 580 /* set the clock and data lines to a harmless state */ 581 I2CAL_output_clock(1); 582 I2CAL_output_data(1); 583 584 g_initialized = 0; 585 } 586 587 I2CAL_cleanup(); 588} 589 590int 591I2CAL_init(void) 592{ 593 unsigned long l_reg; 594 unsigned short reg; 595 596 /* initialize the i2c port. */ 597 l_reg = gfx_pci_config_read(CS5530_GPIO); 598 599 if (l_reg != 0x01001078) 600 return 1; 601 602 l_reg = gfx_pci_config_read(CS5530_GPIO); 603 reg = (unsigned short)l_reg; 604 605 /* both outputs, both high. */ 606 reg |= (SDADIR | SCLDIR | SDA | SCL); 607 l_reg = reg; 608 gfx_pci_config_write(CS5530_GPIO, l_reg); 609 610 g_initialized = 1; 611 612 return 0; 613} 614 615void 616I2CAL_cleanup(void) 617{ 618 if (g_initialized) { 619 620 g_initialized = 0; 621 } 622} 623 624/* 625//-------------------------------------------------------------------------------- 626// 627// set the I2C clock line state 628// 629//-------------------------------------------------------------------------------- 630*/ 631void 632I2CAL_output_clock(int inState) 633{ 634 unsigned short reg; 635 unsigned long value; 636 637 value = gfx_pci_config_read(CS5530_GPIO); 638 reg = (unsigned short)value; 639 640 if (inState) { /* write a 1. */ 641 reg |= SCL; 642 } else { /* write a 0. */ 643 reg &= ~SCL; 644 } 645 646 value = reg; 647 gfx_pci_config_write(CS5530_GPIO, value); 648 649 /* hold it for a minimum of 4.7us */ 650 gfx_delay_microseconds(5); 651} 652 653/* 654//-------------------------------------------------------------------------------- 655// 656// set the I2C data line state 657// 658//-------------------------------------------------------------------------------- 659*/ 660void 661I2CAL_output_data(int inState) 662{ 663 unsigned short reg; 664 unsigned long value; 665 666 value = gfx_pci_config_read(CS5530_GPIO); 667 reg = (unsigned short)value; 668 669 if (inState) { /* write a 1. */ 670 reg |= SDA; 671 } else { 672 /* write a 0. */ 673 reg &= ~SDA; 674 } 675 value = reg; 676 gfx_pci_config_write(CS5530_GPIO, value); 677 678 /* 250 ns setup time */ 679 gfx_delay_microseconds(1); 680} 681 682/* 683//-------------------------------------------------------------------------------- 684// 685// read the state of the data line 686// 687//-------------------------------------------------------------------------------- 688*/ 689unsigned char 690I2CAL_input_data(void) 691{ 692 unsigned short reg; 693 unsigned long value; 694 695 value = gfx_pci_config_read(CS5530_GPIO); 696 reg = (unsigned short)value; 697 698 if (reg & SDA) 699 return 1; 700 else 701 return 0; 702} 703 704/* 705//-------------------------------------------------------------------------------- 706// 707// set the I2C data for input mode 708// 709//-------------------------------------------------------------------------------- 710*/ 711void 712I2CAL_set_data_for_input(void) 713{ 714 unsigned short reg; 715 unsigned long value; 716 717 value = gfx_pci_config_read(CS5530_GPIO); 718 reg = (unsigned short)value; 719 720 reg &= ~SDADIR; 721 722 value = reg; 723 724 gfx_pci_config_write(CS5530_GPIO, value); 725} 726 727/* 728//-------------------------------------------------------------------------------- 729// 730// set the I2C data for output mode 731// 732//-------------------------------------------------------------------------------- 733*/ 734void 735I2CAL_set_data_for_output(void) 736{ 737 unsigned short reg; 738 unsigned long value; 739 740 value = gfx_pci_config_read(CS5530_GPIO); 741 reg = (unsigned short)value; 742 reg |= SDADIR; 743 value = reg; 744 745 gfx_pci_config_write(CS5530_GPIO, value); 746 747} 748 749/* END OF FILE */ 750