NetBSD/sys/arch/arm/iomd/iomd_iic.S

248 lines
5.2 KiB
ArmAsm

/* $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 <machine/asm.h>
#include <machine/cpu.h>
#include <arm/iomd/iomdreg.h>
#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 */