1/* 2 * Copyright (C) 2009 Sascha Hauer <s.hauer@pengutronix.de> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9#include <linux/linkage.h> 10#include <asm/assembler.h> 11#include <asm/export.h> 12 13/* 14 * r8 = bit 0-15: tx offset, bit 16-31: tx buffer size 15 * r9 = bit 0-15: rx offset, bit 16-31: rx buffer size 16 */ 17 18#define SSI_STX0 0x00 19#define SSI_SRX0 0x08 20#define SSI_SISR 0x14 21#define SSI_SIER 0x18 22#define SSI_SACNT 0x38 23 24#define SSI_SACNT_AC97EN (1 << 0) 25 26#define SSI_SIER_TFE0_EN (1 << 0) 27#define SSI_SISR_TFE0 (1 << 0) 28#define SSI_SISR_RFF0 (1 << 2) 29#define SSI_SIER_RFF0_EN (1 << 2) 30 31 .text 32 .global imx_ssi_fiq_start 33 .global imx_ssi_fiq_end 34 .global imx_ssi_fiq_base 35 .global imx_ssi_fiq_rx_buffer 36 .global imx_ssi_fiq_tx_buffer 37 38/* 39 * imx_ssi_fiq_start is _intentionally_ not marked as a function symbol 40 * using ENDPROC(). imx_ssi_fiq_start and imx_ssi_fiq_end are used to 41 * mark the function body so that it can be copied to the FIQ vector in 42 * the vectors page. imx_ssi_fiq_start should only be called as the result 43 * of an FIQ: calling it directly will not work. 44 */ 45imx_ssi_fiq_start: 46 ldr r12, .L_imx_ssi_fiq_base 47 48 /* TX */ 49 ldr r13, .L_imx_ssi_fiq_tx_buffer 50 51 /* shall we send? */ 52 ldr r11, [r12, #SSI_SIER] 53 tst r11, #SSI_SIER_TFE0_EN 54 beq 1f 55 56 /* TX FIFO empty? */ 57 ldr r11, [r12, #SSI_SISR] 58 tst r11, #SSI_SISR_TFE0 59 beq 1f 60 61 mov r10, #0x10000 62 sub r10, #1 63 and r10, r10, r8 /* r10: current buffer offset */ 64 65 add r13, r13, r10 66 67 ldrh r11, [r13] 68 strh r11, [r12, #SSI_STX0] 69 70 ldrh r11, [r13, #2] 71 strh r11, [r12, #SSI_STX0] 72 73 ldrh r11, [r13, #4] 74 strh r11, [r12, #SSI_STX0] 75 76 ldrh r11, [r13, #6] 77 strh r11, [r12, #SSI_STX0] 78 79 add r10, #8 80 lsr r11, r8, #16 /* r11: buffer size */ 81 cmp r10, r11 82 lslgt r8, r11, #16 83 addle r8, #8 841: 85 /* RX */ 86 87 /* shall we receive? */ 88 ldr r11, [r12, #SSI_SIER] 89 tst r11, #SSI_SIER_RFF0_EN 90 beq 1f 91 92 /* RX FIFO full? */ 93 ldr r11, [r12, #SSI_SISR] 94 tst r11, #SSI_SISR_RFF0 95 beq 1f 96 97 ldr r13, .L_imx_ssi_fiq_rx_buffer 98 99 mov r10, #0x10000 100 sub r10, #1 101 and r10, r10, r9 /* r10: current buffer offset */ 102 103 add r13, r13, r10 104 105 ldr r11, [r12, #SSI_SACNT] 106 tst r11, #SSI_SACNT_AC97EN 107 108 ldr r11, [r12, #SSI_SRX0] 109 strh r11, [r13] 110 111 ldr r11, [r12, #SSI_SRX0] 112 strh r11, [r13, #2] 113 114 /* dummy read to skip slot 12 */ 115 ldrne r11, [r12, #SSI_SRX0] 116 117 ldr r11, [r12, #SSI_SRX0] 118 strh r11, [r13, #4] 119 120 ldr r11, [r12, #SSI_SRX0] 121 strh r11, [r13, #6] 122 123 /* dummy read to skip slot 12 */ 124 ldrne r11, [r12, #SSI_SRX0] 125 126 add r10, #8 127 lsr r11, r9, #16 /* r11: buffer size */ 128 cmp r10, r11 129 lslgt r9, r11, #16 130 addle r9, #8 131 1321: 133 @ return from FIQ 134 subs pc, lr, #4 135 136 .align 137.L_imx_ssi_fiq_base: 138imx_ssi_fiq_base: 139 .word 0x0 140.L_imx_ssi_fiq_rx_buffer: 141imx_ssi_fiq_rx_buffer: 142 .word 0x0 143.L_imx_ssi_fiq_tx_buffer: 144imx_ssi_fiq_tx_buffer: 145 .word 0x0 146.L_imx_ssi_fiq_end: 147imx_ssi_fiq_end: 148EXPORT_SYMBOL(imx_ssi_fiq_tx_buffer) 149EXPORT_SYMBOL(imx_ssi_fiq_rx_buffer) 150EXPORT_SYMBOL(imx_ssi_fiq_start) 151EXPORT_SYMBOL(imx_ssi_fiq_end) 152EXPORT_SYMBOL(imx_ssi_fiq_base) 153