171d7fec4Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/i2c_gpio.c,v 1.1 2002/12/10 15:12:26 alanh Exp $ */ 271d7fec4Smrg/* 371d7fec4Smrg * $Workfile: i2c_gpio.c $ 471d7fec4Smrg * 571d7fec4Smrg * This file contains routines to write to and read from the I2C bus using 671d7fec4Smrg * the GPIO pins of the CS5530. 771d7fec4Smrg * 871d7fec4Smrg * NSC_LIC_ALTERNATIVE_PREAMBLE 971d7fec4Smrg * 1071d7fec4Smrg * Revision 1.0 1171d7fec4Smrg * 1271d7fec4Smrg * National Semiconductor Alternative GPL-BSD License 1371d7fec4Smrg * 1471d7fec4Smrg * National Semiconductor Corporation licenses this software 1571d7fec4Smrg * ("Software"): 1671d7fec4Smrg * 1771d7fec4Smrg * Durango 1871d7fec4Smrg * 1971d7fec4Smrg * under one of the two following licenses, depending on how the 2071d7fec4Smrg * Software is received by the Licensee. 2171d7fec4Smrg * 2271d7fec4Smrg * If this Software is received as part of the Linux Framebuffer or 2371d7fec4Smrg * other GPL licensed software, then the GPL license designated 2471d7fec4Smrg * NSC_LIC_GPL applies to this Software; in all other circumstances 2571d7fec4Smrg * then the BSD-style license designated NSC_LIC_BSD shall apply. 2671d7fec4Smrg * 2771d7fec4Smrg * END_NSC_LIC_ALTERNATIVE_PREAMBLE */ 2871d7fec4Smrg 2971d7fec4Smrg/* NSC_LIC_BSD 3071d7fec4Smrg * 3171d7fec4Smrg * National Semiconductor Corporation Open Source License for Durango 3271d7fec4Smrg * 3371d7fec4Smrg * (BSD License with Export Notice) 3471d7fec4Smrg * 3571d7fec4Smrg * Copyright (c) 1999-2001 3671d7fec4Smrg * National Semiconductor Corporation. 3771d7fec4Smrg * All rights reserved. 3871d7fec4Smrg * 3971d7fec4Smrg * Redistribution and use in source and binary forms, with or without 4071d7fec4Smrg * modification, are permitted provided that the following conditions 4171d7fec4Smrg * are met: 4271d7fec4Smrg * 4371d7fec4Smrg * * Redistributions of source code must retain the above copyright 4471d7fec4Smrg * notice, this list of conditions and the following disclaimer. 4571d7fec4Smrg * 4671d7fec4Smrg * * Redistributions in binary form must reproduce the above 4771d7fec4Smrg * copyright notice, this list of conditions and the following 4871d7fec4Smrg * disclaimer in the documentation and/or other materials provided 4971d7fec4Smrg * with the distribution. 5071d7fec4Smrg * 5171d7fec4Smrg * * Neither the name of the National Semiconductor Corporation nor 5271d7fec4Smrg * the names of its contributors may be used to endorse or promote 5371d7fec4Smrg * products derived from this software without specific prior 5471d7fec4Smrg * written permission. 5571d7fec4Smrg * 5671d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 5771d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 5871d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 5971d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 6071d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 6171d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6271d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 6371d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6471d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 6571d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 6671d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 6771d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 6871d7fec4Smrg * OF SUCH DAMAGE. 6971d7fec4Smrg * 7071d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 7171d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with 7271d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under 7371d7fec4Smrg * CURRENT (2001) U.S. export regulations this software 7471d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or 7571d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 7671d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 7771d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S. 7871d7fec4Smrg * has embargoed goods and services. 7971d7fec4Smrg * 8071d7fec4Smrg * END_NSC_LIC_BSD */ 8171d7fec4Smrg 8271d7fec4Smrg/* NSC_LIC_GPL 8371d7fec4Smrg * 8471d7fec4Smrg * National Semiconductor Corporation Gnu General Public License for Durango 8571d7fec4Smrg * 8671d7fec4Smrg * (GPL License with Export Notice) 8771d7fec4Smrg * 8871d7fec4Smrg * Copyright (c) 1999-2001 8971d7fec4Smrg * National Semiconductor Corporation. 9071d7fec4Smrg * All rights reserved. 9171d7fec4Smrg * 9271d7fec4Smrg * Redistribution and use in source and binary forms, with or without 9371d7fec4Smrg * modification, are permitted under the terms of the GNU General 9471d7fec4Smrg * Public License as published by the Free Software Foundation; either 9571d7fec4Smrg * version 2 of the License, or (at your option) any later version 9671d7fec4Smrg * 9771d7fec4Smrg * In addition to the terms of the GNU General Public License, neither 9871d7fec4Smrg * the name of the National Semiconductor Corporation nor the names of 9971d7fec4Smrg * its contributors may be used to endorse or promote products derived 10071d7fec4Smrg * from this software without specific prior written permission. 10171d7fec4Smrg * 10271d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 10371d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 10471d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 10571d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 10671d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 10771d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 10871d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 10971d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 11071d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 11171d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 11271d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 11371d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 11471d7fec4Smrg * OF SUCH DAMAGE. See the GNU General Public License for more details. 11571d7fec4Smrg * 11671d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 11771d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with 11871d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under 11971d7fec4Smrg * CURRENT (2001) U.S. export regulations this software 12071d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or 12171d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 12271d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 12371d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S. 12471d7fec4Smrg * has embargoed goods and services. 12571d7fec4Smrg * 12671d7fec4Smrg * You should have received a copy of the GNU General Public License 12771d7fec4Smrg * along with this file; if not, write to the Free Software Foundation, 12871d7fec4Smrg * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 12971d7fec4Smrg * 13071d7fec4Smrg * END_NSC_LIC_GPL */ 13171d7fec4Smrg 13271d7fec4Smrg/* STATIC VARIABLES TO STORE WHAT GPIO PINS TO USE */ 13371d7fec4Smrg 13471d7fec4Smrgint gpio_clock = 0; 13571d7fec4Smrgint gpio_data = 0; 13671d7fec4Smrg 13771d7fec4Smrgstatic int g_initialized = 0; 13871d7fec4Smrg 13971d7fec4Smrg#define I2CWRITE 0x00 /* Write address */ 14071d7fec4Smrg#define I2CREAD 0x01 /* Read address */ 14171d7fec4Smrg 14271d7fec4Smrg#define I2CACK 0x00 /* Ack value */ 14371d7fec4Smrg#define I2CNACK 0x01 /* Not - ack value */ 14471d7fec4Smrg 14571d7fec4Smrg#define CS5530_ID (0x80000000 | (0x00<<16) | (0x12<<11) | (0<<8) | 0x00) 14671d7fec4Smrg#define CS5530_GPIO (0x80000000 | (0x00<<16) | (0x12<<11) | (0<<8) | 0x90) 14771d7fec4Smrg#define SDA 0x0800 14871d7fec4Smrg#define SCL 0x0400 14971d7fec4Smrg#define SDADIR 0x0008 15071d7fec4Smrg#define SCLDIR 0x0004 15171d7fec4Smrg 15271d7fec4Smrgint I2C_init(void); 15371d7fec4Smrgvoid I2C_cleanup(void); 15471d7fec4Smrg 15571d7fec4Smrgint I2C_Read(unsigned char address, unsigned int reg, unsigned long *p_value, 15671d7fec4Smrg unsigned int bytes); 15771d7fec4Smrgint I2C_Write(unsigned char address, unsigned int reg, unsigned long value, 15871d7fec4Smrg unsigned int bytes); 15971d7fec4Smrgint I2CAL_init(void); 16071d7fec4Smrgvoid I2CAL_cleanup(void); 16171d7fec4Smrg 16271d7fec4Smrgvoid I2CAL_output_clock(int state); 16371d7fec4Smrgvoid I2CAL_output_data(int state); 16471d7fec4Smrgunsigned char I2CAL_input_data(void); 16571d7fec4Smrg 16671d7fec4Smrgvoid I2CAL_set_data_for_input(void); 16771d7fec4Smrgvoid I2CAL_set_data_for_output(void); 16871d7fec4Smrg 16971d7fec4Smrgvoid SendI2CStart(void); 17071d7fec4Smrgvoid SendI2CData(unsigned char inData); 17171d7fec4Smrg 17271d7fec4Smrgunsigned char ReceiveI2CAck(void); 17371d7fec4Smrgvoid SendI2CStop(void); 17471d7fec4Smrgvoid SendI2CNack(void); 17571d7fec4Smrgvoid SendI2CAck(void); 17671d7fec4Smrgunsigned char ReceiveI2CData(void); 17771d7fec4Smrg 17871d7fec4Smrgint gpio_i2c_reset(unsigned char busnum, short adr, char freq); 17971d7fec4Smrgint gpio_i2c_write(unsigned char busnum, unsigned char chipadr, 18071d7fec4Smrg unsigned char subadr, unsigned char bytes, 18171d7fec4Smrg unsigned char *data); 18271d7fec4Smrgint gpio_i2c_read(unsigned char busnum, unsigned char chipadr, 18371d7fec4Smrg unsigned char subadr, unsigned char bytes, 18471d7fec4Smrg unsigned char *data); 18571d7fec4Smrgint gpio_i2c_select_gpio(int clock, int data); 18671d7fec4Smrgint gpio_i2c_init(void); 18771d7fec4Smrgvoid gpio_i2c_cleanup(void); 18871d7fec4Smrg 18971d7fec4Smrg/* ### ADD ### ANY LOCAL ROUTINE DEFINITIONS SPECIFIC TO GPIO */ 19071d7fec4Smrg 19171d7fec4Smrg/*--------------------------------------------------------------------------- 19271d7fec4Smrg * gfx_i2c_reset 19371d7fec4Smrg * 19471d7fec4Smrg * This routine resets the I2C bus. 19571d7fec4Smrg *--------------------------------------------------------------------------- 19671d7fec4Smrg */ 19771d7fec4Smrg 19871d7fec4Smrg#if GFX_I2C_DYNAMIC 19971d7fec4Smrgint 20071d7fec4Smrggpio_i2c_reset(unsigned char busnum, short adr, char freq) 20171d7fec4Smrg#else 20271d7fec4Smrgint 20371d7fec4Smrggfx_i2c_reset(unsigned char busnum, short adr, char freq) 20471d7fec4Smrg#endif 20571d7fec4Smrg{ 20671d7fec4Smrg /* ### ADD ### Any code needed to reset the state of the GPIOs. */ 20771d7fec4Smrg return GFX_STATUS_OK; 20871d7fec4Smrg} 20971d7fec4Smrg 21071d7fec4Smrg/*--------------------------------------------------------------------------- 21171d7fec4Smrg * gfx_i2c_select_gpio 21271d7fec4Smrg * 21371d7fec4Smrg * This routine selects which GPIO pins to use. 21471d7fec4Smrg *--------------------------------------------------------------------------- 21571d7fec4Smrg */ 21671d7fec4Smrg#if GFX_I2C_DYNAMIC 21771d7fec4Smrgint 21871d7fec4Smrggpio_i2c_select_gpio(int clock, int data) 21971d7fec4Smrg#else 22071d7fec4Smrgint 22171d7fec4Smrggfx_i2c_select_gpio(int clock, int data) 22271d7fec4Smrg#endif 22371d7fec4Smrg{ 22471d7fec4Smrg gpio_clock = clock; 22571d7fec4Smrg gpio_data = data; 22671d7fec4Smrg return (0); 22771d7fec4Smrg} 22871d7fec4Smrg 22971d7fec4Smrg/*--------------------------------------------------------------------------- 23071d7fec4Smrg * gfx_i2c_write 23171d7fec4Smrg * 23271d7fec4Smrg * This routine writes data to the specified I2C address. 23371d7fec4Smrg *--------------------------------------------------------------------------- 23471d7fec4Smrg */ 23571d7fec4Smrg#if GFX_I2C_DYNAMIC 23671d7fec4Smrgint 23771d7fec4Smrggpio_i2c_write(unsigned char busnum, unsigned char address, unsigned char reg, 23871d7fec4Smrg unsigned char bytes, unsigned char *value) 23971d7fec4Smrg#else 24071d7fec4Smrgint 24171d7fec4Smrggfx_i2c_write(unsigned char busnum, unsigned char address, unsigned char reg, 24271d7fec4Smrg unsigned char bytes, unsigned char *value) 24371d7fec4Smrg#endif 24471d7fec4Smrg{ 24571d7fec4Smrg /* ### ADD ### CODE TO WRITE BYTE TO I2B BUS */ 24671d7fec4Smrg 24771d7fec4Smrg int restart_count = 0; 24871d7fec4Smrg 24971d7fec4Smrg while (restart_count++ < 5) { 25071d7fec4Smrg /* set the access pointer register. */ 25171d7fec4Smrg /* The address is shifted left by one to make room for Read/Write bit */ 25271d7fec4Smrg SendI2CStart(); 25371d7fec4Smrg SendI2CData((char)((address << 1) | I2CWRITE)); 25471d7fec4Smrg if (!ReceiveI2CAck()) { 25571d7fec4Smrg SendI2CStop(); 25671d7fec4Smrg gfx_delay_milliseconds(10); 25771d7fec4Smrg continue; 25871d7fec4Smrg } 25971d7fec4Smrg SendI2CData((unsigned char)reg); 26071d7fec4Smrg if (!ReceiveI2CAck()) { 26171d7fec4Smrg SendI2CStop(); 26271d7fec4Smrg gfx_delay_milliseconds(10); 26371d7fec4Smrg continue; 26471d7fec4Smrg } 26571d7fec4Smrg 26671d7fec4Smrg /* write the first byte */ 26771d7fec4Smrg SendI2CData(*value); 26871d7fec4Smrg if (!ReceiveI2CAck()) { 26971d7fec4Smrg SendI2CStop(); 27071d7fec4Smrg gfx_delay_milliseconds(10); 27171d7fec4Smrg continue; 27271d7fec4Smrg } 27371d7fec4Smrg 27471d7fec4Smrg /* write the second byte. */ 27571d7fec4Smrg if (bytes == 2) { 27671d7fec4Smrg SendI2CData(*(value + 1)); 27771d7fec4Smrg if (!ReceiveI2CAck()) { 27871d7fec4Smrg SendI2CStop(); 27971d7fec4Smrg gfx_delay_milliseconds(10); 28071d7fec4Smrg continue; 28171d7fec4Smrg } 28271d7fec4Smrg } 28371d7fec4Smrg 28471d7fec4Smrg /* done. */ 28571d7fec4Smrg SendI2CStop(); 28671d7fec4Smrg 28771d7fec4Smrg return 0; 28871d7fec4Smrg } 28971d7fec4Smrg 29071d7fec4Smrg return (0); 29171d7fec4Smrg 29271d7fec4Smrg} 29371d7fec4Smrg 29471d7fec4Smrg/*--------------------------------------------------------------------------- 29571d7fec4Smrg * gfx_i2c_read 29671d7fec4Smrg * 29771d7fec4Smrg * This routine reads data from the specified I2C address. 29871d7fec4Smrg *--------------------------------------------------------------------------- 29971d7fec4Smrg */ 30071d7fec4Smrg#if GFX_I2C_DYNAMIC 30171d7fec4Smrgint 30271d7fec4Smrggpio_i2c_read(unsigned char busnum, unsigned char address, unsigned char reg, 30371d7fec4Smrg unsigned char bytes, unsigned char *p_value) 30471d7fec4Smrg#else 30571d7fec4Smrgint 30671d7fec4Smrggfx_i2c_read(unsigned char busnum, unsigned char address, unsigned char reg, 30771d7fec4Smrg unsigned char bytes, unsigned char *p_value) 30871d7fec4Smrg#endif 30971d7fec4Smrg{ 31071d7fec4Smrg /* ### ADD ### CODE TO WRITE BYTE TO I2B BUS */ 31171d7fec4Smrg /* For now return clock and data pins */ 31271d7fec4Smrg 31371d7fec4Smrg int restart_count = 0; 31471d7fec4Smrg 31571d7fec4Smrg if (!p_value) 31671d7fec4Smrg return (1); 31771d7fec4Smrg 31871d7fec4Smrg while (restart_count++ < 5) { 31971d7fec4Smrg /* set the access pointer register. */ 32071d7fec4Smrg /* The address is shifted left by one to make room for Read/Write bit */ 32171d7fec4Smrg SendI2CStart(); 32271d7fec4Smrg SendI2CData((char)((address << 1) | I2CWRITE)); 32371d7fec4Smrg if (!ReceiveI2CAck()) { 32471d7fec4Smrg SendI2CStop(); 32571d7fec4Smrg gfx_delay_milliseconds(10); 32671d7fec4Smrg continue; 32771d7fec4Smrg } 32871d7fec4Smrg SendI2CData((unsigned char)(reg & 0xFF)); 32971d7fec4Smrg SendI2CNack(); 33071d7fec4Smrg 33171d7fec4Smrg /* read the first data byte. */ 33271d7fec4Smrg SendI2CStart(); 33371d7fec4Smrg SendI2CData((char)((address << 1) | I2CREAD)); 33471d7fec4Smrg if (!ReceiveI2CAck()) { 33571d7fec4Smrg SendI2CStop(); 33671d7fec4Smrg gfx_delay_milliseconds(10); 33771d7fec4Smrg continue; 33871d7fec4Smrg } 33971d7fec4Smrg *p_value = ReceiveI2CData(); 34071d7fec4Smrg 34171d7fec4Smrg /* read the second byte. */ 34271d7fec4Smrg if (bytes == 2) { 34371d7fec4Smrg SendI2CAck(); 34471d7fec4Smrg *(p_value + 1) = ReceiveI2CData(); 34571d7fec4Smrg } 34671d7fec4Smrg 34771d7fec4Smrg /* done. */ 34871d7fec4Smrg SendI2CNack(); 34971d7fec4Smrg SendI2CStop(); 35071d7fec4Smrg 35171d7fec4Smrg return 0; 35271d7fec4Smrg } 35371d7fec4Smrg 35471d7fec4Smrg return (1); 35571d7fec4Smrg} 35671d7fec4Smrg 35771d7fec4Smrg/* Added i2c/gpio code to test fs451 chip. */ 35871d7fec4Smrg 35971d7fec4Smrg/* 36071d7fec4Smrg//---------------------------------------------------------------------- 36171d7fec4Smrg// 36271d7fec4Smrg// void SendI2CStart(void) 36371d7fec4Smrg// 36471d7fec4Smrg// Sends an I2C start signal on the bus. 36571d7fec4Smrg// 36671d7fec4Smrg//---------------------------------------------------------------------- 36771d7fec4Smrg*/ 36871d7fec4Smrgvoid 36971d7fec4SmrgSendI2CStart(void) 37071d7fec4Smrg{ 37171d7fec4Smrg I2CAL_output_data(1); 37271d7fec4Smrg I2CAL_output_clock(1); 37371d7fec4Smrg I2CAL_output_data(0); 37471d7fec4Smrg I2CAL_output_clock(0); 37571d7fec4Smrg} 37671d7fec4Smrg 37771d7fec4Smrg/* 37871d7fec4Smrg//---------------------------------------------------------------------- 37971d7fec4Smrg// 38071d7fec4Smrg// void SendI2CStop(void) 38171d7fec4Smrg// 38271d7fec4Smrg// Sends an I2C stop signal on the bus. 38371d7fec4Smrg// 38471d7fec4Smrg//---------------------------------------------------------------------- 38571d7fec4Smrg*/ 38671d7fec4Smrgvoid 38771d7fec4SmrgSendI2CStop(void) 38871d7fec4Smrg{ 38971d7fec4Smrg I2CAL_output_data(0); 39071d7fec4Smrg I2CAL_output_clock(1); 39171d7fec4Smrg I2CAL_output_data(1); 39271d7fec4Smrg} 39371d7fec4Smrg 39471d7fec4Smrg/* 39571d7fec4Smrg//---------------------------------------------------------------------- 39671d7fec4Smrg// 39771d7fec4Smrg// void SendI2CAck(void) 39871d7fec4Smrg// 39971d7fec4Smrg// Sends the Ack signal on the I2C bus. 40071d7fec4Smrg// 40171d7fec4Smrg//---------------------------------------------------------------------- 40271d7fec4Smrg*/ 40371d7fec4Smrgvoid 40471d7fec4SmrgSendI2CAck(void) 40571d7fec4Smrg{ 40671d7fec4Smrg I2CAL_output_data(0); 40771d7fec4Smrg I2CAL_output_clock(1); 40871d7fec4Smrg I2CAL_output_clock(0); 40971d7fec4Smrg} 41071d7fec4Smrg 41171d7fec4Smrg/* 41271d7fec4Smrg//---------------------------------------------------------------------- 41371d7fec4Smrg// 41471d7fec4Smrg// void SendI2CNack(void) 41571d7fec4Smrg// 41671d7fec4Smrg// Sends the Nt-Ack signal on the I2C bus. 41771d7fec4Smrg// 41871d7fec4Smrg//---------------------------------------------------------------------- 41971d7fec4Smrg*/ 42071d7fec4Smrgvoid 42171d7fec4SmrgSendI2CNack(void) 42271d7fec4Smrg{ 42371d7fec4Smrg I2CAL_output_data(1); 42471d7fec4Smrg I2CAL_output_clock(1); 42571d7fec4Smrg I2CAL_output_clock(0); 42671d7fec4Smrg} 42771d7fec4Smrg 42871d7fec4Smrg/* 42971d7fec4Smrg//---------------------------------------------------------------------- 43071d7fec4Smrg// 43171d7fec4Smrg// UInt8 SendI2CData( UInt8 inData ) 43271d7fec4Smrg// 43371d7fec4Smrg// Sends a byte of data on the I2C bus and returns the TRUE if the slave ACK'd 43471d7fec4Smrg// the data. 43571d7fec4Smrg// 43671d7fec4Smrg// Input: inData - the byte of data to send 43771d7fec4Smrg// Output: (return) - TRUE (1) if ACK was received, FALSE (0) if not 43871d7fec4Smrg// 43971d7fec4Smrg//---------------------------------------------------------------------- 44071d7fec4Smrg*/ 44171d7fec4Smrgvoid 44271d7fec4SmrgSendI2CData(unsigned char inData) 44371d7fec4Smrg{ 44471d7fec4Smrg unsigned char bit; 44571d7fec4Smrg 44671d7fec4Smrg /* Send all 8 bits of data byte, MSB to LSB */ 44771d7fec4Smrg for (bit = 0x80; bit != 0; bit >>= 1) { 44871d7fec4Smrg if (inData & bit) 44971d7fec4Smrg I2CAL_output_data(1); 45071d7fec4Smrg else 45171d7fec4Smrg I2CAL_output_data(0); 45271d7fec4Smrg 45371d7fec4Smrg I2CAL_output_clock(1); 45471d7fec4Smrg I2CAL_output_clock(0); 45571d7fec4Smrg } 45671d7fec4Smrg} 45771d7fec4Smrg 45871d7fec4Smrg/* 45971d7fec4Smrg//---------------------------------------------------------------------- 46071d7fec4Smrg// 46171d7fec4Smrg// UInt8 ReceiveI2CAck( ) 46271d7fec4Smrg// 46371d7fec4Smrg// Receives the Ack (or Nack) from the slave. 46471d7fec4Smrg// 46571d7fec4Smrg// Output: (return) - TRUE (1) if ACK was received, FALSE (0) if not 46671d7fec4Smrg// 46771d7fec4Smrg//---------------------------------------------------------------------- 46871d7fec4Smrg*/ 46971d7fec4Smrgunsigned char 47071d7fec4SmrgReceiveI2CAck(void) 47171d7fec4Smrg{ 47271d7fec4Smrg unsigned char bit; 47371d7fec4Smrg 47471d7fec4Smrg /* Test for Ack/Nack */ 47571d7fec4Smrg I2CAL_set_data_for_input(); 47671d7fec4Smrg I2CAL_output_data(1); 47771d7fec4Smrg I2CAL_output_clock(1); 47871d7fec4Smrg bit = I2CAL_input_data(); 47971d7fec4Smrg I2CAL_output_clock(0); 48071d7fec4Smrg I2CAL_set_data_for_output(); 48171d7fec4Smrg return !bit; 48271d7fec4Smrg} 48371d7fec4Smrg 48471d7fec4Smrg/* 48571d7fec4Smrg//---------------------------------------------------------------------- 48671d7fec4Smrg// 48771d7fec4Smrg// unsigned char ReceiveI2CData(void) 48871d7fec4Smrg// 48971d7fec4Smrg// Receives a byte of data from the I2C bus. 49071d7fec4Smrg// 49171d7fec4Smrg// Output: (return) - The data byte recehved from the bus 49271d7fec4Smrg// 49371d7fec4Smrg//---------------------------------------------------------------------- 49471d7fec4Smrg*/ 49571d7fec4Smrgunsigned char 49671d7fec4SmrgReceiveI2CData(void) 49771d7fec4Smrg{ 49871d7fec4Smrg unsigned char data = 0; 49971d7fec4Smrg unsigned char x; 50071d7fec4Smrg 50171d7fec4Smrg /* make sure the data line is released */ 50271d7fec4Smrg I2CAL_set_data_for_input(); 50371d7fec4Smrg I2CAL_output_data(1); 50471d7fec4Smrg 50571d7fec4Smrg /* shift in the data */ 50671d7fec4Smrg for (x = 0; x < 8; x++) { 50771d7fec4Smrg /* shift the data left */ 50871d7fec4Smrg I2CAL_output_clock(1); 50971d7fec4Smrg data <<= 1; 51071d7fec4Smrg data |= I2CAL_input_data(); 51171d7fec4Smrg I2CAL_output_clock(0); 51271d7fec4Smrg } 51371d7fec4Smrg 51471d7fec4Smrg I2CAL_set_data_for_output(); 51571d7fec4Smrg I2CAL_output_data(1); 51671d7fec4Smrg return data; 51771d7fec4Smrg} 51871d7fec4Smrg 51971d7fec4Smrg/* 52071d7fec4Smrg//---------------------------------------------------------------------- 52171d7fec4Smrg// 52271d7fec4Smrg// void I2C_init(void) 52371d7fec4Smrg// 52471d7fec4Smrg// This routine initializes the I2C interface. Clients of the I2C.c 52571d7fec4Smrg// will call this routine before calling any other routine in the I2C.c 52671d7fec4Smrg// 52771d7fec4Smrg//---------------------------------------------------------------------- 52871d7fec4Smrg*/ 52971d7fec4Smrg 53071d7fec4Smrg#if GFX_I2C_DYNAMIC 53171d7fec4Smrgint 53271d7fec4Smrggpio_i2c_init(void) 53371d7fec4Smrg#else 53471d7fec4Smrgint 53571d7fec4Smrggfx_i2c_init(void) 53671d7fec4Smrg#endif 53771d7fec4Smrg{ 53871d7fec4Smrg int errc; 53971d7fec4Smrg 54071d7fec4Smrg /* init I2CAL */ 54171d7fec4Smrg errc = I2CAL_init(); 54271d7fec4Smrg if (errc) 54371d7fec4Smrg return errc; 54471d7fec4Smrg 54571d7fec4Smrg /* set the clock and data lines to the proper states */ 54671d7fec4Smrg I2CAL_output_clock(1); 54771d7fec4Smrg I2CAL_output_data(1); 54871d7fec4Smrg I2CAL_set_data_for_output(); 54971d7fec4Smrg 55071d7fec4Smrg SendI2CStart(); 55171d7fec4Smrg SendI2CStop(); 55271d7fec4Smrg SendI2CStop(); 55371d7fec4Smrg 55471d7fec4Smrg g_initialized = 1; 55571d7fec4Smrg 55671d7fec4Smrg return 0; 55771d7fec4Smrg} 55871d7fec4Smrg 55971d7fec4Smrg/* 56071d7fec4Smrg//---------------------------------------------------------------------- 56171d7fec4Smrg// 56271d7fec4Smrg// void I2C_cleanup(void) 56371d7fec4Smrg// 56471d7fec4Smrg// This routine disables the I2C interface. Clients of the I2C.c will not 56571d7fec4Smrg// call any other I2C routine after calling this routine. 56671d7fec4Smrg// 56771d7fec4Smrg//---------------------------------------------------------------------- 56871d7fec4Smrg*/ 56971d7fec4Smrg 57071d7fec4Smrg#if GFX_I2C_DYNAMIC 57171d7fec4Smrgvoid 57271d7fec4Smrggpio_i2c_cleanup(void) 57371d7fec4Smrg#else 57471d7fec4Smrgvoid 57571d7fec4Smrggfx_i2c_cleanup(void) 57671d7fec4Smrg#endif 57771d7fec4Smrg{ 57871d7fec4Smrg if (g_initialized) { 57971d7fec4Smrg 58071d7fec4Smrg /* set the clock and data lines to a harmless state */ 58171d7fec4Smrg I2CAL_output_clock(1); 58271d7fec4Smrg I2CAL_output_data(1); 58371d7fec4Smrg 58471d7fec4Smrg g_initialized = 0; 58571d7fec4Smrg } 58671d7fec4Smrg 58771d7fec4Smrg I2CAL_cleanup(); 58871d7fec4Smrg} 58971d7fec4Smrg 59071d7fec4Smrgint 59171d7fec4SmrgI2CAL_init(void) 59271d7fec4Smrg{ 59371d7fec4Smrg unsigned long l_reg; 59471d7fec4Smrg unsigned short reg; 59571d7fec4Smrg 59671d7fec4Smrg /* initialize the i2c port. */ 59771d7fec4Smrg l_reg = gfx_pci_config_read(CS5530_GPIO); 59871d7fec4Smrg 59971d7fec4Smrg if (l_reg != 0x01001078) 60071d7fec4Smrg return 1; 60171d7fec4Smrg 60271d7fec4Smrg l_reg = gfx_pci_config_read(CS5530_GPIO); 60371d7fec4Smrg reg = (unsigned short)l_reg; 60471d7fec4Smrg 60571d7fec4Smrg /* both outputs, both high. */ 60671d7fec4Smrg reg |= (SDADIR | SCLDIR | SDA | SCL); 60771d7fec4Smrg l_reg = reg; 60871d7fec4Smrg gfx_pci_config_write(CS5530_GPIO, l_reg); 60971d7fec4Smrg 61071d7fec4Smrg g_initialized = 1; 61171d7fec4Smrg 61271d7fec4Smrg return 0; 61371d7fec4Smrg} 61471d7fec4Smrg 61571d7fec4Smrgvoid 61671d7fec4SmrgI2CAL_cleanup(void) 61771d7fec4Smrg{ 61871d7fec4Smrg if (g_initialized) { 61971d7fec4Smrg 62071d7fec4Smrg g_initialized = 0; 62171d7fec4Smrg } 62271d7fec4Smrg} 62371d7fec4Smrg 62471d7fec4Smrg/* 62571d7fec4Smrg//-------------------------------------------------------------------------------- 62671d7fec4Smrg// 62771d7fec4Smrg// set the I2C clock line state 62871d7fec4Smrg// 62971d7fec4Smrg//-------------------------------------------------------------------------------- 63071d7fec4Smrg*/ 63171d7fec4Smrgvoid 63271d7fec4SmrgI2CAL_output_clock(int inState) 63371d7fec4Smrg{ 63471d7fec4Smrg unsigned short reg; 63571d7fec4Smrg unsigned long value; 63671d7fec4Smrg 63771d7fec4Smrg value = gfx_pci_config_read(CS5530_GPIO); 63871d7fec4Smrg reg = (unsigned short)value; 63971d7fec4Smrg 64071d7fec4Smrg if (inState) { /* write a 1. */ 64171d7fec4Smrg reg |= SCL; 64271d7fec4Smrg } else { /* write a 0. */ 64371d7fec4Smrg reg &= ~SCL; 64471d7fec4Smrg } 64571d7fec4Smrg 64671d7fec4Smrg value = reg; 64771d7fec4Smrg gfx_pci_config_write(CS5530_GPIO, value); 64871d7fec4Smrg 64971d7fec4Smrg /* hold it for a minimum of 4.7us */ 65071d7fec4Smrg gfx_delay_microseconds(5); 65171d7fec4Smrg} 65271d7fec4Smrg 65371d7fec4Smrg/* 65471d7fec4Smrg//-------------------------------------------------------------------------------- 65571d7fec4Smrg// 65671d7fec4Smrg// set the I2C data line state 65771d7fec4Smrg// 65871d7fec4Smrg//-------------------------------------------------------------------------------- 65971d7fec4Smrg*/ 66071d7fec4Smrgvoid 66171d7fec4SmrgI2CAL_output_data(int inState) 66271d7fec4Smrg{ 66371d7fec4Smrg unsigned short reg; 66471d7fec4Smrg unsigned long value; 66571d7fec4Smrg 66671d7fec4Smrg value = gfx_pci_config_read(CS5530_GPIO); 66771d7fec4Smrg reg = (unsigned short)value; 66871d7fec4Smrg 66971d7fec4Smrg if (inState) { /* write a 1. */ 67071d7fec4Smrg reg |= SDA; 67171d7fec4Smrg } else { 67271d7fec4Smrg /* write a 0. */ 67371d7fec4Smrg reg &= ~SDA; 67471d7fec4Smrg } 67571d7fec4Smrg value = reg; 67671d7fec4Smrg gfx_pci_config_write(CS5530_GPIO, value); 67771d7fec4Smrg 67871d7fec4Smrg /* 250 ns setup time */ 67971d7fec4Smrg gfx_delay_microseconds(1); 68071d7fec4Smrg} 68171d7fec4Smrg 68271d7fec4Smrg/* 68371d7fec4Smrg//-------------------------------------------------------------------------------- 68471d7fec4Smrg// 68571d7fec4Smrg// read the state of the data line 68671d7fec4Smrg// 68771d7fec4Smrg//-------------------------------------------------------------------------------- 68871d7fec4Smrg*/ 68971d7fec4Smrgunsigned char 69071d7fec4SmrgI2CAL_input_data(void) 69171d7fec4Smrg{ 69271d7fec4Smrg unsigned short reg; 69371d7fec4Smrg unsigned long value; 69471d7fec4Smrg 69571d7fec4Smrg value = gfx_pci_config_read(CS5530_GPIO); 69671d7fec4Smrg reg = (unsigned short)value; 69771d7fec4Smrg 69871d7fec4Smrg if (reg & SDA) 69971d7fec4Smrg return 1; 70071d7fec4Smrg else 70171d7fec4Smrg return 0; 70271d7fec4Smrg} 70371d7fec4Smrg 70471d7fec4Smrg/* 70571d7fec4Smrg//-------------------------------------------------------------------------------- 70671d7fec4Smrg// 70771d7fec4Smrg// set the I2C data for input mode 70871d7fec4Smrg// 70971d7fec4Smrg//-------------------------------------------------------------------------------- 71071d7fec4Smrg*/ 71171d7fec4Smrgvoid 71271d7fec4SmrgI2CAL_set_data_for_input(void) 71371d7fec4Smrg{ 71471d7fec4Smrg unsigned short reg; 71571d7fec4Smrg unsigned long value; 71671d7fec4Smrg 71771d7fec4Smrg value = gfx_pci_config_read(CS5530_GPIO); 71871d7fec4Smrg reg = (unsigned short)value; 71971d7fec4Smrg 72071d7fec4Smrg reg &= ~SDADIR; 72171d7fec4Smrg 72271d7fec4Smrg value = reg; 72371d7fec4Smrg 72471d7fec4Smrg gfx_pci_config_write(CS5530_GPIO, value); 72571d7fec4Smrg} 72671d7fec4Smrg 72771d7fec4Smrg/* 72871d7fec4Smrg//-------------------------------------------------------------------------------- 72971d7fec4Smrg// 73071d7fec4Smrg// set the I2C data for output mode 73171d7fec4Smrg// 73271d7fec4Smrg//-------------------------------------------------------------------------------- 73371d7fec4Smrg*/ 73471d7fec4Smrgvoid 73571d7fec4SmrgI2CAL_set_data_for_output(void) 73671d7fec4Smrg{ 73771d7fec4Smrg unsigned short reg; 73871d7fec4Smrg unsigned long value; 73971d7fec4Smrg 74071d7fec4Smrg value = gfx_pci_config_read(CS5530_GPIO); 74171d7fec4Smrg reg = (unsigned short)value; 74271d7fec4Smrg reg |= SDADIR; 74371d7fec4Smrg value = reg; 74471d7fec4Smrg 74571d7fec4Smrg gfx_pci_config_write(CS5530_GPIO, value); 74671d7fec4Smrg 74771d7fec4Smrg} 74871d7fec4Smrg 74971d7fec4Smrg/* END OF FILE */ 750