/* $Id: i2c.S,v 1.1 2001/12/11 08:19:18 pefo Exp $ */ /* * Copyright (c) 2001 Opsycon AB (www.opsycon.se) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Opsycon AB, Sweden. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * I2C Functions used in early startup code to get SPD info from * SDRAM modules. This code must be entirely PIC and RAM independent. */ #include "pmon/dev/gt64260reg.h" #include "target/ev64260.h" #include #include #define CTR 9 #define HIADJ(x) (x)@ha #define HI(x) (x)@h #define LO(x) (x)@l /* * Use this macro to prevent reordering by as/ld and processor */ #define IORDER eieio; sync /* Delay macro */ #define DELAY(count) \ li 0, count; \ mtctr 0; \ 1: \ bdnz 1b \ /************************************************************* *NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE* ************************************************************* * Throughout this code r25 is used to hold the GT-chip base * address. DON'T use r25 for any purpose whatsoever! */ /* * Macros to simplify setting up the Galileo controller */ #define GT_REGAD(offs) \ ori r5, r25, offs #define GT_REGWR(offs, value) \ ori r5, r25, offs; \ lis r6, HIADJ(value); \ addi r6, r6, LO(value); \ stwbrx r6, 0, (r5); \ eieio; sync #define GT_REGRD(offs) \ ori r5, r25, offs; \ lwbrx r6, 0, (r5); \ eieio; sync #define GT_REGSET(offs, value) \ ori r5, r25, offs; \ lwbrx r6, 0, (r5); \ oris r6, r6, HI(value); \ ori r6, r6, LO(value); \ stwbrx r6, 0, (r5); \ eieio; sync #define GT_REGCLR(offs, value) \ ori r5, r25, offs; \ lwbrx r6, 0, (r5); \ lis r5, HI(value); \ ori r5, r5, LO(value); \ andc r6, r6, r5; \ ori r5, r25, offs; \ stwbrx r6, 0, (r5); \ eieio; sync #define I2C_INT_ENABLE 0x80 #define I2C_ENABLE 0x40 #define I2C_ACK 0x04 #define I2C_INT_FLAG 0x08 #define I2C_STOP_BIT 0x10 #define I2C_START_BIT 0x20 #define I2C_AMOD_RD 0x01 #define BUS_ERROR 0x00 #define START_CONDITION_TRA 0x08 #define RSTART_CONDITION_TRA 0x10 #define ADDR_AND_WRITE_BIT_TRA_ACK_REC 0x18 #define ADDR_AND_READ_BIT_TRA_ACK_REC 0x40 #define SLAVE_REC_WRITE_DATA_ACK_TRA 0x28 #define MAS_REC_READ_DATA_ACK_NOT_TRA 0x58 boot_i2c_test: li r3, 0x600 boot_i2c_test_call: or r7, r25, r25 mflr r8 lis r25, HI(GT_BASE_ADDR) bl boot_i2c_init bl boot_i2c_read mtlr r8 or r25, r7, r7 blr /* * Wait for interrupt, return status byte */ wait_int: GT_REGRD(I2C_CONTROL) li r5, I2C_INT_FLAG and. r6, r6, r5 beq wait_int GT_REGRD(I2C_STATUS_BAUDE_RATE) blr /* * I2C Master init. */ .globl boot_i2c_init boot_i2c_init: GT_REGWR(I2C_SOFT_RESET, 0x0) GT_REGWR(I2C_STATUS_BAUDE_RATE, 0x24); GT_REGWR(I2C_CONTROL, I2C_ENABLE) blr /* * I2C Read byte from device. Use RANDOM READ protocol. */ .globl boot_i2c_read boot_i2c_read: mflr r4 /* Save return address */ GT_REGSET(I2C_CONTROL, I2C_START_BIT) bl wait_int cmpwi r6, START_CONDITION_TRA bne boot_i2c_read_bad /* Bad start, exit */ /**/ rlwinm r6, r3, 25, 28, 30 /* Get device part of addr */ ori r6, r6, 0xa0 /* Device type + write(addr) */ GT_REGAD(I2C_DATA) /* Send device address */ stwbrx r6, 0, (r5) GT_REGCLR(I2C_CONTROL, I2C_INT_FLAG) /* Send it */ bl wait_int cmpwi r6, ADDR_AND_WRITE_BIT_TRA_ACK_REC bne boot_i2c_read_bad /**/ andi. r6, r3, 0xff GT_REGAD(I2C_DATA) /* Send address */ stwbrx r6, 0, (r5) GT_REGCLR(I2C_CONTROL, I2C_INT_FLAG) /* Send it */ bl wait_int cmpwi r6, SLAVE_REC_WRITE_DATA_ACK_TRA bne boot_i2c_read_bad /**/ GT_REGSET(I2C_CONTROL, I2C_START_BIT) /* Restart! */ GT_REGCLR(I2C_CONTROL, I2C_INT_FLAG) /* Send it */ bl wait_int cmpwi r6, RSTART_CONDITION_TRA bne boot_i2c_read_bad /* Bad start, exit */ /**/ rlwinm r6, r3, 25, 28, 30 /* Get device part of addr */ ori r6, r6, 0xa1 /* Device type + read */ GT_REGAD(I2C_DATA) /* Send device address */ stwbrx r6, 0, (r5) GT_REGCLR(I2C_CONTROL, I2C_INT_FLAG) /* Send it */ bl wait_int cmpwi r6, ADDR_AND_READ_BIT_TRA_ACK_REC bne boot_i2c_read_bad /**/ GT_REGCLR(I2C_CONTROL, I2C_INT_FLAG | I2C_ACK) /* Get data */ /**/ bl wait_int cmpwi r6, MAS_REC_READ_DATA_ACK_NOT_TRA bne boot_i2c_read_bad GT_REGRD(I2C_DATA) or r3, r6 ,r6 b boot_i2c_read_end /**/ boot_i2c_read_bad: li r3, -1 boot_i2c_read_end: GT_REGSET(I2C_CONTROL, I2C_STOP_BIT) GT_REGCLR(I2C_CONTROL, I2C_INT_FLAG) mtlr r4 blr