Skip to content

Commit 2e9154a

Browse files
michalsieroncarlescufi
authored andcommitted
soc: litex-vexriscv: Rewrite litex_read/write
Changes signature so it takes uint32_t instead of pointer to a register. Later `sys_read*` and `sys_write*` functions are used, which cast given address to volatile pointer anyway. This required changing types of some fields in LiteX GPIO driver and removal of two casts in clock control driver. There was a weird assert from LiteX GPIO driver, which checked whether size of first register in dts was a multiple of 4. It didn't make much sense, so I removed it. Previous dts was describing size of a register in terms of subregisters used. New one uses size of register, so right now it is almost always 4 bytes. Most drivers don't read register size from dts anyway, so only changes had to be made in GPIO and clock control drivers. Both use `litex_read` and `litex_write` to operate on `n`bytes. Now GPIO driver calculates this `n` value in compile time from given number of pins and stores it in `reg_size` field of config struct like before. Registe sizes in clock control driver are hardcoded, because they are tied to LiteX wrapper anyway. This makes it possible to have code, independent of CSR data width. Signed-off-by: Michal Sieron <[email protected]>
1 parent f1e0cb6 commit 2e9154a

File tree

5 files changed

+71
-73
lines changed

5 files changed

+71
-73
lines changed

drivers/clock_control/clock_control_litex.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ static struct litex_clk_clkout *clkouts;/* clkout array for whole driver */
2525

2626
/* All DRP regs addresses and sizes */
2727
static struct litex_drp_reg drp[] = {
28-
{DRP_ADDR_RESET, DRP_SIZE_RESET},
29-
{DRP_ADDR_LOCKED, DRP_SIZE_LOCKED},
30-
{DRP_ADDR_READ, DRP_SIZE_READ},
31-
{DRP_ADDR_WRITE, DRP_SIZE_WRITE},
32-
{DRP_ADDR_DRDY, DRP_SIZE_DRDY},
33-
{DRP_ADDR_ADR, DRP_SIZE_ADR},
34-
{DRP_ADDR_DAT_W, DRP_SIZE_DAT_W},
35-
{DRP_ADDR_DAT_R, DRP_SIZE_DAT_R},
28+
{DRP_ADDR_RESET, 1},
29+
{DRP_ADDR_LOCKED, 1},
30+
{DRP_ADDR_READ, 1},
31+
{DRP_ADDR_WRITE, 1},
32+
{DRP_ADDR_DRDY, 1},
33+
{DRP_ADDR_ADR, 1},
34+
{DRP_ADDR_DAT_W, 2},
35+
{DRP_ADDR_DAT_R, 2},
3636
};
3737

3838
struct litex_clk_regs_addr litex_clk_regs_addr_init(void)
@@ -219,12 +219,12 @@ static inline uint64_t litex_clk_lookup_lock(uint32_t glob_mul)
219219

220220
static inline void litex_clk_set_reg(uint32_t reg, uint32_t val)
221221
{
222-
litex_write((uint32_t *)drp[reg].addr, drp[reg].size, val);
222+
litex_write(drp[reg].addr, drp[reg].size, val);
223223
}
224224

225225
static inline uint32_t litex_clk_get_reg(uint32_t reg)
226226
{
227-
return litex_read((uint32_t *)drp[reg].addr, drp[reg].size);
227+
return litex_read(drp[reg].addr, drp[reg].size);
228228
}
229229

230230
static inline void litex_clk_assert_reg(uint32_t reg)

drivers/clock_control/clock_control_litex.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,6 @@
4141
#define DRP_ADDR_ADR DT_REG_ADDR_BY_IDX(MMCM, 5/*DRP_ADR*/)
4242
#define DRP_ADDR_DAT_W DT_REG_ADDR_BY_IDX(MMCM, 6/*DRP_DAT_W*/)
4343
#define DRP_ADDR_DAT_R DT_REG_ADDR_BY_IDX(MMCM, 7/*DRP_DAT_R*/)
44-
/* Register size */
45-
#define DRP_SIZE_RESET DT_REG_SIZE_BY_IDX(MMCM, 0/*DRP_RESET*/)
46-
#define DRP_SIZE_LOCKED DT_REG_SIZE_BY_IDX(MMCM, 1/*DRP_LOCKED*/)
47-
#define DRP_SIZE_READ DT_REG_SIZE_BY_IDX(MMCM, 2/*DRP_READ*/)
48-
#define DRP_SIZE_WRITE DT_REG_SIZE_BY_IDX(MMCM, 3/*DRP_WRITE*/)
49-
#define DRP_SIZE_DRDY DT_REG_SIZE_BY_IDX(MMCM, 4/*DRP_DRDY*/)
50-
#define DRP_SIZE_ADR DT_REG_SIZE_BY_IDX(MMCM, 5/*DRP_ADR*/)
51-
#define DRP_SIZE_DAT_W DT_REG_SIZE_BY_IDX(MMCM, 6/*DRP_DAT_W*/)
52-
#define DRP_SIZE_DAT_R DT_REG_SIZE_BY_IDX(MMCM, 7/*DRP_DAT_R*/)
5344

