1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
3*5113495bSYour Name * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name *
5*5113495bSYour Name * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name * above copyright notice and this permission notice appear in all
8*5113495bSYour Name * copies.
9*5113495bSYour Name *
10*5113495bSYour Name * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name */
19*5113495bSYour Name
20*5113495bSYour Name #include "athdefs.h"
21*5113495bSYour Name #include "a_types.h"
22*5113495bSYour Name #include "a_osapi.h"
23*5113495bSYour Name #define ATH_MODULE_NAME hif
24*5113495bSYour Name #include "a_debug.h"
25*5113495bSYour Name
26*5113495bSYour Name #include "targaddrs.h"
27*5113495bSYour Name #include "hif.h"
28*5113495bSYour Name #include "if_sdio.h"
29*5113495bSYour Name #include "regtable_sdio.h"
30*5113495bSYour Name #include "hif_sdio_dev.h"
31*5113495bSYour Name #include "qdf_module.h"
32*5113495bSYour Name
33*5113495bSYour Name #define CPU_DBG_SEL_ADDRESS 0x00000483
34*5113495bSYour Name #define CPU_DBG_ADDRESS 0x00000484
35*5113495bSYour Name #define WORD_NON_ALIGNMENT_MASK 0x03
36*5113495bSYour Name
37*5113495bSYour Name /**
38*5113495bSYour Name * hif_ar6000_set_address_window_register() - set the window address register
39*5113495bSYour Name * (using 4-byte register access).
40*5113495bSYour Name * @hif_device: hif context
41*5113495bSYour Name * @register_addr: register address
42*5113495bSYour Name * @addr: addr
43*5113495bSYour Name *
44*5113495bSYour Name * This mitigates host interconnect issues with non-4byte aligned bus requests,
45*5113495bSYour Name * some interconnects use bus adapters that impose strict limitations.
46*5113495bSYour Name * Since diag window access is not intended for performance critical operations,
47*5113495bSYour Name * the 4byte mode should be satisfactory as it generates 4X the bus activity.
48*5113495bSYour Name *
49*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success.
50*5113495bSYour Name */
51*5113495bSYour Name static
hif_ar6000_set_address_window_register(struct hif_sdio_dev * hif_device,uint32_t register_addr,uint32_t addr)52*5113495bSYour Name QDF_STATUS hif_ar6000_set_address_window_register(
53*5113495bSYour Name struct hif_sdio_dev *hif_device,
54*5113495bSYour Name uint32_t register_addr,
55*5113495bSYour Name uint32_t addr)
56*5113495bSYour Name {
57*5113495bSYour Name QDF_STATUS status;
58*5113495bSYour Name static uint32_t address;
59*5113495bSYour Name
60*5113495bSYour Name address = addr;
61*5113495bSYour Name /*AR6320,just write the 4-byte address to window register*/
62*5113495bSYour Name status = hif_read_write(hif_device,
63*5113495bSYour Name register_addr,
64*5113495bSYour Name (char *) (&address),
65*5113495bSYour Name 4, HIF_WR_SYNC_BYTE_INC, NULL);
66*5113495bSYour Name
67*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
68*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
69*5113495bSYour Name ("Cannot write 0x%x to window reg: 0x%X\n",
70*5113495bSYour Name addr, register_addr));
71*5113495bSYour Name return status;
72*5113495bSYour Name }
73*5113495bSYour Name
74*5113495bSYour Name return QDF_STATUS_SUCCESS;
75*5113495bSYour Name }
76*5113495bSYour Name
77*5113495bSYour Name /**
78*5113495bSYour Name * hif_diag_read_access() - Read from the AR6000 through its diagnostic window.
79*5113495bSYour Name * @hif_ctx: hif context
80*5113495bSYour Name * @address: address
81*5113495bSYour Name * @data: data
82*5113495bSYour Name *
83*5113495bSYour Name * No cooperation from the Target is required for this.
84*5113495bSYour Name *
85*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success.
86*5113495bSYour Name */
hif_diag_read_access(struct hif_opaque_softc * hif_ctx,uint32_t address,uint32_t * data)87*5113495bSYour Name QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *hif_ctx,
88*5113495bSYour Name uint32_t address,
89*5113495bSYour Name uint32_t *data)
90*5113495bSYour Name {
91*5113495bSYour Name QDF_STATUS status;
92*5113495bSYour Name static uint32_t readvalue;
93*5113495bSYour Name struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
94*5113495bSYour Name struct hif_sdio_dev *hif_device = scn->hif_handle;
95*5113495bSYour Name
96*5113495bSYour Name if (address & WORD_NON_ALIGNMENT_MASK) {
97*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
98*5113495bSYour Name ("[%s]addr is not 4 bytes align.addr[0x%08x]\n",
99*5113495bSYour Name __func__, address));
100*5113495bSYour Name return QDF_STATUS_E_FAILURE;
101*5113495bSYour Name }
102*5113495bSYour Name
103*5113495bSYour Name /* set window register to start read cycle */
104*5113495bSYour Name status = hif_ar6000_set_address_window_register(hif_device,
105*5113495bSYour Name WINDOW_READ_ADDR_ADDRESS,
106*5113495bSYour Name address);
107*5113495bSYour Name
108*5113495bSYour Name if (status != QDF_STATUS_SUCCESS)
109*5113495bSYour Name return status;
110*5113495bSYour Name
111*5113495bSYour Name /* read the data */
112*5113495bSYour Name status = hif_read_write(hif_device,
113*5113495bSYour Name WINDOW_DATA_ADDRESS,
114*5113495bSYour Name (char *) &readvalue,
115*5113495bSYour Name sizeof(uint32_t), HIF_RD_SYNC_BYTE_INC, NULL);
116*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
117*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
118*5113495bSYour Name ("Cannot read from WINDOW_DATA_ADDRESS\n"));
119*5113495bSYour Name return status;
120*5113495bSYour Name }
121*5113495bSYour Name
122*5113495bSYour Name *data = readvalue;
123*5113495bSYour Name return status;
124*5113495bSYour Name }
125*5113495bSYour Name
126*5113495bSYour Name /**
127*5113495bSYour Name * hif_diag_write_access() - Write to the AR6000 through its diagnostic window.
128*5113495bSYour Name * @hif_ctx: hif context
129*5113495bSYour Name * @address: address
130*5113495bSYour Name * @data: data
131*5113495bSYour Name *
132*5113495bSYour Name * No cooperation from the Target is required for this.
133*5113495bSYour Name *
134*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success.
135*5113495bSYour Name */
hif_diag_write_access(struct hif_opaque_softc * hif_ctx,uint32_t address,uint32_t data)136*5113495bSYour Name QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *hif_ctx,
137*5113495bSYour Name uint32_t address, uint32_t data)
138*5113495bSYour Name {
139*5113495bSYour Name QDF_STATUS status;
140*5113495bSYour Name static uint32_t write_value;
141*5113495bSYour Name struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
142*5113495bSYour Name struct hif_sdio_dev *hif_device = scn->hif_handle;
143*5113495bSYour Name
144*5113495bSYour Name if (address & WORD_NON_ALIGNMENT_MASK) {
145*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
146*5113495bSYour Name ("[%s]addr is not 4 bytes align.addr[0x%08x]\n",
147*5113495bSYour Name __func__, address));
148*5113495bSYour Name return QDF_STATUS_E_FAILURE;
149*5113495bSYour Name }
150*5113495bSYour Name
151*5113495bSYour Name write_value = data;
152*5113495bSYour Name
153*5113495bSYour Name /* set write data */
154*5113495bSYour Name status = hif_read_write(hif_device,
155*5113495bSYour Name WINDOW_DATA_ADDRESS,
156*5113495bSYour Name (char *) &write_value,
157*5113495bSYour Name sizeof(uint32_t), HIF_WR_SYNC_BYTE_INC, NULL);
158*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
159*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
160*5113495bSYour Name ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n",
161*5113495bSYour Name data));
162*5113495bSYour Name return status;
163*5113495bSYour Name }
164*5113495bSYour Name
165*5113495bSYour Name /* set window register, which starts the write cycle */
166*5113495bSYour Name return hif_ar6000_set_address_window_register(hif_device,
167*5113495bSYour Name WINDOW_WRITE_ADDR_ADDRESS,
168*5113495bSYour Name address);
169*5113495bSYour Name }
170*5113495bSYour Name
171*5113495bSYour Name /**
172*5113495bSYour Name * hif_diag_write_mem() - Write a block data to the AR6000 through its
173*5113495bSYour Name * diagnostic window.
174*5113495bSYour Name * @scn: hif context
175*5113495bSYour Name * @address: address
176*5113495bSYour Name * @data: data
177*5113495bSYour Name * @nbytes: nbytes
178*5113495bSYour Name *
179*5113495bSYour Name * This function may take some time.
180*5113495bSYour Name * No cooperation from the Target is required for this.
181*5113495bSYour Name *
182*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success.
183*5113495bSYour Name */
hif_diag_write_mem(struct hif_opaque_softc * scn,uint32_t address,uint8_t * data,int nbytes)184*5113495bSYour Name QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *scn, uint32_t address,
185*5113495bSYour Name uint8_t *data, int nbytes)
186*5113495bSYour Name {
187*5113495bSYour Name QDF_STATUS status;
188*5113495bSYour Name int32_t i;
189*5113495bSYour Name uint32_t tmp_data;
190*5113495bSYour Name
191*5113495bSYour Name if ((address & WORD_NON_ALIGNMENT_MASK) ||
192*5113495bSYour Name (nbytes & WORD_NON_ALIGNMENT_MASK)) {
193*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
194*5113495bSYour Name ("[%s]addr or length is not 4 bytes align.addr[0x%08x] len[0x%08x]\n",
195*5113495bSYour Name __func__, address, nbytes));
196*5113495bSYour Name return QDF_STATUS_E_FAILURE;
197*5113495bSYour Name }
198*5113495bSYour Name
199*5113495bSYour Name for (i = 0; i < nbytes; i += 4) {
200*5113495bSYour Name tmp_data =
201*5113495bSYour Name data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) |
202*5113495bSYour Name (data[i + 3] << 24);
203*5113495bSYour Name status = hif_diag_write_access(scn, address + i, tmp_data);
204*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
205*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
206*5113495bSYour Name ("Diag Write mem failed.addr[0x%08x] value[0x%08x]\n",
207*5113495bSYour Name address + i, tmp_data));
208*5113495bSYour Name return status;
209*5113495bSYour Name }
210*5113495bSYour Name }
211*5113495bSYour Name
212*5113495bSYour Name return QDF_STATUS_SUCCESS;
213*5113495bSYour Name }
214*5113495bSYour Name
215*5113495bSYour Name /**
216*5113495bSYour Name * hif_diag_read_mem() - Read a block data to the AR6000 through its diagnostic
217*5113495bSYour Name * window.
218*5113495bSYour Name * @scn: hif context
219*5113495bSYour Name * @address: target address
220*5113495bSYour Name * @data: data
221*5113495bSYour Name * @nbytes: nbytes
222*5113495bSYour Name *
223*5113495bSYour Name * This function may take some time.
224*5113495bSYour Name * No cooperation from the Target is required for this.
225*5113495bSYour Name *
226*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success.
227*5113495bSYour Name */
hif_diag_read_mem(struct hif_opaque_softc * scn,uint32_t address,uint8_t * data,int nbytes)228*5113495bSYour Name QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *scn,
229*5113495bSYour Name uint32_t address, uint8_t *data,
230*5113495bSYour Name int nbytes)
231*5113495bSYour Name {
232*5113495bSYour Name QDF_STATUS status;
233*5113495bSYour Name int32_t i;
234*5113495bSYour Name uint32_t tmp_data;
235*5113495bSYour Name
236*5113495bSYour Name if ((address & WORD_NON_ALIGNMENT_MASK) ||
237*5113495bSYour Name (nbytes & WORD_NON_ALIGNMENT_MASK)) {
238*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
239*5113495bSYour Name ("[%s]addr or length is not 4 bytes align.addr[0x%08x] len[0x%08x]\n",
240*5113495bSYour Name __func__, address, nbytes));
241*5113495bSYour Name return QDF_STATUS_E_FAILURE;
242*5113495bSYour Name }
243*5113495bSYour Name
244*5113495bSYour Name for (i = 0; i < nbytes; i += 4) {
245*5113495bSYour Name status = hif_diag_read_access(scn, address + i, &tmp_data);
246*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
247*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
248*5113495bSYour Name ("Diag Write mem failed.addr[0x%08x] value[0x%08x]\n",
249*5113495bSYour Name address + i, tmp_data));
250*5113495bSYour Name return status;
251*5113495bSYour Name }
252*5113495bSYour Name data[i] = tmp_data & 0xff;
253*5113495bSYour Name data[i + 1] = tmp_data >> 8 & 0xff;
254*5113495bSYour Name data[i + 2] = tmp_data >> 16 & 0xff;
255*5113495bSYour Name data[i + 3] = tmp_data >> 24 & 0xff;
256*5113495bSYour Name }
257*5113495bSYour Name
258*5113495bSYour Name return QDF_STATUS_SUCCESS;
259*5113495bSYour Name }
260*5113495bSYour Name qdf_export_symbol(hif_diag_read_mem);
261*5113495bSYour Name
262*5113495bSYour Name /**
263*5113495bSYour Name * hif_ar6k_read_target_register() - call to read target register values
264*5113495bSYour Name * @hif_device: hif context
265*5113495bSYour Name * @regsel: register selection
266*5113495bSYour Name * @regval: reg value
267*5113495bSYour Name *
268*5113495bSYour Name * Return: QDF_STATUS_SUCCESS for success.
269*5113495bSYour Name */
hif_ar6k_read_target_register(struct hif_sdio_dev * hif_device,int regsel,uint32_t * regval)270*5113495bSYour Name static QDF_STATUS hif_ar6k_read_target_register(struct hif_sdio_dev *hif_device,
271*5113495bSYour Name int regsel, uint32_t *regval)
272*5113495bSYour Name {
273*5113495bSYour Name QDF_STATUS status;
274*5113495bSYour Name char vals[4];
275*5113495bSYour Name char register_selection[4];
276*5113495bSYour Name
277*5113495bSYour Name register_selection[0] = regsel & 0xff;
278*5113495bSYour Name register_selection[1] = regsel & 0xff;
279*5113495bSYour Name register_selection[2] = regsel & 0xff;
280*5113495bSYour Name register_selection[3] = regsel & 0xff;
281*5113495bSYour Name status = hif_read_write(hif_device, CPU_DBG_SEL_ADDRESS,
282*5113495bSYour Name register_selection, 4,
283*5113495bSYour Name HIF_WR_SYNC_BYTE_FIX, NULL);
284*5113495bSYour Name
285*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
286*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
287*5113495bSYour Name ("Cannot write CPU_DBG_SEL (%d)\n", regsel));
288*5113495bSYour Name return status;
289*5113495bSYour Name }
290*5113495bSYour Name
291*5113495bSYour Name status = hif_read_write(hif_device,
292*5113495bSYour Name CPU_DBG_ADDRESS,
293*5113495bSYour Name (char *) vals,
294*5113495bSYour Name sizeof(vals), HIF_RD_SYNC_BYTE_INC, NULL);
295*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
296*5113495bSYour Name AR_DEBUG_PRINTF(ATH_LOG_ERR,
297*5113495bSYour Name ("Cannot read from CPU_DBG_ADDRESS\n"));
298*5113495bSYour Name return status;
299*5113495bSYour Name }
300*5113495bSYour Name
301*5113495bSYour Name *regval = vals[0] << 0 | vals[1] << 8 |
302*5113495bSYour Name vals[2] << 16 | vals[3] << 24;
303*5113495bSYour Name
304*5113495bSYour Name return status;
305*5113495bSYour Name }
306*5113495bSYour Name
307*5113495bSYour Name /**
308*5113495bSYour Name * hif_ar6k_fetch_target_regs() - call to fetch target reg values
309*5113495bSYour Name * @hif_device: hif context
310*5113495bSYour Name * @targregs: target regs
311*5113495bSYour Name *
312*5113495bSYour Name * Return: None
313*5113495bSYour Name */
hif_ar6k_fetch_target_regs(struct hif_sdio_dev * hif_device,uint32_t * targregs)314*5113495bSYour Name void hif_ar6k_fetch_target_regs(struct hif_sdio_dev *hif_device,
315*5113495bSYour Name uint32_t *targregs)
316*5113495bSYour Name {
317*5113495bSYour Name int i;
318*5113495bSYour Name uint32_t val;
319*5113495bSYour Name
320*5113495bSYour Name for (i = 0; i < AR6003_FETCH_TARG_REGS_COUNT; i++) {
321*5113495bSYour Name val = 0xffffffff;
322*5113495bSYour Name hif_ar6k_read_target_register(hif_device, i, &val);
323*5113495bSYour Name targregs[i] = val;
324*5113495bSYour Name }
325*5113495bSYour Name }
326