summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/mvme5500/GT64260/GT64260TWSI.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/mvme5500/GT64260/GT64260TWSI.c')
-rw-r--r--bsps/powerpc/mvme5500/GT64260/GT64260TWSI.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/bsps/powerpc/mvme5500/GT64260/GT64260TWSI.c b/bsps/powerpc/mvme5500/GT64260/GT64260TWSI.c
new file mode 100644
index 0000000000..6b5b46e511
--- /dev/null
+++ b/bsps/powerpc/mvme5500/GT64260/GT64260TWSI.c
@@ -0,0 +1,214 @@
+/*
+ * Two-Wire Serial Interface (TWSI) support for the GT64260
+ */
+
+/*
+ * Copyright (c) 2004, Brookhaven National Laboratory and
+ * Shuchen Kate Feng <feng1@bnl.gov>
+ * All rights reserved.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution.
+ *
+ * See section 24:TWSI interface of "the GT-64260B System Controller
+ * for powerPc Processors Data Sheet".
+ *
+ * For full TWSI protocol description look in Philips Semiconductor
+ * TWSI spec.
+ *
+ * We need it to read out I2C devices used for the MVME5500
+ * (eg. the memory SPD and VPD).
+ */
+
+#include <libcpu/spr.h> /*registers.h included here for rtems_bsp_delay()*/
+#include <libcpu/io.h>
+#include <rtems/bspIo.h>
+
+#include "bsp/gtreg.h"
+#include "bsp/GT64260TWSI.h"
+
+#define MAX_LOOP 100
+
+#define TWSI_DEBUG 0
+
+static int TWSI_initFlg = 0; /* TWSI Initialization Flag */
+
+void GT64260TWSIinit(void)
+{
+ if ( !TWSI_initFlg ) {
+#if TWSI_DEBUG
+ printk("GT64260TWSIinit(");
+#endif
+ outl( 0, TWSI_SFT_RST); /* soft reset */
+ rtems_bsp_delay(1000);
+
+ /* See 24.2.5 : Assume bus speed is 133MHZ
+ * Try to be close to the default frequency : 62.5KHZ
+ * value 0x2c: 69.27 KHz TWSI bus clock
+ */
+ outl(0x2c, TWSI_BAUDE_RATE);
+ rtems_bsp_delay(1000);
+
+ /* Set Acknowledge and enable TWSI in the Control register */
+ outl(0x44, TWSI_CTRL);
+ rtems_bsp_delay(4000);
+ TWSI_initFlg = 1;
+#if TWSI_DEBUG
+ printk(")\n");
+#endif
+ }
+}
+
+/* return the interrupt flag */
+static int GT64260TWSIintFlag(void)
+{
+ unsigned int loop;
+
+ for (loop = 0; loop < MAX_LOOP; loop++ ) {
+ /* Return 1 if the interrupt flag is set */
+ if (inl(TWSI_CTRL) & TWSI_INTFLG)
+ return(1);
+ rtems_bsp_delay(1000);
+ }
+ return(0);
+}
+
+int GT64260TWSIstop(void)
+{
+
+#if TWSI_DEBUG
+ printk("GT64260TWSIstop(");
+#endif
+
+ outl((inl(TWSI_CTRL) | TWSI_STOP), TWSI_CTRL);
+ rtems_bsp_delay(1000);
+
+ /* Check if interrupt flag bit is set*/
+ if (GT64260TWSIintFlag()) {
+ outl((inl( TWSI_CTRL) & ~TWSI_INTFLG), TWSI_CTRL);
+ rtems_bsp_delay(1000);
+#if TWSI_DEBUG
+ printk(")\n");
+#endif
+ return(0);
+ }
+#if TWSI_DEBUG
+ printk("NoIntFlag\n");
+#endif
+ return(-1);
+}
+
+int GT64260TWSIstart(void)
+{
+ unsigned int loop;
+ unsigned int status;
+
+#if TWSI_DEBUG
+ printk("GT64260TWSIstart(");
+#endif
+ /* Initialize the TWSI interface */
+ GT64260TWSIinit();
+
+ /* set the start bit */
+ outl((TWSI_START | TWSI_TWSIEN), TWSI_CTRL);
+ rtems_bsp_delay(1000);
+
+ if (GT64260TWSIintFlag()) {
+ /* Check for completion of START sequence */
+ for (loop = 0; loop<MAX_LOOP; loop++ ) {
+ /* if (start condition transmitted) ||
+ * (repeated start condition transmitted )
+ */
+ if (((status= inl( TWSI_STATUS)) == 8) || (status == 0x10)) {
+#if TWSI_DEBUG
+ printk(")");
+#endif
+ return(0);
+ }
+ rtems_bsp_delay(1000);
+ }
+ }
+ /* if loop ends or intFlag ==0 */
+ GT64260TWSIstop();
+ return(-1);
+}
+
+int GT64260TWSIread(unsigned char * pData, int lastByte)
+{
+ unsigned int loop;
+
+#if TWSI_DEBUG
+ printk("GT64260TWSIread(");
+#endif
+ /* Clear INTFLG and set ACK and ENABLE bits */
+ outl((TWSI_ACK | TWSI_TWSIEN), TWSI_CTRL);
+ rtems_bsp_delay(1000);
+
+ if (GT64260TWSIintFlag()) {
+ for (loop = 0; loop< MAX_LOOP; loop++) {
+ /* if Master received read data, acknowledge transmitted */
+ if ( (inl( TWSI_STATUS) == 0x50)) {
+ *pData = (unsigned char) inl( TWSI_DATA);
+ rtems_bsp_delay(1500);
+
+ /* Clear INTFLAG and set Enable bit only */
+ if (lastByte)
+ outl(TWSI_TWSIEN, TWSI_CTRL);
+ rtems_bsp_delay(1500);
+#if TWSI_DEBUG
+ printk(")\n");
+#endif
+ return(0);
+ }
+ rtems_bsp_delay(1000);
+ } /* end for */
+ }
+ /* if loop ends or intFlag ==0 */
+ GT64260TWSIstop();
+ return(-1);
+}
+
+/* do a TWSI write cycle on the TWSI bus*/
+int GT64260TWSIwrite(unsigned char Data)
+{
+ unsigned int loop;
+ unsigned int status;
+
+#if TWSI_DEBUG
+ printk("GT64260TWSIwrite(");
+#endif
+ /* Write data into the TWSI data register */
+ outl(((unsigned int) Data), TWSI_DATA);
+ rtems_bsp_delay(1000);
+
+ /* Clear INTFLG in the control register to drive data onto TWSI bus */
+ outl(0, TWSI_CTRL);
+ rtems_bsp_delay(1000);
+
+ if (GT64260TWSIintFlag() ) {
+ for (loop = 0; loop< MAX_LOOP; loop++) {
+ rtems_bsp_delay(1000);
+ /* if address + write bit transmitted, acknowledge not received */
+ if ( (status = inl( TWSI_STATUS)) == 0x20) {
+ /* No device responding, generate STOP and return -1 */
+ printk("no device responding\n");
+ GT64260TWSIstop();
+ return(-1);
+ }
+ /* if (address + write bit transmitted, acknowledge received)
+ * (Master transmmitted data byte, acknowledge received)
+ * (address + read bit transmitted, acknowledge received)
+ */
+ if ((status == 0x18)||(status == 0x28)||(status == 0x40)) {
+#if TWSI_DEBUG
+ printk(")\n");
+#endif
+ return(0);
+ }
+ rtems_bsp_delay(1000);
+ } /* end for */
+ }
+ printk("No correct status, timeout\n");
+ GT64260TWSIstop();
+ return(-1);
+}