/* $NetBSD: iomd_iic.S,v 1.3 2001/11/23 16:53:07 thorpej Exp $ */ /* * Copyright (c) 1994-1996 Mark Brinicombe. * Copyright (c) 1994 Brini. * All rights reserved. * * This code is derived from software written for Brini by Mark Brinicombe * * 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 Mark Brinicombe. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI OR CONTRIBUTORS 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. * * RiscBSD kernel project * * iic.s * * Low level routines to with IIC devices * * Created : 13/10/94 * * Based of kate/display/iic.s */ #include "assym.h" /* for __PROG32 */ #include #include #include #define IIC_BITDELAY 10 Liomd_base: .word _C_LABEL(iomd_base) ENTRY(iic_set_state) /* * Parameters * r0 - IIC data bit * r1 - IIC clock bit */ /* Store temporary register */ /* stmfd sp!, {r4}*/ /* * Mask the data and clock bits * Since these routines are only called from iiccontrol.c this is not * really needed */ and r0, r0, #0x00000001 and r1, r1, #0x00000001 /* Get address of IOMD control register */ ldr r2, Liomd_base ldr r2, [r2] /* Get the current CPSR */ /* mrs r4, cpsr_all orr r3, r4, #(I32_bit | F32_bit) msr cpsr_all, r3 */ IRQdisable /* Get current value of control register */ ldrb r3, [r2, #(IOMD_IOCR << 2)] /* Preserve non-IIC bits */ bic r3, r3, #0x00000003 /* orr r3, r3, #0x000000c0*/ /* Set the IIC clock and data bits */ orr r3, r3, r0 orr r3, r3, r1, lsl #1 /* Store the new value of control register */ strb r3, [r2, #(IOMD_IOCR << 2)] /* Restore CPSR state */ /* msr cpsr_all, r4 */ IRQenable /* Restore temporary register */ /* ldmfd sp!, {r4} */ /* Pause a bit */ mov r0, #(IIC_BITDELAY) /* Exit via iic_delay routine */ b _C_LABEL(iic_delay) ENTRY(iic_set_state_and_ack) /* * Parameters * r0 - IIC data bit * r1 - IIC clock bit */ /* Store temporary register */ /* stmfd sp!, {r4} */ /* * Mask the data and clock bits * Since these routines are only called from iiccontrol.c this is not * really needed */ and r0, r0, #0x00000001 and r1, r1, #0x00000001 /* Get address of IOMD control register */ ldr r2, Liomd_base ldr r2, [r2] /* Get the current CPSR */ /* mrs r4, cpsr_all orr r3, r4, #(I32_bit | F32_bit) msr cpsr_all, r3 */ IRQdisable /* Get current value of control register */ ldrb r3, [r2, #(IOMD_IOCR << 2)] /* Preserve non-IIC bits */ bic r3, r3, #0x00000003 /* orr r3, r3, #0x000000c0*/ /* Set the IIC clock and data bits */ orr r3, r3, r0 orr r3, r3, r1, lsl #1 /* Store the new value of control register */ strb r3, [r2, #(IOMD_IOCR << 2)] Liic_set_state_and_ack_loop: ldrb r3, [r2, #(IOMD_IOCR << 2)] tst r3, #0x00000002 beq Liic_set_state_and_ack_loop /* Restore CPSR state */ /* msr cpsr_all, r4 */ IRQenable /* Restore temporary register */ /* ldmfd sp!, {r4} */ /* Pause a bit */ mov r0, #(IIC_BITDELAY) /* Exit via iic_delay routine */ b _C_LABEL(iic_delay) ENTRY(iic_delay) /* * Parameters * r0 - time to wait */ /* Load address of IOMD */ ldr r2, Liomd_base ldr r2, [r2] /* Latch current value of timer 1 */ strb r2, [r2, #(IOMD_T0LATCH << 2)] /* Get the latched value */ ldrb r1, [r2, #(IOMD_T0LOW << 2)] /* Loop until timer reaches end value */ Liic_delay_loop: /* Latch the current value of timer1 */ strb r2, [r2, #(IOMD_T0LATCH << 2)] /* Get the latched value */ ldrb r3, [r2, #(IOMD_T0LOW << 2)] /* Loop until timer reached expected value */ teq r3, r1 movne r1, r3 beq Liic_delay_loop subs r0, r0, #0x00000001 bne Liic_delay_loop /* Exit */ mov pc, lr ENTRY(iic_getstate) /* Load address of IOMD */ ldr r2, Liomd_base ldr r2, [r2] /* Read IOCR */ ldrb r0, [r2, #(IOMD_IOCR << 2)] mov pc, lr /* End of iomd_iic.S */