xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/hif_io32.h (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef __HIF_IO32_H__
20 #define __HIF_IO32_H__
21 
22 #include <linux/io.h>
23 #include "hif.h"
24 #include "hif_main.h"
25 
26 #if defined(HIF_REG_WINDOW_SUPPORT) && defined(HIF_PCI)
27 
28 static inline
29 void hif_write32_mb_reg_window(void *sc,
30 			       void __iomem *addr, uint32_t value);
31 static inline
32 uint32_t hif_read32_mb_reg_window(void *sc,
33 				  void __iomem *addr);
34 #define hif_read32_mb(scn, addr) \
35 	hif_read32_mb_reg_window((void *)scn, \
36 				 (void __iomem *)addr)
37 #define hif_write32_mb(scn, addr, value) \
38 	hif_write32_mb_reg_window((void *)scn, \
39 				  (void __iomem *)addr, value)
40 
41 #else
42 #define hif_read32_mb(scn, addr)         ioread32((void __iomem *)addr)
43 #define hif_write32_mb(scn, addr, value) \
44 	iowrite32((u32)(value), (void __iomem *)(addr))
45 #endif
46 
47 #define Q_TARGET_ACCESS_BEGIN(scn) \
48 	hif_target_sleep_state_adjust(scn, false, true)
49 #define Q_TARGET_ACCESS_END(scn) \
50 	hif_target_sleep_state_adjust(scn, true, false)
51 #define TARGET_REGISTER_ACCESS_ALLOWED(scn)\
52 		hif_is_target_register_access_allowed(scn)
53 
54 /*
55  * A_TARGET_ACCESS_LIKELY will not wait for the target to wake up before
56  * continuing execution.  Because A_TARGET_ACCESS_LIKELY does not guarantee
57  * that the target is awake before continuing, Q_TARGET_ACCESS macros must
58  * protect the actual target access.  Since Q_TARGET_ACCESS protect the actual
59  * target access, A_TARGET_ACCESS_LIKELY hints are optional.
60  *
61  * To ignore "LIKELY" hints, set CONFIG_TARGET_ACCESS_LIKELY to 0
62  * (slightly worse performance, less power)
63  *
64  * To use "LIKELY" hints, set CONFIG_TARGET_ACCESS_LIKELY to 1
65  * (slightly better performance, more power)
66  *
67  * note: if a bus doesn't use hif_target_sleep_state_adjust, this will have
68  * no impact.
69  */
70 #define CONFIG_TARGET_ACCESS_LIKELY 0
71 #if CONFIG_TARGET_ACCESS_LIKELY
72 #define A_TARGET_ACCESS_LIKELY(scn) \
73 	hif_target_sleep_state_adjust(scn, false, false)
74 #define A_TARGET_ACCESS_UNLIKELY(scn) \
75 	hif_target_sleep_state_adjust(scn, true, false)
76 #else                           /* CONFIG_ATH_PCIE_ACCESS_LIKELY */
77 #define A_TARGET_ACCESS_LIKELY(scn) \
78 	do { \
79 		unsigned long unused = (unsigned long)(scn); \
80 		unused = unused; \
81 	} while (0)
82 
83 #define A_TARGET_ACCESS_UNLIKELY(scn) \
84 	do { \
85 		unsigned long unused = (unsigned long)(scn); \
86 		unused = unused; \
87 	} while (0)
88 #endif /* CONFIG_ATH_PCIE_ACCESS_LIKELY */
89 
90 
91 #ifdef HIF_PCI
92 #include "hif_io32_pci.h"
93 #endif
94 #ifdef HIF_SNOC
95 #include "hif_io32_snoc.h"
96 #endif
97 #ifdef HIF_IPCI
98 #include "hif_io32_ipci.h"
99 #endif
100 
101 #ifdef HIF_IPCI
102 /**
103  * hif_target_access_allowed(): Check if target access is allowed
104  *
105  * @scn: HIF handler
106  *
107  * Return: True if access is allowed else False
108  */
109 static inline
110 bool hif_target_access_allowed(struct hif_softc *scn)
111 {
112 	return !(scn->recovery);
113 }
114 
115 #define TARGET_ACCESS_ALLOWED(scn) \
116 	hif_target_access_allowed(scn)
117 #else
118 #define TARGET_ACCESS_ALLOWED(scn) (1)
119 #endif
120 
121 #if defined(HIF_REG_WINDOW_SUPPORT) && defined(HIF_PCI)
122 
123 #include "qdf_lock.h"
124 #include "qdf_util.h"
125 
126 /* Device memory is 32MB but bar size is only 1MB.
127  * Register remapping logic is used to access 32MB device memory.
128  * 0-512KB : Fixed address, 512KB-1MB : remapped address.
129  * Use PCIE_REMAP_1M_BAR_CTRL register to set window.
130  * Offset: 0x310C
131  * Bits  : Field Name
132  * 31      FUNCTION_ENABLE_V
133  * 5:0     ADDR_24_19_V
134  */
135 
136 #define MAX_UNWINDOWED_ADDRESS 0x80000 /* 512KB */
137 #define WINDOW_ENABLE_BIT 0x80000000 /* 31st bit to enable window */
138 #define WINDOW_REG_ADDRESS 0x310C /* PCIE_REMAP_1M_BAR_CTRL Reg offset */
139 #define WINDOW_SHIFT 19
140 #define WINDOW_VALUE_MASK 0x3F
141 #define WINDOW_START MAX_UNWINDOWED_ADDRESS
142 #define WINDOW_RANGE_MASK 0x7FFFF
143 
144 static inline void hif_select_window(struct hif_pci_softc *sc, uint32_t offset)
145 {
146 	uint32_t window = (offset >> WINDOW_SHIFT) & WINDOW_VALUE_MASK;
147 
148 	if (window != sc->register_window) {
149 		qdf_iowrite32(sc->mem + WINDOW_REG_ADDRESS,
150 			      WINDOW_ENABLE_BIT | window);
151 		sc->register_window = window;
152 	}
153 }
154 
155 /**
156  * note1: WINDOW_RANGE_MASK = (1 << WINDOW_SHIFT) -1
157  * note2: 1 << WINDOW_SHIFT = MAX_UNWINDOWED_ADDRESS
158  * note3: WINDOW_VALUE_MASK = big enough that trying to write past that window
159  *				would be a bug
160  */
161 static inline void hif_write32_mb_reg_window(void *scn,
162 					     void __iomem *addr, uint32_t value)
163 {
164 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
165 	uint32_t offset = addr - sc->mem;
166 
167 	if (!sc->use_register_windowing ||
168 	    offset < MAX_UNWINDOWED_ADDRESS) {
169 		qdf_iowrite32(addr, value);
170 	} else {
171 		qdf_spin_lock_irqsave(&sc->register_access_lock);
172 		hif_select_window(sc, offset);
173 		qdf_iowrite32(sc->mem + WINDOW_START +
174 			  (offset & WINDOW_RANGE_MASK), value);
175 		qdf_spin_unlock_irqrestore(&sc->register_access_lock);
176 	}
177 }
178 
179 static inline uint32_t hif_read32_mb_reg_window(void *scn, void __iomem *addr)
180 {
181 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
182 	uint32_t ret;
183 	uint32_t offset = addr - sc->mem;
184 
185 	if (!sc->use_register_windowing ||
186 	    offset < MAX_UNWINDOWED_ADDRESS) {
187 		return qdf_ioread32(addr);
188 	}
189 
190 	qdf_spin_lock_irqsave(&sc->register_access_lock);
191 	hif_select_window(sc, offset);
192 	ret = qdf_ioread32(sc->mem + WINDOW_START +
193 		       (offset & WINDOW_RANGE_MASK));
194 	qdf_spin_unlock_irqrestore(&sc->register_access_lock);
195 
196 	return ret;
197 }
198 #endif
199 
200 #ifdef CONFIG_IO_MEM_ACCESS_DEBUG
201 uint32_t hif_target_read_checked(struct hif_softc *scn,
202 					uint32_t offset);
203 void hif_target_write_checked(struct hif_softc *scn, uint32_t offset,
204 				     uint32_t value);
205 
206 #define A_TARGET_READ(scn, offset) \
207 	hif_target_read_checked(scn, (offset))
208 #define A_TARGET_WRITE(scn, offset, value) \
209 	hif_target_write_checked(scn, (offset), (value))
210 #else                           /* CONFIG_ATH_PCIE_ACCESS_DEBUG */
211 #define A_TARGET_READ(scn, offset) \
212 	hif_read32_mb(scn, scn->mem + (offset))
213 #define A_TARGET_WRITE(scn, offset, value) \
214 	hif_write32_mb(scn, (scn->mem) + (offset), value)
215 #endif
216 
217 void hif_irq_enable(struct hif_softc *scn, int irq_id);
218 void hif_irq_disable(struct hif_softc *scn, int irq_id);
219 
220 #endif /* __HIF_IO32_H__ */
221