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