5445
/* Devicetree global defines */
5546
#define LOCK_TIMEOUT DT_PROP(MMCM, litex_lock_timeout)

drivers/gpio/gpio_litex.c

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ static const char *LITEX_LOG_CANNOT_CHANGE_DIR =
3333
"Cannot change port direction selected in device tree\n";
3434

3535
struct gpio_litex_cfg {
36-
volatile uint32_t *reg_addr;
36+
uint32_t reg_addr;
3737
int reg_size;
38-
volatile uint32_t *ev_pending_addr;
39-
volatile uint32_t *ev_enable_addr;
40-
volatile uint32_t *ev_mode_addr;
41-
volatile uint32_t *ev_edge_addr;
38+
uint32_t ev_pending_addr;
39+
uint32_t ev_enable_addr;
40+
uint32_t ev_mode_addr;
41+
uint32_t ev_edge_addr;
4242
int nr_gpios;
4343
bool port_is_output;
4444
};
@@ -288,24 +288,16 @@ static const struct gpio_driver_api gpio_litex_driver_api = {
288288

289289
#define GPIO_LITEX_INIT(n) \
290290
static int gpio_litex_port_init_##n(const struct device *dev); \
291-
BUILD_ASSERT(DT_INST_REG_SIZE(n) != 0 \
292-
&& DT_INST_REG_SIZE(n) % 4 == 0, \
293-
"Register size must be a multiple of 4"); \
294291
\
295292
static const struct gpio_litex_cfg gpio_litex_cfg_##n = { \
296-
.reg_addr = \
297-
(volatile uint32_t *) DT_INST_REG_ADDR(n), \
298-
.reg_size = DT_INST_REG_SIZE(n) / 4, \
293+
.reg_addr = DT_INST_REG_ADDR(n), \
294+
.reg_size = DT_INST_REG_SIZE(n), \
299295
.nr_gpios = DT_INST_PROP(n, ngpios), \
300296
IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), ( \
301-
.ev_mode_addr = \
302-
(volatile uint32_t *) DT_INST_REG_ADDR_BY_NAME(n, irq_mode), \
303-
.ev_edge_addr = \
304-
(volatile uint32_t *) DT_INST_REG_ADDR_BY_NAME(n, irq_edge), \
305-
.ev_pending_addr = \
306-
(volatile uint32_t *) DT_INST_REG_ADDR_BY_NAME(n, irq_pend), \
307-
.ev_enable_addr = \
308-
(volatile uint32_t *) DT_INST_REG_ADDR_BY_NAME(n, irq_en), \
297+
.ev_mode_addr = DT_INST_REG_ADDR_BY_NAME(n, irq_mode), \
298+
.ev_edge_addr = DT_INST_REG_ADDR_BY_NAME(n, irq_edge), \
299+
.ev_pending_addr = DT_INST_REG_ADDR_BY_NAME(n, irq_pend), \
300+
.ev_enable_addr = DT_INST_REG_ADDR_BY_NAME(n, irq_en), \
309301
)) \
310302
.port_is_output = DT_INST_PROP(n, port_is_output), \
311303
}; \
@@ -325,8 +317,11 @@ static const struct gpio_driver_api gpio_litex_driver_api = {
325317
{ \
326318
const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev); \
327319
\
328-
/* each 4-byte register is able to handle 8 GPIO pins */ \
329-
if (gpio_config->nr_gpios > (gpio_config->reg_size * 8)) { \
320+
/* Check if gpios fit in declared register space */ \
321+
/* Number of subregisters times size in bits */ \
322+
const int max_gpios_can_fit = DT_INST_REG_SIZE(n) / 4 \
323+
* CONFIG_LITEX_CSR_DATA_WIDTH; \
324+
if (gpio_config->nr_gpios > max_gpios_can_fit) { \
330325
LOG_ERR("%s", LITEX_LOG_REG_SIZE_NGPIOS_MISMATCH); \
331326
return -EINVAL; \
332327
} \

dts/riscv/riscv32-litex-vexriscv.dtsi

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@
115115
gpio_in: gpio@e0006000 {
116116
compatible = "litex,gpio";
117117
reg = <0xe0006000 0x4
118-
0xe0006004 0x1
119-
0xe0006008 0x1
120-
0xe0006010 0x1
121-
0xe0006014 0x1>;
118+
0xe0006004 0x4
119+
0xe0006008 0x4
120+
0xe0006010 0x4
121+
0xe0006014 0x4>;
122122
interrupt-parent = <&intc0>;
123123
interrupts = <4 2>;
124124
reg-names = "base",
@@ -204,14 +204,14 @@
204204
clock0: clock@82005000 {
205205
compatible = "litex,clk";
206206
label = "clock0";
207-
reg = <0x82005000 0x1
208-
0x82005004 0x1
209-
0x82005008 0x1
210-
0x8200500c 0x1
211-
0x82005010 0x1
212-
0x82005014 0x1
213-
0x82005018 0x2
214-
0x82005020 0x2>;
207+
reg = <0x82005000 0x4
208+
0x82005004 0x4
209+
0x82005008 0x4
210+
0x8200500c 0x4
211+
0x82005010 0x4
212+
0x82005014 0x4
213+
0x82005018 0x8
214+
0x82005020 0x8>;
215215
reg-names = "drp_reset",
216216
"drp_locked",
217217
"drp_read",

soc/riscv/litex-vexriscv/soc.h

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
#include "../riscv-privilege/common/soc_common.h"
1111
#include <devicetree.h>
1212

13-
#define LITEX_SUBREG_SIZE 0x1
14-
#define LITEX_SUBREG_SIZE_BIT (LITEX_SUBREG_SIZE * 8)
15-
1613
/* lib-c hooks required RAM defined variables */
1714
#define RISCV_RAM_BASE DT_REG_ADDR(DT_INST(0, mmio_sram))
1815
#define RISCV_RAM_SIZE DT_REG_SIZE(DT_INST(0, mmio_sram))
@@ -110,30 +107,45 @@ static inline void litex_write32(unsigned int value, unsigned long addr)
110107
#endif
111108
}
112109

113-
static inline void litex_write(volatile uint32_t *reg, uint32_t reg_size, uint32_t val)
110+
/*
111+
* Operates on uint32_t values only
112+
* Size is in bytes and meaningful are 1, 2 or 4
113+
* Address must be aligned to 4 bytes
114+
*/
115+
static inline void litex_write(uint32_t addr, uint32_t size, uint32_t value)
114116
{
115-
uint32_t shifted_data, i;
116-
volatile uint32_t *reg_addr;
117-
118-
for (i = 0; i < reg_size; ++i) {
119-
shifted_data = val >> ((reg_size - i - 1) *
120-
LITEX_SUBREG_SIZE_BIT);
121-
reg_addr = ((volatile uint32_t *) reg) + i;
122-
*(reg_addr) = shifted_data;
117+
switch (size) {
118+
case 1:
119+
litex_write8(value, addr);
120+
break;
121+
case 2:
122+
litex_write16(value, addr);
123+
break;
124+
case 4:
125+
litex_write32(value, addr);
126+
break;
127+
default:
128+
break;
123129
}
124130
}
125131

126-
static inline uint32_t litex_read(volatile uint32_t *reg, uint32_t reg_size)
132+
/*
133+
* Operates on uint32_t values only
134+
* Size is in bytes and meaningful are 1, 2 or 4
135+
* Address must be aligned to 4 bytes
136+
*/
137+
static inline uint32_t litex_read(uint32_t addr, uint32_t size)
127138
{
128-
uint32_t shifted_data, i, result = 0;
129-
130-
for (i = 0; i < reg_size; ++i) {
131-
shifted_data = *(reg + i) << ((reg_size - i - 1) *
132-
LITEX_SUBREG_SIZE_BIT);
133-
result |= shifted_data;
139+
switch (size) {
140+
case 1:
141+
return litex_read8(addr);
142+
case 2:
143+
return litex_read16(addr);
144+
case 4:
145+
return litex_read32(addr);
146+
default:
147+
return 0;
134148
}
135-
136-
return result;
137149
}
138150

139151
#endif /* _ASMLANGUAGE */

0 commit comments

Comments
 (0)