1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2020-2023 Intel Corporation |
4 | */ |
5 | |
6 | #ifndef __IVPU_HW_REG_IO_H__ |
7 | #define __IVPU_HW_REG_IO_H__ |
8 | |
9 | #include <linux/bitfield.h> |
10 | #include <linux/io.h> |
11 | #include <linux/iopoll.h> |
12 | |
13 | #include "ivpu_drv.h" |
14 | |
15 | #define REG_POLL_SLEEP_US 50 |
16 | #define REG_IO_ERROR 0xffffffff |
17 | |
18 | #define REGB_RD32(reg) ivpu_hw_reg_rd32(vdev, vdev->regb, (reg), #reg, __func__) |
19 | #define REGB_RD32_SILENT(reg) readl(vdev->regb + (reg)) |
20 | #define REGB_RD64(reg) ivpu_hw_reg_rd64(vdev, vdev->regb, (reg), #reg, __func__) |
21 | #define REGB_WR32(reg, val) ivpu_hw_reg_wr32(vdev, vdev->regb, (reg), (val), #reg, __func__) |
22 | #define REGB_WR64(reg, val) ivpu_hw_reg_wr64(vdev, vdev->regb, (reg), (val), #reg, __func__) |
23 | |
24 | #define REGV_RD32(reg) ivpu_hw_reg_rd32(vdev, vdev->regv, (reg), #reg, __func__) |
25 | #define REGV_RD32_SILENT(reg) readl(vdev->regv + (reg)) |
26 | #define REGV_RD64(reg) ivpu_hw_reg_rd64(vdev, vdev->regv, (reg), #reg, __func__) |
27 | #define REGV_WR32(reg, val) ivpu_hw_reg_wr32(vdev, vdev->regv, (reg), (val), #reg, __func__) |
28 | #define REGV_WR64(reg, val) ivpu_hw_reg_wr64(vdev, vdev->regv, (reg), (val), #reg, __func__) |
29 | |
30 | #define REGV_WR32I(reg, stride, index, val) \ |
31 | ivpu_hw_reg_wr32_index(vdev, vdev->regv, (reg), (stride), (index), (val), #reg, __func__) |
32 | |
33 | #define REG_FLD(REG, FLD) \ |
34 | (REG##_##FLD##_MASK) |
35 | #define REG_FLD_NUM(REG, FLD, num) \ |
36 | FIELD_PREP(REG##_##FLD##_MASK, num) |
37 | #define REG_GET_FLD(REG, FLD, val) \ |
38 | FIELD_GET(REG##_##FLD##_MASK, val) |
39 | #define REG_CLR_FLD(REG, FLD, val) \ |
40 | ((val) & ~(REG##_##FLD##_MASK)) |
41 | #define REG_SET_FLD(REG, FLD, val) \ |
42 | ((val) | (REG##_##FLD##_MASK)) |
43 | #define REG_SET_FLD_NUM(REG, FLD, num, val) \ |
44 | (((val) & ~(REG##_##FLD##_MASK)) | FIELD_PREP(REG##_##FLD##_MASK, num)) |
45 | #define REG_TEST_FLD(REG, FLD, val) \ |
46 | ((REG##_##FLD##_MASK) == ((val) & (REG##_##FLD##_MASK))) |
47 | #define REG_TEST_FLD_NUM(REG, FLD, num, val) \ |
48 | ((num) == FIELD_GET(REG##_##FLD##_MASK, val)) |
49 | |
50 | #define REGB_POLL_FLD(reg, fld, val, timeout_us) \ |
51 | ({ \ |
52 | u32 var; \ |
53 | int r; \ |
54 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s started (expected 0x%x)\n", \ |
55 | __func__, #reg, reg, #fld, val); \ |
56 | r = read_poll_timeout(REGB_RD32_SILENT, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)),\ |
57 | REG_POLL_SLEEP_US, timeout_us, false, (reg)); \ |
58 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s %s (reg val 0x%08x)\n", \ |
59 | __func__, #reg, reg, #fld, r ? "ETIMEDOUT" : "OK", var); \ |
60 | r; \ |
61 | }) |
62 | |
63 | #define REGV_POLL_FLD(reg, fld, val, timeout_us) \ |
64 | ({ \ |
65 | u32 var; \ |
66 | int r; \ |
67 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s started (expected 0x%x)\n", \ |
68 | __func__, #reg, reg, #fld, val); \ |
69 | r = read_poll_timeout(REGV_RD32_SILENT, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)),\ |
70 | REG_POLL_SLEEP_US, timeout_us, false, (reg)); \ |
71 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s %s (reg val 0x%08x)\n", \ |
72 | __func__, #reg, reg, #fld, r ? "ETIMEDOUT" : "OK", var); \ |
73 | r; \ |
74 | }) |
75 | |
76 | static inline u32 |
77 | ivpu_hw_reg_rd32(struct ivpu_device *vdev, void __iomem *base, u32 reg, |
78 | const char *name, const char *func) |
79 | { |
80 | u32 val = readl(addr: base + reg); |
81 | |
82 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) RD: 0x%08x\n" , func, name, reg, val); |
83 | return val; |
84 | } |
85 | |
86 | static inline u64 |
87 | ivpu_hw_reg_rd64(struct ivpu_device *vdev, void __iomem *base, u32 reg, |
88 | const char *name, const char *func) |
89 | { |
90 | u64 val = readq(addr: base + reg); |
91 | |
92 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) RD: 0x%016llx\n" , func, name, reg, val); |
93 | return val; |
94 | } |
95 | |
96 | static inline void |
97 | ivpu_hw_reg_wr32(struct ivpu_device *vdev, void __iomem *base, u32 reg, u32 val, |
98 | const char *name, const char *func) |
99 | { |
100 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) WR: 0x%08x\n" , func, name, reg, val); |
101 | writel(val, addr: base + reg); |
102 | } |
103 | |
104 | static inline void |
105 | ivpu_hw_reg_wr64(struct ivpu_device *vdev, void __iomem *base, u32 reg, u64 val, |
106 | const char *name, const char *func) |
107 | { |
108 | ivpu_dbg(vdev, REG, "%s : %s (0x%08x) WR: 0x%016llx\n" , func, name, reg, val); |
109 | writeq(val, addr: base + reg); |
110 | } |
111 | |
112 | static inline void |
113 | ivpu_hw_reg_wr32_index(struct ivpu_device *vdev, void __iomem *base, u32 reg, |
114 | u32 stride, u32 index, u32 val, const char *name, |
115 | const char *func) |
116 | { |
117 | reg += index * stride; |
118 | |
119 | ivpu_dbg(vdev, REG, "%s WR: %s_%d (0x%08x) <= 0x%08x\n" , func, name, index, reg, val); |
120 | writel(val, addr: base + reg); |
121 | } |
122 | |
123 | #endif /* __IVPU_HW_REG_IO_H__ */ |
124 | |