From b30e78bd005b6f08e15ea75517eb2e2b293c7b4a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 3 Jun 2018 22:39:46 +1000 Subject: Add arbitration mechanism This will be used by the kernel GPIO driver to synchronize with the CF when accessing GPIO shared with FSI. Signed-off-by: Benjamin Herrenschmidt --- cf-code/cf-fsi-fw.S | 50 ++++++++++++++++++++++++++++++++++++++++++++------ cf-fsi-fw.h | 11 +++++++++-- cf-fsi-test.c | 2 +- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/cf-code/cf-fsi-fw.S b/cf-code/cf-fsi-fw.S index a68ce68..533cf39 100644 --- a/cf-code/cf-fsi-fw.S +++ b/cf-code/cf-fsi-fw.S @@ -200,21 +200,56 @@ _start: move.b #FW_VERSION,%a1@(FW_VERS_REG) move.b #API_VERSION,%a1@(API_VERS_REG) + /* Clear arbitration register */ + move.b #0,%a1@(ARB_REG) + /* * Main command loop */ main_loop: lea %a1@(TRACEBUF),%a3 - /* Wait for command */ -1: move.l %a1@(CMD_REG),%d2 + /* Wait arbitration request or command + * + * Note: This can run with interrupts enabled as a result of + * the stop op, so %d0 can be clobbered at any time. + */ +1: move.b %a1@(ARB_REG),%d2 + bne arbitration_request + move.l %a1@(CMD_REG),%d2 tst.b %d2 - bne 1f + bne command_request stop #0x2000 bra 1b +arbitration_request: /* Mask interrupts */ -1: move.w #0x2007,%sr + move.w #0x2007,%sr + + /* Ack request */ + move.b #ARB_ARM_ACK,%a1@(ARB_REG) + + /* Wait until it's cleared by the host */ +0: move.b %a1@(ARB_REG),%d1 + bne 1f + + /* Got it, re-load the GPIO caches */ + move.l %a5@(0),%DCLK + move.l %a4@(0),%DDAT + + /* Reconfigure data as output just in case ... */ + bsr config_gpio_out + + /* Back to main loop */ + bra main_loop + + /* Wait, we'll get an interrupt when the host clears it */ +1: stop #0x2000 + bra 0b + +command_request: + /* Mask interrupts */ + move.w #0x2007,%sr /* Mark ourselves as sending a command */ move.b #STAT_SENDING,%a1@(STAT_REG) @@ -443,10 +478,13 @@ config_gpio_in: move.l %d0,%a4@(4) rts - /* Interrupt handler */ + /* Interrupt handler + * + * Note: Must only clobber %d0 + */ _int: addq.l #1,%a1@(INT_CNT) - moveq.l #CVIC_SW_IRQ, %d0 + moveq.l #CVIC_SW_IRQ,%d0 move.l %d0,%a2@(CVIC_SW_IRQ_CLR) rte diff --git a/cf-fsi-fw.h b/cf-fsi-fw.h index 44bd8cc..36df3c9 100644 --- a/cf-fsi-fw.h +++ b/cf-fsi-fw.h @@ -2,7 +2,7 @@ #define __CF_FSI_FW_H /* - * SRAM layout + * SRAM layout: Main part */ /* Command register: @@ -74,7 +74,7 @@ /* Misc */ #define INT_CNT 0x30 /* 32-bit interrupt count */ #define BAD_INT_VEC 0x34 -#define TRACEBUF 0x40 +#define TRACEBUF 0x100 #define TR_CLKOSTART 0x00 #define TR_OLEN 0x01/* + len */ #define TR_CLKOBIT0 0x02 @@ -87,5 +87,12 @@ #define TR_CLKIBIT0 0x80 #define TR_CLKIBIT1 0x81 +/* + * SRAM layout: GPIO arbitration part + */ +#define ARB_REG 0x40 +#define ARB_ARM_REQ 0x01 +#define ARB_ARM_ACK 0x02 + #endif /* __CF_FSI_FW_H */ diff --git a/cf-fsi-test.c b/cf-fsi-test.c index 65c240c..56e8a8f 100644 --- a/cf-fsi-test.c +++ b/cf-fsi-test.c @@ -104,7 +104,7 @@ static inline void writeq(uint64_t val, void *addr) #define GPIO_AA_SRC_BIT 0x00010000 #define GPIO_R_SRC_BIT 0x00000100 -#define CVIC_BASE 0x000c2000 +#define CVIC_BASE 0x000c2000 /* 1e602000 */ #define CVIC_EN_REG 0x10 #define CVIC_TRIG_REG 0x18 -- cgit v1.2.1