1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | * cx18 driver PCI memory mapped IO access routines |
4 | * |
5 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> |
6 | * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> |
7 | */ |
8 | |
9 | #ifndef CX18_IO_H |
10 | #define CX18_IO_H |
11 | |
12 | #include "cx18-driver.h" |
13 | |
14 | /* |
15 | * Readback and retry of MMIO access for reliability: |
16 | * The concept was suggested by Steve Toth <stoth@linuxtv.org>. |
17 | * The implementation is the fault of Andy Walls <awalls@md.metrocast.net>. |
18 | * |
19 | * *write* functions are implied to retry the mmio unless suffixed with _noretry |
20 | * *read* functions never retry the mmio (it never helps to do so) |
21 | */ |
22 | |
23 | /* Non byteswapping memory mapped IO */ |
24 | static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) |
25 | { |
26 | return __raw_readl(addr); |
27 | } |
28 | |
29 | static inline |
30 | void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) |
31 | { |
32 | __raw_writel(val, addr); |
33 | } |
34 | |
35 | static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) |
36 | { |
37 | int i; |
38 | for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) { |
39 | cx18_raw_writel_noretry(cx, val, addr); |
40 | if (val == cx18_raw_readl(cx, addr)) |
41 | break; |
42 | } |
43 | } |
44 | |
45 | /* Normal memory mapped IO */ |
46 | static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) |
47 | { |
48 | return readl(addr); |
49 | } |
50 | |
51 | static inline |
52 | void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) |
53 | { |
54 | writel(val, addr); |
55 | } |
56 | |
57 | static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) |
58 | { |
59 | int i; |
60 | for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) { |
61 | cx18_writel_noretry(cx, val, addr); |
62 | if (val == cx18_readl(cx, addr)) |
63 | break; |
64 | } |
65 | } |
66 | |
67 | static inline |
68 | void cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, |
69 | u32 eval, u32 mask) |
70 | { |
71 | int i; |
72 | u32 r; |
73 | eval &= mask; |
74 | for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) { |
75 | cx18_writel_noretry(cx, val, addr); |
76 | r = cx18_readl(cx, addr); |
77 | if (r == 0xffffffff && eval != 0xffffffff) |
78 | continue; |
79 | if (eval == (r & mask)) |
80 | break; |
81 | } |
82 | } |
83 | |
84 | static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr) |
85 | { |
86 | return readw(addr); |
87 | } |
88 | |
89 | static inline |
90 | void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) |
91 | { |
92 | writew(val, addr); |
93 | } |
94 | |
95 | static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr) |
96 | { |
97 | int i; |
98 | for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) { |
99 | cx18_writew_noretry(cx, val, addr); |
100 | if (val == cx18_readw(cx, addr)) |
101 | break; |
102 | } |
103 | } |
104 | |
105 | static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr) |
106 | { |
107 | return readb(addr); |
108 | } |
109 | |
110 | static inline |
111 | void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr) |
112 | { |
113 | writeb(val, addr); |
114 | } |
115 | |
116 | static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr) |
117 | { |
118 | int i; |
119 | for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) { |
120 | cx18_writeb_noretry(cx, val, addr); |
121 | if (val == cx18_readb(cx, addr)) |
122 | break; |
123 | } |
124 | } |
125 | |
126 | static inline |
127 | void cx18_memcpy_fromio(struct cx18 *cx, void *to, |
128 | const void __iomem *from, unsigned int len) |
129 | { |
130 | memcpy_fromio(to, from, len); |
131 | } |
132 | |
133 | void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count); |
134 | |
135 | |
136 | /* Access "register" region of CX23418 memory mapped I/O */ |
137 | static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg) |
138 | { |
139 | cx18_writel_noretry(cx, val, addr: cx->reg_mem + reg); |
140 | } |
141 | |
142 | static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) |
143 | { |
144 | cx18_writel(cx, val, addr: cx->reg_mem + reg); |
145 | } |
146 | |
147 | static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, |
148 | u32 eval, u32 mask) |
149 | { |
150 | cx18_writel_expect(cx, val, addr: cx->reg_mem + reg, eval, mask); |
151 | } |
152 | |
153 | static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg) |
154 | { |
155 | return cx18_readl(cx, addr: cx->reg_mem + reg); |
156 | } |
157 | |
158 | |
159 | /* Access "encoder memory" region of CX23418 memory mapped I/O */ |
160 | static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) |
161 | { |
162 | cx18_writel(cx, val, addr: cx->enc_mem + addr); |
163 | } |
164 | |
165 | static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr) |
166 | { |
167 | return cx18_readl(cx, addr: cx->enc_mem + addr); |
168 | } |
169 | |
170 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val); |
171 | void cx18_sw1_irq_disable(struct cx18 *cx, u32 val); |
172 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val); |
173 | void cx18_sw2_irq_disable(struct cx18 *cx, u32 val); |
174 | void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val); |
175 | void cx18_setup_page(struct cx18 *cx, u32 addr); |
176 | |
177 | #endif /* CX18_IO_H */ |
178 | |