Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c
39566 views
1
/*-
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
5
* Copyright (c) 2002-2008 Atheros Communications, Inc.
6
*
7
* Permission to use, copy, modify, and/or distribute this software for any
8
* purpose with or without fee is hereby granted, provided that the above
9
* copyright notice and this permission notice appear in all copies.
10
*
11
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
*/
19
#include "opt_ah.h"
20
21
#include "ah.h"
22
#include "ah_internal.h"
23
#include "ah_devid.h"
24
25
#include "ar5416/ar5416.h"
26
#include "ar5416/ar5416reg.h"
27
#include "ar5416/ar5416phy.h"
28
29
#define AR_GPIO_BIT(_gpio) (1 << _gpio)
30
31
/*
32
* Configure GPIO Output Mux control
33
*/
34
static void
35
cfgOutputMux(struct ath_hal *ah, uint32_t gpio, uint32_t type)
36
{
37
int addr;
38
uint32_t gpio_shift, tmp;
39
40
HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d, type=%d\n",
41
__func__, gpio, type);
42
43
/* each MUX controls 6 GPIO pins */
44
if (gpio > 11)
45
addr = AR_GPIO_OUTPUT_MUX3;
46
else if (gpio > 5)
47
addr = AR_GPIO_OUTPUT_MUX2;
48
else
49
addr = AR_GPIO_OUTPUT_MUX1;
50
51
/*
52
* 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux,
53
* bits 5..9 for 2nd pin, etc.
54
*/
55
gpio_shift = (gpio % 6) * 5;
56
57
/*
58
* From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit
59
* 9 are wrong. Here is hardware's coding:
60
* PRDATA[4:0] <= gpio_output_mux[0];
61
* PRDATA[9:4] <= gpio_output_mux[1];
62
* <==== Bit 4 is used by both gpio_output_mux[0] [1].
63
* Currently the max value for gpio_output_mux[] is 6. So bit 4
64
* will never be used. So it should be fine that bit 4 won't be
65
* able to recover.
66
*/
67
if (AR_SREV_MERLIN_20_OR_LATER(ah) ||
68
(addr != AR_GPIO_OUTPUT_MUX1)) {
69
OS_REG_RMW(ah, addr, (type << gpio_shift),
70
(0x1f << gpio_shift));
71
} else {
72
tmp = OS_REG_READ(ah, addr);
73
tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
74
tmp &= ~(0x1f << gpio_shift);
75
tmp |= type << gpio_shift;
76
OS_REG_WRITE(ah, addr, tmp);
77
}
78
}
79
80
/*
81
* Configure GPIO Output lines
82
*/
83
HAL_BOOL
84
ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
85
{
86
uint32_t gpio_shift, reg;
87
88
#define N(a) (sizeof(a) / sizeof(a[0]))
89
90
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
91
92
/*
93
* This table maps the HAL GPIO pins to the actual hardware
94
* values.
95
*/
96
static const u_int32_t MuxSignalConversionTable[] = {
97
AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
98
AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
99
AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
100
AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
101
AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
102
AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
103
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
104
};
105
106
HALDEBUG(ah, HAL_DEBUG_GPIO,
107
"%s: gpio=%d, type=%d\n", __func__, gpio, type);
108
109
/*
110
* Convert HAL signal type definitions to hardware-specific values.
111
*/
112
if (type >= N(MuxSignalConversionTable)) {
113
ath_hal_printf(ah, "%s: mux %d is invalid!\n",
114
__func__,
115
type);
116
return AH_FALSE;
117
}
118
cfgOutputMux(ah, gpio, MuxSignalConversionTable[type]);
119
120
/* 2 bits per output mode */
121
gpio_shift = gpio << 1;
122
123
/* Always drive, rather than tristate/drive low/drive high */
124
reg = OS_REG_READ(ah, AR_GPIO_OE_OUT);
125
reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift);
126
reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift;
127
OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg);
128
129
return AH_TRUE;
130
#undef N
131
}
132
133
/*
134
* Configure GPIO Input lines
135
*/
136
HAL_BOOL
137
ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
138
{
139
uint32_t gpio_shift, reg;
140
141
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
142
143
HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d\n", __func__, gpio);
144
145
/* TODO: configure input mux for AR5416 */
146
/* If configured as input, set output to tristate */
147
gpio_shift = gpio << 1;
148
149
reg = OS_REG_READ(ah, AR_GPIO_OE_OUT);
150
reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift);
151
reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift;
152
OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg);
153
154
return AH_TRUE;
155
}
156
157
/*
158
* Once configured for I/O - set output lines
159
*/
160
HAL_BOOL
161
ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
162
{
163
uint32_t reg;
164
165
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
166
HALDEBUG(ah, HAL_DEBUG_GPIO,
167
"%s: gpio=%d, val=%d\n", __func__, gpio, val);
168
169
reg = OS_REG_READ(ah, AR_GPIO_IN_OUT);
170
if (val & 1)
171
reg |= AR_GPIO_BIT(gpio);
172
else
173
reg &= ~AR_GPIO_BIT(gpio);
174
OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg);
175
return AH_TRUE;
176
}
177
178
/*
179
* Once configured for I/O - get input lines
180
*/
181
uint32_t
182
ar5416GpioGet(struct ath_hal *ah, uint32_t gpio)
183
{
184
uint32_t bits;
185
186
if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins)
187
return 0xffffffff;
188
/*
189
* Read output value for all gpio's, shift it,
190
* and verify whether the specific bit is set.
191
*/
192
if (AR_SREV_KIWI_10_OR_LATER(ah))
193
bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9287_GPIO_IN_VAL);
194
if (AR_SREV_KITE_10_OR_LATER(ah))
195
bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL);
196
else if (AR_SREV_MERLIN_10_OR_LATER(ah))
197
bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL);
198
else
199
bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL);
200
return ((bits & AR_GPIO_BIT(gpio)) != 0);
201
}
202
203
/*
204
* Set the GPIO Interrupt Sync and Async interrupts are both set/cleared.
205
* Async GPIO interrupts may not be raised when the chip is put to sleep.
206
*/
207
void
208
ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
209
{
210
uint32_t val, mask;
211
212
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
213
HALDEBUG(ah, HAL_DEBUG_GPIO,
214
"%s: gpio=%d, ilevel=%d\n", __func__, gpio, ilevel);
215
216
if (ilevel == HAL_GPIO_INTR_DISABLE) {
217
val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE),
218
AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio);
219
OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE,
220
AR_INTR_ASYNC_ENABLE_GPIO, val);
221
222
mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK),
223
AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio);
224
OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK,
225
AR_INTR_ASYNC_MASK_GPIO, mask);
226
227
/* Clear synchronous GPIO interrupt registers and pending interrupt flag */
228
val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE),
229
AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio);
230
OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE,
231
AR_INTR_SYNC_ENABLE_GPIO, val);
232
233
mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK),
234
AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio);
235
OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK,
236
AR_INTR_SYNC_MASK_GPIO, mask);
237
238
val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE),
239
AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);
240
OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE,
241
AR_INTR_SYNC_ENABLE_GPIO, val);
242
} else {
243
val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL),
244
AR_GPIO_INTR_POL_VAL);
245
if (ilevel == HAL_GPIO_INTR_HIGH) {
246
/* 0 == interrupt on pin high */
247
val &= ~AR_GPIO_BIT(gpio);
248
} else if (ilevel == HAL_GPIO_INTR_LOW) {
249
/* 1 == interrupt on pin low */
250
val |= AR_GPIO_BIT(gpio);
251
}
252
OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL,
253
AR_GPIO_INTR_POL_VAL, val);
254
255
/* Change the interrupt mask. */
256
val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE),
257
AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);
258
OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE,
259
AR_INTR_ASYNC_ENABLE_GPIO, val);
260
261
mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK),
262
AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio);
263
OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK,
264
AR_INTR_ASYNC_MASK_GPIO, mask);
265
266
/* Set synchronous GPIO interrupt registers as well */
267
val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE),
268
AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);
269
OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE,
270
AR_INTR_SYNC_ENABLE_GPIO, val);
271
272
mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK),
273
AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio);
274
OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK,
275
AR_INTR_SYNC_MASK_GPIO, mask);
276
}
277
AH5416(ah)->ah_gpioMask = mask; /* for ar5416SetInterrupts */
278
}
279
280