1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 26ebbf2ceSRussell King #include <asm/assembler.h> 3c36ef4b1SWill Deacon #include <asm/unwind.h> 4c36ef4b1SWill Deacon 56323f0ccSRussell King #if __LINUX_ARM_ARCH__ >= 6 6c36ef4b1SWill Deacon .macro bitop, name, instr 7c36ef4b1SWill Deacon ENTRY( \name ) 8c36ef4b1SWill Deacon UNWIND( .fnstart ) 9a16ede35SRussell King ands ip, r1, #3 10c001899aSStefan Agner strbne r1, [ip] @ assert word-aligned 1154ea06f6SRussell King mov r2, #1 126323f0ccSRussell King and r3, r0, #31 @ Get bit offset 136323f0ccSRussell King mov r0, r0, lsr #5 146323f0ccSRussell King add r1, r1, r0, lsl #2 @ Get word offset 15b7ec6994SWill Deacon #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) 16d779c07dSWill Deacon .arch_extension mp 17d779c07dSWill Deacon ALT_SMP(W(pldw) [r1]) 18d779c07dSWill Deacon ALT_UP(W(nop)) 19d779c07dSWill Deacon #endif 2054ea06f6SRussell King mov r3, r2, lsl r3 216323f0ccSRussell King 1: ldrex r2, [r1] 2254ea06f6SRussell King \instr r2, r2, r3 236323f0ccSRussell King strex r0, r2, [r1] 24e7ec0293SRussell King cmp r0, #0 2554ea06f6SRussell King bne 1b 263ba6e69aSDave Martin bx lr 27c36ef4b1SWill Deacon UNWIND( .fnend ) 28c36ef4b1SWill Deacon ENDPROC(\name ) 2954ea06f6SRussell King .endm 3054ea06f6SRussell King 31*dda5f312SMark Rutland .macro __testop, name, instr, store, barrier 32c36ef4b1SWill Deacon ENTRY( \name ) 33c36ef4b1SWill Deacon UNWIND( .fnstart ) 34a16ede35SRussell King ands ip, r1, #3 35c001899aSStefan Agner strbne r1, [ip] @ assert word-aligned 3654ea06f6SRussell King mov r2, #1 376323f0ccSRussell King and r3, r0, #31 @ Get bit offset 386323f0ccSRussell King mov r0, r0, lsr #5 396323f0ccSRussell King add r1, r1, r0, lsl #2 @ Get word offset 4054ea06f6SRussell King mov r3, r2, lsl r3 @ create mask 41*dda5f312SMark Rutland \barrier 42c32ffce0SWill Deacon #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) 43c32ffce0SWill Deacon .arch_extension mp 44c32ffce0SWill Deacon ALT_SMP(W(pldw) [r1]) 45c32ffce0SWill Deacon ALT_UP(W(nop)) 46c32ffce0SWill Deacon #endif 476323f0ccSRussell King 1: ldrex r2, [r1] 4854ea06f6SRussell King ands r0, r2, r3 @ save old value of bit 49614d73edSRussell King \instr r2, r2, r3 @ toggle bit 506323f0ccSRussell King strex ip, r2, [r1] 51614d73edSRussell King cmp ip, #0 5254ea06f6SRussell King bne 1b 53*dda5f312SMark Rutland \barrier 5454ea06f6SRussell King cmp r0, #0 5554ea06f6SRussell King movne r0, #1 563ba6e69aSDave Martin 2: bx lr 57c36ef4b1SWill Deacon UNWIND( .fnend ) 58c36ef4b1SWill Deacon ENDPROC(\name ) 5954ea06f6SRussell King .endm 60*dda5f312SMark Rutland 61*dda5f312SMark Rutland .macro testop, name, instr, store 62*dda5f312SMark Rutland __testop \name, \instr, \store, smp_dmb 63*dda5f312SMark Rutland .endm 64*dda5f312SMark Rutland 65*dda5f312SMark Rutland .macro sync_testop, name, instr, store 66*dda5f312SMark Rutland __testop \name, \instr, \store, __smp_dmb 67*dda5f312SMark Rutland .endm 6854ea06f6SRussell King #else 69c36ef4b1SWill Deacon .macro bitop, name, instr 70c36ef4b1SWill Deacon ENTRY( \name ) 71c36ef4b1SWill Deacon UNWIND( .fnstart ) 72a16ede35SRussell King ands ip, r1, #3 73c001899aSStefan Agner strbne r1, [ip] @ assert word-aligned 746323f0ccSRussell King and r2, r0, #31 756323f0ccSRussell King mov r0, r0, lsr #5 767a55fd0bSRussell King mov r3, #1 777a55fd0bSRussell King mov r3, r3, lsl r2 7859d1ff3bSRussell King save_and_disable_irqs ip 796323f0ccSRussell King ldr r2, [r1, r0, lsl #2] 807a55fd0bSRussell King \instr r2, r2, r3 816323f0ccSRussell King str r2, [r1, r0, lsl #2] 827a55fd0bSRussell King restore_irqs ip 836ebbf2ceSRussell King ret lr 84c36ef4b1SWill Deacon UNWIND( .fnend ) 85c36ef4b1SWill Deacon ENDPROC(\name ) 867a55fd0bSRussell King .endm 877a55fd0bSRussell King 887a55fd0bSRussell King /** 897a55fd0bSRussell King * testop - implement a test_and_xxx_bit operation. 907a55fd0bSRussell King * @instr: operational instruction 917a55fd0bSRussell King * @store: store instruction 927a55fd0bSRussell King * 937a55fd0bSRussell King * Note: we can trivially conditionalise the store instruction 946cbdc8c5SSimon Arlott * to avoid dirtying the data cache. 957a55fd0bSRussell King */ 96c36ef4b1SWill Deacon .macro testop, name, instr, store 97c36ef4b1SWill Deacon ENTRY( \name ) 98c36ef4b1SWill Deacon UNWIND( .fnstart ) 99a16ede35SRussell King ands ip, r1, #3 100c001899aSStefan Agner strbne r1, [ip] @ assert word-aligned 1016323f0ccSRussell King and r3, r0, #31 1026323f0ccSRussell King mov r0, r0, lsr #5 10359d1ff3bSRussell King save_and_disable_irqs ip 1046323f0ccSRussell King ldr r2, [r1, r0, lsl #2]! 1056323f0ccSRussell King mov r0, #1 1067a55fd0bSRussell King tst r2, r0, lsl r3 1077a55fd0bSRussell King \instr r2, r2, r0, lsl r3 1087a55fd0bSRussell King \store r2, [r1] 1097a55fd0bSRussell King moveq r0, #0 1100d928b0bSUwe Kleine-König restore_irqs ip 1116ebbf2ceSRussell King ret lr 112c36ef4b1SWill Deacon UNWIND( .fnend ) 113c36ef4b1SWill Deacon ENDPROC(\name ) 1147a55fd0bSRussell King .endm 11554ea06f6SRussell King #endif 116