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