From 9a252e367c18db23388d02814b3b4d7a3f0370e4 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 22 Sep 2018 16:30:05 +0200 Subject: [PATCH 1/2] csr: use readl()/writel() accessors for accessing mmio Instead of directly dereferencing pointers, use variants on readl()/writel(). This way we can replace these functions with others for remote access when writing drivers and code outside of the litex environment. Signed-off-by: Sean Cross --- litex/soc/integration/cpu_interface.py | 9 +++--- litex/soc/software/include/hw/common.h | 38 ++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/litex/soc/integration/cpu_interface.py b/litex/soc/integration/cpu_interface.py index fb9560706..e431f363f 100644 --- a/litex/soc/integration/cpu_interface.py +++ b/litex/soc/integration/cpu_interface.py @@ -123,12 +123,12 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_acc if with_access_functions: r += "static inline "+ctype+" "+reg_name+"_read(void) {\n" if size > 1: - r += "\t"+ctype+" r = MMPTR("+hex(reg_base)+");\n" + r += "\t"+ctype+" r = csr_readl("+hex(reg_base)+");\n" for byte in range(1, nwords): - r += "\tr <<= "+str(busword)+";\n\tr |= MMPTR("+hex(reg_base+4*byte)+");\n" + r += "\tr <<= "+str(busword)+";\n\tr |= csr_readl("+hex(reg_base+4*byte)+");\n" r += "\treturn r;\n}\n" else: - r += "\treturn MMPTR("+hex(reg_base)+");\n}\n" + r += "\treturn csr_readl("+hex(reg_base)+");\n}\n" if not read_only: r += "static inline void "+reg_name+"_write("+ctype+" value) {\n" @@ -138,7 +138,7 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_acc value_shifted = "value >> "+str(shift) else: value_shifted = "value" - r += "\tMMPTR("+hex(reg_base+4*word)+") = "+value_shifted+";\n" + r += "\tcsr_writel("+value_shifted+", "+hex(reg_base+4*word)+");\n" r += "}\n" return r @@ -146,6 +146,7 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_acc def get_csr_header(regions, constants, with_access_functions=True, with_shadow_base=True, shadow_base=0x80000000): r = "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n" if with_access_functions: + r += "#include \n" r += "#include \n" for name, origin, busword, obj in regions: if not with_shadow_base: diff --git a/litex/soc/software/include/hw/common.h b/litex/soc/software/include/hw/common.h index e5f9b51ee..abef55d65 100644 --- a/litex/soc/software/include/hw/common.h +++ b/litex/soc/software/include/hw/common.h @@ -1,10 +1,42 @@ #ifndef __HW_COMMON_H #define __HW_COMMON_H +#include + #ifdef __ASSEMBLER__ #define MMPTR(x) x -#else +#else /* ! __ASSEMBLER__ */ #define MMPTR(x) (*((volatile unsigned int *)(x))) -#endif -#endif +static inline void csr_writeb(uint8_t value, uint32_t addr) +{ + *((volatile uint8_t *)addr) = value; +} + +static inline uint8_t csr_readb(uint32_t addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline void csr_writew(uint16_t value, uint32_t addr) +{ + *((volatile uint16_t *)addr) = value; +} + +static inline uint16_t csr_readw(uint32_t addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline void csr_writel(uint32_t value, uint32_t addr) +{ + *((volatile uint32_t *)addr) = value; +} + +static inline uint32_t csr_readl(uint32_t addr) +{ + return *(volatile uint32_t *)addr; +} +#endif /* ! __ASSEMBLER__ */ + +#endif /* __HW_COMMON_H */ From 6f25a0d8a1dced95c87bbe38e014f85ec56a1528 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 22 Sep 2018 16:33:15 +0200 Subject: [PATCH 2/2] csr: use external csr_readl()/csr_writel() if present If the variable CSR_ACCESSORS_DEFINED is set, then use external csr_readl() and csr_writel() instead of locally-generated inline functions. With this patch, csr.h can be used with etherbone.h and litex_server to prototype drivers remotely. Signed-off-by: Sean Cross --- litex/soc/integration/cpu_interface.py | 9 +++++++++ litex/soc/software/include/hw/common.h | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/litex/soc/integration/cpu_interface.py b/litex/soc/integration/cpu_interface.py index e431f363f..0819b0a0a 100644 --- a/litex/soc/integration/cpu_interface.py +++ b/litex/soc/integration/cpu_interface.py @@ -147,7 +147,16 @@ def get_csr_header(regions, constants, with_access_functions=True, with_shadow_b r = "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n" if with_access_functions: r += "#include \n" + r += "#ifdef CSR_ACCESSORS_DEFINED\n" + r += "extern void csr_writeb(uint8_t value, uint32_t addr);\n" + r += "extern uint8_t csr_readb(uint32_t addr);\n" + r += "extern void csr_writew(uint16_t value, uint32_t addr);\n" + r += "extern uint16_t csr_readw(uint32_t addr);\n" + r += "extern void csr_writel(uint32_t value, uint32_t addr);\n" + r += "extern uint32_t csr_readl(uint32_t addr);\n" + r += "#else /* ! CSR_ACCESSORS_DEFINED */\n" r += "#include \n" + r += "#endif /* ! CSR_ACCESSORS_DEFINED */\n" for name, origin, busword, obj in regions: if not with_shadow_base: origin &= (~shadow_base) diff --git a/litex/soc/software/include/hw/common.h b/litex/soc/software/include/hw/common.h index abef55d65..af668f74e 100644 --- a/litex/soc/software/include/hw/common.h +++ b/litex/soc/software/include/hw/common.h @@ -3,6 +3,14 @@ #include +/* To overwrite CSR accessors, define extern, non-inlined versions + * of csr_read[bwl]() and csr_write[bwl](), and define + * CSR_ACCESSORS_DEFINED. + */ + +#ifndef CSR_ACCESSORS_DEFINED +#define CSR_ACCESSORS_DEFINED + #ifdef __ASSEMBLER__ #define MMPTR(x) x #else /* ! __ASSEMBLER__ */ @@ -39,4 +47,6 @@ static inline uint32_t csr_readl(uint32_t addr) } #endif /* ! __ASSEMBLER__ */ +#endif /* ! CSR_ACCESSORS_DEFINED */ + #endif /* __HW_COMMON_H */