1 .cpu arm7tdmi 2 .arch armv4t 3 .fpu softvfp 4 .eabi_attribute 20, 1 5 .eabi_attribute 21, 1 6 .eabi_attribute 23, 3 7 .eabi_attribute 24, 1 8 .eabi_attribute 25, 1 9 .eabi_attribute 26, 1 10 .eabi_attribute 30, 4 11 .eabi_attribute 34, 0 12 .eabi_attribute 18, 4 13 .file "spi.c" 14 .text 15 .Ltext0: 16 .cfi_sections .debug_frame 17 .file 1 "calypso/spi.c" 18 .section .text.spi_init,"ax",%progbits 19 .align 2 20 .global spi_init 21 .syntax unified 22 .arm 24 spi_init: 25 .LFB0: 1:calypso/spi.c **** /* Driver for SPI Master Controller inside TI Calypso */ 2:calypso/spi.c **** 3:calypso/spi.c **** /* (C) 2010 by Harald Welte 4:calypso/spi.c **** * 5:calypso/spi.c **** * All Rights Reserved 6:calypso/spi.c **** * 7:calypso/spi.c **** * This program is free software; you can redistribute it and/or modify 8:calypso/spi.c **** * it under the terms of the GNU General Public License as published by 9:calypso/spi.c **** * the Free Software Foundation; either version 2 of the License, or 10:calypso/spi.c **** * (at your option) any later version. 11:calypso/spi.c **** * 12:calypso/spi.c **** * This program is distributed in the hope that it will be useful, 13:calypso/spi.c **** * but WITHOUT ANY WARRANTY; without even the implied warranty of 14:calypso/spi.c **** * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15:calypso/spi.c **** * GNU General Public License for more details. 16:calypso/spi.c **** * 17:calypso/spi.c **** */ 18:calypso/spi.c **** 19:calypso/spi.c **** #include 20:calypso/spi.c **** #include 21:calypso/spi.c **** 22:calypso/spi.c **** //#define DEBUG 23:calypso/spi.c **** #include 24:calypso/spi.c **** 25:calypso/spi.c **** #include 26:calypso/spi.c **** #include 27:calypso/spi.c **** #include 28:calypso/spi.c **** 29:calypso/spi.c **** #define BASE_ADDR_SPI 0xfffe3000 30:calypso/spi.c **** #define SPI_REG(n) (BASE_ADDR_SPI+(n)) 31:calypso/spi.c **** 32:calypso/spi.c **** enum spi_regs { 33:calypso/spi.c **** REG_SET1 = 0x00, 34:calypso/spi.c **** REG_SET2 = 0x02, 35:calypso/spi.c **** REG_CTRL = 0x04, 36:calypso/spi.c **** REG_STATUS = 0x06, 37:calypso/spi.c **** REG_TX_LSB = 0x08, 38:calypso/spi.c **** REG_TX_MSB = 0x0a, 39:calypso/spi.c **** REG_RX_LSB = 0x0c, 40:calypso/spi.c **** REG_RX_MSB = 0x0e, 41:calypso/spi.c **** }; 42:calypso/spi.c **** 43:calypso/spi.c **** #define SPI_SET1_EN_CLK (1 << 0) 44:calypso/spi.c **** #define SPI_SET1_WR_IRQ_DIS (1 << 4) 45:calypso/spi.c **** #define SPI_SET1_RDWR_IRQ_DIS (1 << 5) 46:calypso/spi.c **** 47:calypso/spi.c **** #define SPI_CTRL_RDWR (1 << 0) 48:calypso/spi.c **** #define SPI_CTRL_WR (1 << 1) 49:calypso/spi.c **** #define SPI_CTRL_NB_SHIFT 2 50:calypso/spi.c **** #define SPI_CTRL_AD_SHIFT 7 51:calypso/spi.c **** 52:calypso/spi.c **** #define SPI_STATUS_RE (1 << 0) /* Read End */ 53:calypso/spi.c **** #define SPI_STATUS_WE (1 << 1) /* Write End */ 54:calypso/spi.c **** 55:calypso/spi.c **** void spi_init(void) 56:calypso/spi.c **** { 26 .loc 1 56 1 view -0 27 .cfi_startproc 28 @ Function supports interworking. 29 @ args = 0, pretend = 0, frame = 0 30 @ frame_needed = 0, uses_anonymous_args = 0 31 @ link register save eliminated. 57:calypso/spi.c **** writew(SPI_SET1_EN_CLK | SPI_SET1_WR_IRQ_DIS | SPI_SET1_RDWR_IRQ_DIS, 32 .loc 1 57 2 view .LVU1 33 0000 3120A0E3 mov r2, #49 34 0004 0C309FE5 ldr r3, .L2 35 0008 BF2F43E1 strh r2, [r3, #-255] @ movhi 58:calypso/spi.c **** SPI_REG(REG_SET1)); 59:calypso/spi.c **** 60:calypso/spi.c **** writew(0x0001, SPI_REG(REG_SET2)); 36 .loc 1 60 2 view .LVU2 37 000c 0120A0E3 mov r2, #1 38 0010 BD2F43E1 strh r2, [r3, #-253] @ movhi 61:calypso/spi.c **** } 39 .loc 1 61 1 is_stmt 0 view .LVU3 40 0014 1EFF2FE1 bx lr 41 .L3: 42 .align 2 43 .L2: 44 0018 FF30FEFF .word -118529 45 .cfi_endproc 46 .LFE0: 48 .section .text.spi_xfer,"ax",%progbits 49 .align 2 50 .global spi_xfer 51 .syntax unified 52 .arm 54 spi_xfer: 55 .LVL0: 56 .LFB1: 62:calypso/spi.c **** 63:calypso/spi.c **** int spi_xfer(uint8_t dev_idx, uint8_t bitlen, const void *dout, void *din) 64:calypso/spi.c **** { 57 .loc 1 64 1 is_stmt 1 view -0 58 .cfi_startproc 59 @ Function supports interworking. 60 @ args = 0, pretend = 0, frame = 0 61 @ frame_needed = 0, uses_anonymous_args = 0 65:calypso/spi.c **** uint8_t bytes_per_xfer; 62 .loc 1 65 2 view .LVU5 66:calypso/spi.c **** uint8_t reg_status, reg_ctrl = 0; 63 .loc 1 66 2 view .LVU6 67:calypso/spi.c **** uint32_t tmp; 64 .loc 1 67 2 view .LVU7 68:calypso/spi.c **** 69:calypso/spi.c **** if (bitlen == 0) 65 .loc 1 69 2 view .LVU8 64:calypso/spi.c **** uint8_t bytes_per_xfer; 66 .loc 1 64 1 is_stmt 0 view .LVU9 67 0000 70402DE9 push {r4, r5, r6, lr} 68 .LCFI0: 69 .cfi_def_cfa_offset 16 70 .cfi_offset 4, -16 71 .cfi_offset 5, -12 72 .cfi_offset 6, -8 73 .cfi_offset 14, -4 74 .loc 1 69 5 view .LVU10 75 0004 004051E2 subs r4, r1, #0 76 0008 2900000A beq .L6 70:calypso/spi.c **** return 0; 71:calypso/spi.c **** 72:calypso/spi.c **** if (bitlen > 32) 77 .loc 1 72 2 is_stmt 1 view .LVU11 73:calypso/spi.c **** return -1; 74:calypso/spi.c **** 75:calypso/spi.c **** if (dev_idx > 4) 78 .loc 1 75 2 view .LVU12 79 .loc 1 75 5 is_stmt 0 view .LVU13 80 000c 200054E3 cmp r4, #32 81 0010 04005093 cmpls r0, #4 73:calypso/spi.c **** return -1; 82 .loc 1 73 10 view .LVU14 83 0014 0000E083 mvnhi r0, #0 84 .LVL1: 85 .loc 1 75 5 view .LVU15 86 0018 2600008A bhi .L4 87 001c 0350A0E1 mov r5, r3 76:calypso/spi.c **** return -1; 77:calypso/spi.c **** 78:calypso/spi.c **** bytes_per_xfer = bitlen / 8; 88 .loc 1 78 2 is_stmt 1 view .LVU16 89 .LVL2: 79:calypso/spi.c **** if (bitlen % 8) 90 .loc 1 79 2 view .LVU17 80:calypso/spi.c **** bytes_per_xfer ++; 81:calypso/spi.c **** 82:calypso/spi.c **** reg_ctrl |= (bitlen - 1) << SPI_CTRL_NB_SHIFT; 91 .loc 1 82 2 view .LVU18 83:calypso/spi.c **** reg_ctrl |= (dev_idx & 0x7) << SPI_CTRL_AD_SHIFT; 92 .loc 1 83 2 view .LVU19 93 .loc 1 83 30 is_stmt 0 view .LVU20 94 0020 8003A0E1 lsl r0, r0, #7 82:calypso/spi.c **** reg_ctrl |= (dev_idx & 0x7) << SPI_CTRL_AD_SHIFT; 95 .loc 1 82 22 view .LVU21 96 0024 013044E2 sub r3, r4, #1 97 .LVL3: 98 .loc 1 83 11 view .LVU22 99 0028 030180E1 orr r0, r0, r3, lsl #2 100 002c 000CA0E1 lsl r0, r0, #24 84:calypso/spi.c **** 85:calypso/spi.c **** if (bitlen <= 8) { 101 .loc 1 85 5 view .LVU23 102 0030 080054E3 cmp r4, #8 86:calypso/spi.c **** tmp = *(uint8_t *)dout; 103 .loc 1 86 7 view .LVU24 104 0034 0020D295 ldrbls r2, [r2] @ zero_extendqisi2 105 .LVL4: 83:calypso/spi.c **** 106 .loc 1 83 11 view .LVU25 107 0038 400CA0E1 asr r0, r0, #24 108 .LVL5: 85:calypso/spi.c **** tmp = *(uint8_t *)dout; 109 .loc 1 85 2 is_stmt 1 view .LVU26 87:calypso/spi.c **** tmp <<= 24 + (8-bitlen); /* align to MSB */ 110 .loc 1 87 14 is_stmt 0 view .LVU27 111 003c 203064E2 rsb r3, r4, #32 85:calypso/spi.c **** tmp = *(uint8_t *)dout; 112 .loc 1 85 5 view .LVU28 113 0040 0200009A bls .L29 88:calypso/spi.c **** } else if (bitlen <= 16) { 114 .loc 1 88 9 is_stmt 1 view .LVU29 115 .loc 1 88 12 is_stmt 0 view .LVU30 116 0044 100054E3 cmp r4, #16 89:calypso/spi.c **** tmp = *(uint16_t *)dout; 117 .loc 1 89 3 is_stmt 1 view .LVU31 118 .loc 1 89 7 is_stmt 0 view .LVU32 119 0048 B020D291 ldrhls r2, [r2] 120 .LVL6: 90:calypso/spi.c **** tmp <<= 16 + (16-bitlen); /* align to MSB */ 121 .loc 1 90 3 is_stmt 1 view .LVU33 91:calypso/spi.c **** } else { 92:calypso/spi.c **** tmp = *(uint32_t *)dout; 122 .loc 1 92 3 view .LVU34 123 .loc 1 92 7 is_stmt 0 view .LVU35 124 004c 00209285 ldrhi r2, [r2] 125 .LVL7: 126 .L29: 93:calypso/spi.c **** tmp <<= (32-bitlen); /* align to MSB */ 127 .loc 1 93 3 is_stmt 1 view .LVU36 128 .loc 1 93 7 is_stmt 0 view .LVU37 129 0050 1223A0E1 lsl r2, r2, r3 130 .LVL8: 94:calypso/spi.c **** } 95:calypso/spi.c **** printd("spi_xfer(dev_idx=%u, bitlen=%u, data_out=0x%08x): ", 96:calypso/spi.c **** dev_idx, bitlen, tmp); 131 .loc 1 96 24 is_stmt 1 view .LVU38 97:calypso/spi.c **** 98:calypso/spi.c **** /* fill transmit registers */ 99:calypso/spi.c **** writew(tmp >> 16, SPI_REG(REG_TX_MSB)); 132 .loc 1 99 2 view .LVU39 100:calypso/spi.c **** writew(tmp & 0xffff, SPI_REG(REG_TX_LSB)); 101:calypso/spi.c **** 102:calypso/spi.c **** /* initiate transfer */ 103:calypso/spi.c **** if (din) 133 .loc 1 103 5 is_stmt 0 view .LVU40 134 0054 000055E3 cmp r5, #0 99:calypso/spi.c **** writew(tmp & 0xffff, SPI_REG(REG_TX_LSB)); 135 .loc 1 99 2 view .LVU41 136 0058 94309FE5 ldr r3, .L31 137 005c 2218A0E1 lsr r1, r2, #16 138 .LVL9: 104:calypso/spi.c **** reg_ctrl |= SPI_CTRL_RDWR; 139 .loc 1 104 12 view .LVU42 140 0060 01008013 orrne r0, r0, #1 141 .LVL10: 100:calypso/spi.c **** writew(tmp & 0xffff, SPI_REG(REG_TX_LSB)); 142 .loc 1 100 2 view .LVU43 143 0064 0228A0E1 lsl r2, r2, #16 144 .LVL11: 105:calypso/spi.c **** else 106:calypso/spi.c **** reg_ctrl |= SPI_CTRL_WR; 145 .loc 1 106 12 view .LVU44 146 0068 02008003 orreq r0, r0, #2 100:calypso/spi.c **** 147 .loc 1 100 2 view .LVU45 148 006c 2228A0E1 lsr r2, r2, #16 149 .loc 1 106 12 view .LVU46 150 0070 FF0000E2 and r0, r0, #255 99:calypso/spi.c **** writew(tmp & 0xffff, SPI_REG(REG_TX_LSB)); 151 .loc 1 99 2 view .LVU47 152 0074 B51F43E1 strh r1, [r3, #-245] @ movhi 100:calypso/spi.c **** 153 .loc 1 100 2 is_stmt 1 view .LVU48 154 0078 B72F43E1 strh r2, [r3, #-247] @ movhi 103:calypso/spi.c **** reg_ctrl |= SPI_CTRL_RDWR; 155 .loc 1 103 2 view .LVU49 104:calypso/spi.c **** else 156 .loc 1 104 3 view .LVU50 157 .loc 1 106 3 view .LVU51 158 .LVL12: 107:calypso/spi.c **** writew(reg_ctrl, SPI_REG(REG_CTRL)); 159 .loc 1 107 2 view .LVU52 108:calypso/spi.c **** printd("reg_ctrl=0x%04x ", reg_ctrl); 109:calypso/spi.c **** 110:calypso/spi.c **** /* wait until the transfer is complete */ 111:calypso/spi.c **** while (1) { 112:calypso/spi.c **** reg_status = readw(SPI_REG(REG_STATUS)); 160 .loc 1 112 16 is_stmt 0 view .LVU53 161 007c 70109FE5 ldr r1, .L31 107:calypso/spi.c **** writew(reg_ctrl, SPI_REG(REG_CTRL)); 162 .loc 1 107 2 view .LVU54 163 0080 BB0F43E1 strh r0, [r3, #-251] @ movhi 164 .L16: 108:calypso/spi.c **** printd("reg_ctrl=0x%04x ", reg_ctrl); 165 .loc 1 108 38 is_stmt 1 view .LVU55 111:calypso/spi.c **** reg_status = readw(SPI_REG(REG_STATUS)); 166 .loc 1 111 2 view .LVU56 167 .loc 1 112 3 view .LVU57 168 .loc 1 112 16 is_stmt 0 view .LVU58 169 0084 B93F51E1 ldrh r3, [r1, #-249] 113:calypso/spi.c **** printd("status=0x%04x ", reg_status); 114:calypso/spi.c **** if (din && (reg_status & SPI_STATUS_RE)) 170 .loc 1 114 6 view .LVU59 171 0088 000055E3 cmp r5, #0 112:calypso/spi.c **** printd("status=0x%04x ", reg_status); 172 .loc 1 112 14 view .LVU60 173 008c FF2003E2 and r2, r3, #255 174 .LVL13: 113:calypso/spi.c **** printd("status=0x%04x ", reg_status); 175 .loc 1 113 39 is_stmt 1 view .LVU61 176 .loc 1 114 3 view .LVU62 177 .loc 1 114 6 is_stmt 0 view .LVU63 178 0090 0100000A beq .L13 179 .loc 1 114 11 discriminator 1 view .LVU64 180 0094 010013E3 tst r3, #1 181 0098 0800001A bne .L14 182 .L13: 115:calypso/spi.c **** break; 116:calypso/spi.c **** else if (reg_status & SPI_STATUS_WE) 183 .loc 1 116 8 is_stmt 1 view .LVU65 184 .loc 1 116 11 is_stmt 0 view .LVU66 185 009c 020012E3 tst r2, #2 186 00a0 F7FFFF0A beq .L16 117:calypso/spi.c **** break; 118:calypso/spi.c **** } 119:calypso/spi.c **** /* FIXME: calibrate how much delay we really need (seven 13MHz cycles) */ 120:calypso/spi.c **** delay_ms(1); 187 .loc 1 120 2 is_stmt 1 view .LVU67 188 00a4 0100A0E3 mov r0, #1 189 .LVL14: 190 .loc 1 120 2 is_stmt 0 view .LVU68 191 00a8 FEFFFFEB bl delay_ms 192 .LVL15: 121:calypso/spi.c **** 122:calypso/spi.c **** if (din) { 193 .loc 1 122 2 is_stmt 1 view .LVU69 194 .loc 1 122 5 is_stmt 0 view .LVU70 195 00ac 000055E3 cmp r5, #0 196 00b0 0400001A bne .L17 197 .LVL16: 198 .L6: 70:calypso/spi.c **** 199 .loc 1 70 10 view .LVU71 200 00b4 0000A0E3 mov r0, #0 201 .L4: 123:calypso/spi.c **** tmp = readw(SPI_REG(REG_RX_MSB)) << 16; 124:calypso/spi.c **** tmp |= readw(SPI_REG(REG_RX_LSB)); 125:calypso/spi.c **** printd("data_in=0x%08x ", tmp); 126:calypso/spi.c **** 127:calypso/spi.c **** if (bitlen <= 8) 128:calypso/spi.c **** *(uint8_t *)din = tmp & 0xff; 129:calypso/spi.c **** else if (bitlen <= 16) 130:calypso/spi.c **** *(uint16_t *)din = tmp & 0xffff; 131:calypso/spi.c **** else 132:calypso/spi.c **** *(uint32_t *)din = tmp; 133:calypso/spi.c **** } 134:calypso/spi.c **** dputchar('\n'); 135:calypso/spi.c **** 136:calypso/spi.c **** return 0; 137:calypso/spi.c **** } 202 .loc 1 137 1 view .LVU72 203 00b8 7040BDE8 pop {r4, r5, r6, lr} 204 .LCFI1: 205 .cfi_remember_state 206 .cfi_restore 14 207 .cfi_restore 6 208 .cfi_restore 5 209 .cfi_restore 4 210 .cfi_def_cfa_offset 0 211 00bc 1EFF2FE1 bx lr 212 .LVL17: 213 .L14: 214 .LCFI2: 215 .cfi_restore_state 120:calypso/spi.c **** 216 .loc 1 120 2 is_stmt 1 view .LVU73 217 00c0 0100A0E3 mov r0, #1 218 .LVL18: 120:calypso/spi.c **** 219 .loc 1 120 2 is_stmt 0 view .LVU74 220 00c4 FEFFFFEB bl delay_ms 221 .LVL19: 122:calypso/spi.c **** tmp = readw(SPI_REG(REG_RX_MSB)) << 16; 222 .loc 1 122 2 is_stmt 1 view .LVU75 223 .L17: 123:calypso/spi.c **** tmp = readw(SPI_REG(REG_RX_MSB)) << 16; 224 .loc 1 123 3 view .LVU76 123:calypso/spi.c **** tmp = readw(SPI_REG(REG_RX_MSB)) << 16; 225 .loc 1 123 9 is_stmt 0 view .LVU77 226 00c8 24309FE5 ldr r3, .L31 227 00cc B12F53E1 ldrh r2, [r3, #-241] 228 .LVL20: 124:calypso/spi.c **** printd("data_in=0x%08x ", tmp); 229 .loc 1 124 3 is_stmt 1 view .LVU78 124:calypso/spi.c **** printd("data_in=0x%08x ", tmp); 230 .loc 1 124 10 is_stmt 0 view .LVU79 231 00d0 B33F53E1 ldrh r3, [r3, #-243] 127:calypso/spi.c **** *(uint8_t *)din = tmp & 0xff; 232 .loc 1 127 6 view .LVU80 233 00d4 080054E3 cmp r4, #8 124:calypso/spi.c **** printd("data_in=0x%08x ", tmp); 234 .loc 1 124 7 view .LVU81 235 00d8 023883E1 orr r3, r3, r2, lsl #16 236 .LVL21: 125:calypso/spi.c **** 237 .loc 1 125 33 is_stmt 1 view .LVU82 127:calypso/spi.c **** *(uint8_t *)din = tmp & 0xff; 238 .loc 1 127 3 view .LVU83 127:calypso/spi.c **** *(uint8_t *)din = tmp & 0xff; 239 .loc 1 127 6 is_stmt 0 view .LVU84 128:calypso/spi.c **** else if (bitlen <= 16) 240 .loc 1 128 4 is_stmt 1 view .LVU85 128:calypso/spi.c **** else if (bitlen <= 16) 241 .loc 1 128 20 is_stmt 0 view .LVU86 242 00dc 0030C595 strbls r3, [r5] 243 00e0 F3FFFF9A bls .L6 244 .L19: 129:calypso/spi.c **** *(uint16_t *)din = tmp & 0xffff; 245 .loc 1 129 8 is_stmt 1 view .LVU87 129:calypso/spi.c **** *(uint16_t *)din = tmp & 0xffff; 246 .loc 1 129 11 is_stmt 0 view .LVU88 247 00e4 100054E3 cmp r4, #16 130:calypso/spi.c **** else 248 .loc 1 130 4 is_stmt 1 view .LVU89 130:calypso/spi.c **** else 249 .loc 1 130 21 is_stmt 0 view .LVU90 250 00e8 B030C591 strhls r3, [r5] @ movhi 132:calypso/spi.c **** } 251 .loc 1 132 4 is_stmt 1 view .LVU91 132:calypso/spi.c **** } 252 .loc 1 132 21 is_stmt 0 view .LVU92 253 00ec 00308585 strhi r3, [r5] 254 00f0 EFFFFFEA b .L6 255 .L32: 256 .align 2 257 .L31: 258 00f4 FF30FEFF .word -118529 259 .cfi_endproc 260 .LFE1: 262 .text 263 .Letext0: 264 .file 2 "/usr/lib/gcc/arm-none-eabi/12.2.1/include/stdint.h" 265 .file 3 "include/delay.h" DEFINED SYMBOLS *ABS*:00000000 spi.c /tmp/ccTVdn6F.s:19 .text.spi_init:00000000 $a /tmp/ccTVdn6F.s:24 .text.spi_init:00000000 spi_init /tmp/ccTVdn6F.s:44 .text.spi_init:00000018 $d /tmp/ccTVdn6F.s:49 .text.spi_xfer:00000000 $a /tmp/ccTVdn6F.s:54 .text.spi_xfer:00000000 spi_xfer /tmp/ccTVdn6F.s:258 .text.spi_xfer:000000f4 $d UNDEFINED SYMBOLS delay_ms