1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Lochnagar pin and GPIO control |
4 | * |
5 | * Copyright (c) 2017-2018 Cirrus Logic, Inc. and |
6 | * Cirrus Logic International Semiconductor Ltd. |
7 | * |
8 | * Author: Charles Keepax <ckeepax@opensource.cirrus.com> |
9 | */ |
10 | |
11 | #include <linux/err.h> |
12 | #include <linux/errno.h> |
13 | #include <linux/gpio/driver.h> |
14 | #include <linux/module.h> |
15 | #include <linux/of.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/regmap.h> |
18 | |
19 | #include <linux/pinctrl/consumer.h> |
20 | #include <linux/pinctrl/pinconf-generic.h> |
21 | #include <linux/pinctrl/pinconf.h> |
22 | #include <linux/pinctrl/pinctrl.h> |
23 | #include <linux/pinctrl/pinmux.h> |
24 | |
25 | #include <linux/mfd/lochnagar.h> |
26 | #include <linux/mfd/lochnagar1_regs.h> |
27 | #include <linux/mfd/lochnagar2_regs.h> |
28 | |
29 | #include <dt-bindings/pinctrl/lochnagar.h> |
30 | |
31 | #include "../pinctrl-utils.h" |
32 | |
33 | #define LN2_NUM_GPIO_CHANNELS 16 |
34 | |
35 | #define LN_CDC_AIF1_STR "codec-aif1" |
36 | #define LN_CDC_AIF2_STR "codec-aif2" |
37 | #define LN_CDC_AIF3_STR "codec-aif3" |
38 | #define LN_DSP_AIF1_STR "dsp-aif1" |
39 | #define LN_DSP_AIF2_STR "dsp-aif2" |
40 | #define LN_PSIA1_STR "psia1" |
41 | #define LN_PSIA2_STR "psia2" |
42 | #define LN_GF_AIF1_STR "gf-aif1" |
43 | #define LN_GF_AIF2_STR "gf-aif2" |
44 | #define LN_GF_AIF3_STR "gf-aif3" |
45 | #define LN_GF_AIF4_STR "gf-aif4" |
46 | #define LN_SPDIF_AIF_STR "spdif-aif" |
47 | #define LN_USB_AIF1_STR "usb-aif1" |
48 | #define LN_USB_AIF2_STR "usb-aif2" |
49 | #define LN_ADAT_AIF_STR "adat-aif" |
50 | #define LN_SOUNDCARD_AIF_STR "soundcard-aif" |
51 | |
52 | #define LN_PIN_GPIO(REV, ID, NAME, REG, SHIFT, INVERT) \ |
53 | static const struct lochnagar_pin lochnagar##REV##_##ID##_pin = { \ |
54 | .name = NAME, .type = LN_PTYPE_GPIO, .reg = LOCHNAGAR##REV##_##REG, \ |
55 | .shift = LOCHNAGAR##REV##_##SHIFT##_SHIFT, .invert = INVERT, \ |
56 | } |
57 | |
58 | #define LN_PIN_SAIF(REV, ID, NAME) \ |
59 | static const struct lochnagar_pin lochnagar##REV##_##ID##_pin = \ |
60 | { .name = NAME, .type = LN_PTYPE_AIF, } |
61 | |
62 | #define LN_PIN_AIF(REV, ID) \ |
63 | LN_PIN_SAIF(REV, ID##_BCLK, LN_##ID##_STR"-bclk"); \ |
64 | LN_PIN_SAIF(REV, ID##_LRCLK, LN_##ID##_STR"-lrclk"); \ |
65 | LN_PIN_SAIF(REV, ID##_RXDAT, LN_##ID##_STR"-rxdat"); \ |
66 | LN_PIN_SAIF(REV, ID##_TXDAT, LN_##ID##_STR"-txdat") |
67 | |
68 | #define LN1_PIN_GPIO(ID, NAME, REG, SHIFT, INVERT) \ |
69 | LN_PIN_GPIO(1, ID, NAME, REG, SHIFT, INVERT) |
70 | |
71 | #define LN1_PIN_MUX(ID, NAME) \ |
72 | static const struct lochnagar_pin lochnagar1_##ID##_pin = \ |
73 | { .name = NAME, .type = LN_PTYPE_MUX, .reg = LOCHNAGAR1_##ID, } |
74 | |
75 | #define LN1_PIN_AIF(ID) LN_PIN_AIF(1, ID) |
76 | |
77 | #define LN2_PIN_GPIO(ID, NAME, REG, SHIFT, INVERT) \ |
78 | LN_PIN_GPIO(2, ID, NAME, REG, SHIFT, INVERT) |
79 | |
80 | #define LN2_PIN_MUX(ID, NAME) \ |
81 | static const struct lochnagar_pin lochnagar2_##ID##_pin = \ |
82 | { .name = NAME, .type = LN_PTYPE_MUX, .reg = LOCHNAGAR2_GPIO_##ID, } |
83 | |
84 | #define LN2_PIN_AIF(ID) LN_PIN_AIF(2, ID) |
85 | |
86 | #define LN2_PIN_GAI(ID) \ |
87 | LN2_PIN_MUX(ID##_BCLK, LN_##ID##_STR"-bclk"); \ |
88 | LN2_PIN_MUX(ID##_LRCLK, LN_##ID##_STR"-lrclk"); \ |
89 | LN2_PIN_MUX(ID##_RXDAT, LN_##ID##_STR"-rxdat"); \ |
90 | LN2_PIN_MUX(ID##_TXDAT, LN_##ID##_STR"-txdat") |
91 | |
92 | #define LN_PIN(REV, ID) [LOCHNAGAR##REV##_PIN_##ID] = { \ |
93 | .number = LOCHNAGAR##REV##_PIN_##ID, \ |
94 | .name = lochnagar##REV##_##ID##_pin.name, \ |
95 | .drv_data = (void *)&lochnagar##REV##_##ID##_pin, \ |
96 | } |
97 | |
98 | #define LN1_PIN(ID) LN_PIN(1, ID) |
99 | #define LN2_PIN(ID) LN_PIN(2, ID) |
100 | |
101 | #define LN_PINS(REV, ID) \ |
102 | LN_PIN(REV, ID##_BCLK), LN_PIN(REV, ID##_LRCLK), \ |
103 | LN_PIN(REV, ID##_RXDAT), LN_PIN(REV, ID##_TXDAT) |
104 | |
105 | #define LN1_PINS(ID) LN_PINS(1, ID) |
106 | #define LN2_PINS(ID) LN_PINS(2, ID) |
107 | |
108 | enum { |
109 | LOCHNAGAR1_PIN_GF_GPIO2 = LOCHNAGAR1_PIN_NUM_GPIOS, |
110 | LOCHNAGAR1_PIN_GF_GPIO3, |
111 | LOCHNAGAR1_PIN_GF_GPIO7, |
112 | LOCHNAGAR1_PIN_LED1, |
113 | LOCHNAGAR1_PIN_LED2, |
114 | LOCHNAGAR1_PIN_CDC_AIF1_BCLK, |
115 | LOCHNAGAR1_PIN_CDC_AIF1_LRCLK, |
116 | LOCHNAGAR1_PIN_CDC_AIF1_RXDAT, |
117 | LOCHNAGAR1_PIN_CDC_AIF1_TXDAT, |
118 | LOCHNAGAR1_PIN_CDC_AIF2_BCLK, |
119 | LOCHNAGAR1_PIN_CDC_AIF2_LRCLK, |
120 | LOCHNAGAR1_PIN_CDC_AIF2_RXDAT, |
121 | LOCHNAGAR1_PIN_CDC_AIF2_TXDAT, |
122 | LOCHNAGAR1_PIN_CDC_AIF3_BCLK, |
123 | LOCHNAGAR1_PIN_CDC_AIF3_LRCLK, |
124 | LOCHNAGAR1_PIN_CDC_AIF3_RXDAT, |
125 | LOCHNAGAR1_PIN_CDC_AIF3_TXDAT, |
126 | LOCHNAGAR1_PIN_DSP_AIF1_BCLK, |
127 | LOCHNAGAR1_PIN_DSP_AIF1_LRCLK, |
128 | LOCHNAGAR1_PIN_DSP_AIF1_RXDAT, |
129 | LOCHNAGAR1_PIN_DSP_AIF1_TXDAT, |
130 | LOCHNAGAR1_PIN_DSP_AIF2_BCLK, |
131 | LOCHNAGAR1_PIN_DSP_AIF2_LRCLK, |
132 | LOCHNAGAR1_PIN_DSP_AIF2_RXDAT, |
133 | LOCHNAGAR1_PIN_DSP_AIF2_TXDAT, |
134 | LOCHNAGAR1_PIN_PSIA1_BCLK, |
135 | LOCHNAGAR1_PIN_PSIA1_LRCLK, |
136 | LOCHNAGAR1_PIN_PSIA1_RXDAT, |
137 | LOCHNAGAR1_PIN_PSIA1_TXDAT, |
138 | LOCHNAGAR1_PIN_PSIA2_BCLK, |
139 | LOCHNAGAR1_PIN_PSIA2_LRCLK, |
140 | LOCHNAGAR1_PIN_PSIA2_RXDAT, |
141 | LOCHNAGAR1_PIN_PSIA2_TXDAT, |
142 | LOCHNAGAR1_PIN_SPDIF_AIF_BCLK, |
143 | LOCHNAGAR1_PIN_SPDIF_AIF_LRCLK, |
144 | LOCHNAGAR1_PIN_SPDIF_AIF_RXDAT, |
145 | LOCHNAGAR1_PIN_SPDIF_AIF_TXDAT, |
146 | LOCHNAGAR1_PIN_GF_AIF3_BCLK, |
147 | LOCHNAGAR1_PIN_GF_AIF3_RXDAT, |
148 | LOCHNAGAR1_PIN_GF_AIF3_LRCLK, |
149 | LOCHNAGAR1_PIN_GF_AIF3_TXDAT, |
150 | LOCHNAGAR1_PIN_GF_AIF4_BCLK, |
151 | LOCHNAGAR1_PIN_GF_AIF4_RXDAT, |
152 | LOCHNAGAR1_PIN_GF_AIF4_LRCLK, |
153 | LOCHNAGAR1_PIN_GF_AIF4_TXDAT, |
154 | LOCHNAGAR1_PIN_GF_AIF1_BCLK, |
155 | LOCHNAGAR1_PIN_GF_AIF1_RXDAT, |
156 | LOCHNAGAR1_PIN_GF_AIF1_LRCLK, |
157 | LOCHNAGAR1_PIN_GF_AIF1_TXDAT, |
158 | LOCHNAGAR1_PIN_GF_AIF2_BCLK, |
159 | LOCHNAGAR1_PIN_GF_AIF2_RXDAT, |
160 | LOCHNAGAR1_PIN_GF_AIF2_LRCLK, |
161 | LOCHNAGAR1_PIN_GF_AIF2_TXDAT, |
162 | |
163 | LOCHNAGAR2_PIN_SPDIF_AIF_BCLK = LOCHNAGAR2_PIN_NUM_GPIOS, |
164 | LOCHNAGAR2_PIN_SPDIF_AIF_LRCLK, |
165 | LOCHNAGAR2_PIN_SPDIF_AIF_RXDAT, |
166 | LOCHNAGAR2_PIN_SPDIF_AIF_TXDAT, |
167 | LOCHNAGAR2_PIN_USB_AIF1_BCLK, |
168 | LOCHNAGAR2_PIN_USB_AIF1_LRCLK, |
169 | LOCHNAGAR2_PIN_USB_AIF1_RXDAT, |
170 | LOCHNAGAR2_PIN_USB_AIF1_TXDAT, |
171 | LOCHNAGAR2_PIN_USB_AIF2_BCLK, |
172 | LOCHNAGAR2_PIN_USB_AIF2_LRCLK, |
173 | LOCHNAGAR2_PIN_USB_AIF2_RXDAT, |
174 | LOCHNAGAR2_PIN_USB_AIF2_TXDAT, |
175 | LOCHNAGAR2_PIN_ADAT_AIF_BCLK, |
176 | LOCHNAGAR2_PIN_ADAT_AIF_LRCLK, |
177 | LOCHNAGAR2_PIN_ADAT_AIF_RXDAT, |
178 | LOCHNAGAR2_PIN_ADAT_AIF_TXDAT, |
179 | LOCHNAGAR2_PIN_SOUNDCARD_AIF_BCLK, |
180 | LOCHNAGAR2_PIN_SOUNDCARD_AIF_LRCLK, |
181 | LOCHNAGAR2_PIN_SOUNDCARD_AIF_RXDAT, |
182 | LOCHNAGAR2_PIN_SOUNDCARD_AIF_TXDAT, |
183 | }; |
184 | |
185 | enum lochnagar_pin_type { |
186 | LN_PTYPE_GPIO, |
187 | LN_PTYPE_MUX, |
188 | LN_PTYPE_AIF, |
189 | LN_PTYPE_COUNT, |
190 | }; |
191 | |
192 | struct lochnagar_pin { |
193 | const char name[20]; |
194 | |
195 | enum lochnagar_pin_type type; |
196 | |
197 | unsigned int reg; |
198 | int shift; |
199 | bool invert; |
200 | }; |
201 | |
202 | LN1_PIN_GPIO(CDC_RESET, "codec-reset" , RST, CDC_RESET, 1); |
203 | LN1_PIN_GPIO(DSP_RESET, "dsp-reset" , RST, DSP_RESET, 1); |
204 | LN1_PIN_GPIO(CDC_CIF1MODE, "codec-cif1mode" , I2C_CTRL, CDC_CIF_MODE, 0); |
205 | LN1_PIN_MUX(GF_GPIO2, "gf-gpio2" ); |
206 | LN1_PIN_MUX(GF_GPIO3, "gf-gpio3" ); |
207 | LN1_PIN_MUX(GF_GPIO7, "gf-gpio7" ); |
208 | LN1_PIN_MUX(LED1, "led1" ); |
209 | LN1_PIN_MUX(LED2, "led2" ); |
210 | LN1_PIN_AIF(CDC_AIF1); |
211 | LN1_PIN_AIF(CDC_AIF2); |
212 | LN1_PIN_AIF(CDC_AIF3); |
213 | LN1_PIN_AIF(DSP_AIF1); |
214 | LN1_PIN_AIF(DSP_AIF2); |
215 | LN1_PIN_AIF(PSIA1); |
216 | LN1_PIN_AIF(PSIA2); |
217 | LN1_PIN_AIF(SPDIF_AIF); |
218 | LN1_PIN_AIF(GF_AIF1); |
219 | LN1_PIN_AIF(GF_AIF2); |
220 | LN1_PIN_AIF(GF_AIF3); |
221 | LN1_PIN_AIF(GF_AIF4); |
222 | |
223 | LN2_PIN_GPIO(CDC_RESET, "codec-reset" , MINICARD_RESETS, CDC_RESET, 1); |
224 | LN2_PIN_GPIO(DSP_RESET, "dsp-reset" , MINICARD_RESETS, DSP_RESET, 1); |
225 | LN2_PIN_GPIO(CDC_CIF1MODE, "codec-cif1mode" , COMMS_CTRL4, CDC_CIF1MODE, 0); |
226 | LN2_PIN_GPIO(CDC_LDOENA, "codec-ldoena" , POWER_CTRL, PWR_ENA, 0); |
227 | LN2_PIN_GPIO(SPDIF_HWMODE, "spdif-hwmode" , SPDIF_CTRL, SPDIF_HWMODE, 0); |
228 | LN2_PIN_GPIO(SPDIF_RESET, "spdif-reset" , SPDIF_CTRL, SPDIF_RESET, 1); |
229 | LN2_PIN_MUX(FPGA_GPIO1, "fpga-gpio1" ); |
230 | LN2_PIN_MUX(FPGA_GPIO2, "fpga-gpio2" ); |
231 | LN2_PIN_MUX(FPGA_GPIO3, "fpga-gpio3" ); |
232 | LN2_PIN_MUX(FPGA_GPIO4, "fpga-gpio4" ); |
233 | LN2_PIN_MUX(FPGA_GPIO5, "fpga-gpio5" ); |
234 | LN2_PIN_MUX(FPGA_GPIO6, "fpga-gpio6" ); |
235 | LN2_PIN_MUX(CDC_GPIO1, "codec-gpio1" ); |
236 | LN2_PIN_MUX(CDC_GPIO2, "codec-gpio2" ); |
237 | LN2_PIN_MUX(CDC_GPIO3, "codec-gpio3" ); |
238 | LN2_PIN_MUX(CDC_GPIO4, "codec-gpio4" ); |
239 | LN2_PIN_MUX(CDC_GPIO5, "codec-gpio5" ); |
240 | LN2_PIN_MUX(CDC_GPIO6, "codec-gpio6" ); |
241 | LN2_PIN_MUX(CDC_GPIO7, "codec-gpio7" ); |
242 | LN2_PIN_MUX(CDC_GPIO8, "codec-gpio8" ); |
243 | LN2_PIN_MUX(DSP_GPIO1, "dsp-gpio1" ); |
244 | LN2_PIN_MUX(DSP_GPIO2, "dsp-gpio2" ); |
245 | LN2_PIN_MUX(DSP_GPIO3, "dsp-gpio3" ); |
246 | LN2_PIN_MUX(DSP_GPIO4, "dsp-gpio4" ); |
247 | LN2_PIN_MUX(DSP_GPIO5, "dsp-gpio5" ); |
248 | LN2_PIN_MUX(DSP_GPIO6, "dsp-gpio6" ); |
249 | LN2_PIN_MUX(GF_GPIO2, "gf-gpio2" ); |
250 | LN2_PIN_MUX(GF_GPIO3, "gf-gpio3" ); |
251 | LN2_PIN_MUX(GF_GPIO7, "gf-gpio7" ); |
252 | LN2_PIN_MUX(DSP_UART1_RX, "dsp-uart1-rx" ); |
253 | LN2_PIN_MUX(DSP_UART1_TX, "dsp-uart1-tx" ); |
254 | LN2_PIN_MUX(DSP_UART2_RX, "dsp-uart2-rx" ); |
255 | LN2_PIN_MUX(DSP_UART2_TX, "dsp-uart2-tx" ); |
256 | LN2_PIN_MUX(GF_UART2_RX, "gf-uart2-rx" ); |
257 | LN2_PIN_MUX(GF_UART2_TX, "gf-uart2-tx" ); |
258 | LN2_PIN_MUX(USB_UART_RX, "usb-uart-rx" ); |
259 | LN2_PIN_MUX(CDC_PDMCLK1, "codec-pdmclk1" ); |
260 | LN2_PIN_MUX(CDC_PDMDAT1, "codec-pdmdat1" ); |
261 | LN2_PIN_MUX(CDC_PDMCLK2, "codec-pdmclk2" ); |
262 | LN2_PIN_MUX(CDC_PDMDAT2, "codec-pdmdat2" ); |
263 | LN2_PIN_MUX(CDC_DMICCLK1, "codec-dmicclk1" ); |
264 | LN2_PIN_MUX(CDC_DMICDAT1, "codec-dmicdat1" ); |
265 | LN2_PIN_MUX(CDC_DMICCLK2, "codec-dmicclk2" ); |
266 | LN2_PIN_MUX(CDC_DMICDAT2, "codec-dmicdat2" ); |
267 | LN2_PIN_MUX(CDC_DMICCLK3, "codec-dmicclk3" ); |
268 | LN2_PIN_MUX(CDC_DMICDAT3, "codec-dmicdat3" ); |
269 | LN2_PIN_MUX(CDC_DMICCLK4, "codec-dmicclk4" ); |
270 | LN2_PIN_MUX(CDC_DMICDAT4, "codec-dmicdat4" ); |
271 | LN2_PIN_MUX(DSP_DMICCLK1, "dsp-dmicclk1" ); |
272 | LN2_PIN_MUX(DSP_DMICDAT1, "dsp-dmicdat1" ); |
273 | LN2_PIN_MUX(DSP_DMICCLK2, "dsp-dmicclk2" ); |
274 | LN2_PIN_MUX(DSP_DMICDAT2, "dsp-dmicdat2" ); |
275 | LN2_PIN_MUX(I2C2_SCL, "i2c2-scl" ); |
276 | LN2_PIN_MUX(I2C2_SDA, "i2c2-sda" ); |
277 | LN2_PIN_MUX(I2C3_SCL, "i2c3-scl" ); |
278 | LN2_PIN_MUX(I2C3_SDA, "i2c3-sda" ); |
279 | LN2_PIN_MUX(I2C4_SCL, "i2c4-scl" ); |
280 | LN2_PIN_MUX(I2C4_SDA, "i2c4-sda" ); |
281 | LN2_PIN_MUX(DSP_STANDBY, "dsp-standby" ); |
282 | LN2_PIN_MUX(CDC_MCLK1, "codec-mclk1" ); |
283 | LN2_PIN_MUX(CDC_MCLK2, "codec-mclk2" ); |
284 | LN2_PIN_MUX(DSP_CLKIN, "dsp-clkin" ); |
285 | LN2_PIN_MUX(PSIA1_MCLK, "psia1-mclk" ); |
286 | LN2_PIN_MUX(PSIA2_MCLK, "psia2-mclk" ); |
287 | LN2_PIN_MUX(GF_GPIO1, "gf-gpio1" ); |
288 | LN2_PIN_MUX(GF_GPIO5, "gf-gpio5" ); |
289 | LN2_PIN_MUX(DSP_GPIO20, "dsp-gpio20" ); |
290 | LN2_PIN_GAI(CDC_AIF1); |
291 | LN2_PIN_GAI(CDC_AIF2); |
292 | LN2_PIN_GAI(CDC_AIF3); |
293 | LN2_PIN_GAI(DSP_AIF1); |
294 | LN2_PIN_GAI(DSP_AIF2); |
295 | LN2_PIN_GAI(PSIA1); |
296 | LN2_PIN_GAI(PSIA2); |
297 | LN2_PIN_GAI(GF_AIF1); |
298 | LN2_PIN_GAI(GF_AIF2); |
299 | LN2_PIN_GAI(GF_AIF3); |
300 | LN2_PIN_GAI(GF_AIF4); |
301 | LN2_PIN_AIF(SPDIF_AIF); |
302 | LN2_PIN_AIF(USB_AIF1); |
303 | LN2_PIN_AIF(USB_AIF2); |
304 | LN2_PIN_AIF(ADAT_AIF); |
305 | LN2_PIN_AIF(SOUNDCARD_AIF); |
306 | |
307 | static const struct pinctrl_pin_desc lochnagar1_pins[] = { |
308 | LN1_PIN(CDC_RESET), LN1_PIN(DSP_RESET), LN1_PIN(CDC_CIF1MODE), |
309 | LN1_PIN(GF_GPIO2), LN1_PIN(GF_GPIO3), LN1_PIN(GF_GPIO7), |
310 | LN1_PIN(LED1), LN1_PIN(LED2), |
311 | LN1_PINS(CDC_AIF1), LN1_PINS(CDC_AIF2), LN1_PINS(CDC_AIF3), |
312 | LN1_PINS(DSP_AIF1), LN1_PINS(DSP_AIF2), |
313 | LN1_PINS(PSIA1), LN1_PINS(PSIA2), |
314 | LN1_PINS(SPDIF_AIF), |
315 | LN1_PINS(GF_AIF1), LN1_PINS(GF_AIF2), |
316 | LN1_PINS(GF_AIF3), LN1_PINS(GF_AIF4), |
317 | }; |
318 | |
319 | static const struct pinctrl_pin_desc lochnagar2_pins[] = { |
320 | LN2_PIN(CDC_RESET), LN2_PIN(DSP_RESET), LN2_PIN(CDC_CIF1MODE), |
321 | LN2_PIN(CDC_LDOENA), |
322 | LN2_PIN(SPDIF_HWMODE), LN2_PIN(SPDIF_RESET), |
323 | LN2_PIN(FPGA_GPIO1), LN2_PIN(FPGA_GPIO2), LN2_PIN(FPGA_GPIO3), |
324 | LN2_PIN(FPGA_GPIO4), LN2_PIN(FPGA_GPIO5), LN2_PIN(FPGA_GPIO6), |
325 | LN2_PIN(CDC_GPIO1), LN2_PIN(CDC_GPIO2), LN2_PIN(CDC_GPIO3), |
326 | LN2_PIN(CDC_GPIO4), LN2_PIN(CDC_GPIO5), LN2_PIN(CDC_GPIO6), |
327 | LN2_PIN(CDC_GPIO7), LN2_PIN(CDC_GPIO8), |
328 | LN2_PIN(DSP_GPIO1), LN2_PIN(DSP_GPIO2), LN2_PIN(DSP_GPIO3), |
329 | LN2_PIN(DSP_GPIO4), LN2_PIN(DSP_GPIO5), LN2_PIN(DSP_GPIO6), |
330 | LN2_PIN(DSP_GPIO20), |
331 | LN2_PIN(GF_GPIO1), LN2_PIN(GF_GPIO2), LN2_PIN(GF_GPIO3), |
332 | LN2_PIN(GF_GPIO5), LN2_PIN(GF_GPIO7), |
333 | LN2_PINS(CDC_AIF1), LN2_PINS(CDC_AIF2), LN2_PINS(CDC_AIF3), |
334 | LN2_PINS(DSP_AIF1), LN2_PINS(DSP_AIF2), |
335 | LN2_PINS(PSIA1), LN2_PINS(PSIA2), |
336 | LN2_PINS(GF_AIF1), LN2_PINS(GF_AIF2), |
337 | LN2_PINS(GF_AIF3), LN2_PINS(GF_AIF4), |
338 | LN2_PIN(DSP_UART1_RX), LN2_PIN(DSP_UART1_TX), |
339 | LN2_PIN(DSP_UART2_RX), LN2_PIN(DSP_UART2_TX), |
340 | LN2_PIN(GF_UART2_RX), LN2_PIN(GF_UART2_TX), |
341 | LN2_PIN(USB_UART_RX), |
342 | LN2_PIN(CDC_PDMCLK1), LN2_PIN(CDC_PDMDAT1), |
343 | LN2_PIN(CDC_PDMCLK2), LN2_PIN(CDC_PDMDAT2), |
344 | LN2_PIN(CDC_DMICCLK1), LN2_PIN(CDC_DMICDAT1), |
345 | LN2_PIN(CDC_DMICCLK2), LN2_PIN(CDC_DMICDAT2), |
346 | LN2_PIN(CDC_DMICCLK3), LN2_PIN(CDC_DMICDAT3), |
347 | LN2_PIN(CDC_DMICCLK4), LN2_PIN(CDC_DMICDAT4), |
348 | LN2_PIN(DSP_DMICCLK1), LN2_PIN(DSP_DMICDAT1), |
349 | LN2_PIN(DSP_DMICCLK2), LN2_PIN(DSP_DMICDAT2), |
350 | LN2_PIN(I2C2_SCL), LN2_PIN(I2C2_SDA), |
351 | LN2_PIN(I2C3_SCL), LN2_PIN(I2C3_SDA), |
352 | LN2_PIN(I2C4_SCL), LN2_PIN(I2C4_SDA), |
353 | LN2_PIN(DSP_STANDBY), |
354 | LN2_PIN(CDC_MCLK1), LN2_PIN(CDC_MCLK2), |
355 | LN2_PIN(DSP_CLKIN), |
356 | LN2_PIN(PSIA1_MCLK), LN2_PIN(PSIA2_MCLK), |
357 | LN2_PINS(SPDIF_AIF), |
358 | LN2_PINS(USB_AIF1), LN2_PINS(USB_AIF2), |
359 | LN2_PINS(ADAT_AIF), |
360 | LN2_PINS(SOUNDCARD_AIF), |
361 | }; |
362 | |
363 | #define LN_AIF_PINS(REV, ID) \ |
364 | LOCHNAGAR##REV##_PIN_##ID##_BCLK, \ |
365 | LOCHNAGAR##REV##_PIN_##ID##_LRCLK, \ |
366 | LOCHNAGAR##REV##_PIN_##ID##_TXDAT, \ |
367 | LOCHNAGAR##REV##_PIN_##ID##_RXDAT, |
368 | |
369 | #define LN1_AIF(ID, CTRL) \ |
370 | static const struct lochnagar_aif lochnagar1_##ID##_aif = { \ |
371 | .name = LN_##ID##_STR, \ |
372 | .pins = { LN_AIF_PINS(1, ID) }, \ |
373 | .src_reg = LOCHNAGAR1_##ID##_SEL, \ |
374 | .src_mask = LOCHNAGAR1_SRC_MASK, \ |
375 | .ctrl_reg = LOCHNAGAR1_##CTRL, \ |
376 | .ena_mask = LOCHNAGAR1_##ID##_ENA_MASK, \ |
377 | .master_mask = LOCHNAGAR1_##ID##_LRCLK_DIR_MASK | \ |
378 | LOCHNAGAR1_##ID##_BCLK_DIR_MASK, \ |
379 | } |
380 | |
381 | #define LN2_AIF(ID) \ |
382 | static const struct lochnagar_aif lochnagar2_##ID##_aif = { \ |
383 | .name = LN_##ID##_STR, \ |
384 | .pins = { LN_AIF_PINS(2, ID) }, \ |
385 | .src_reg = LOCHNAGAR2_##ID##_CTRL, \ |
386 | .src_mask = LOCHNAGAR2_AIF_SRC_MASK, \ |
387 | .ctrl_reg = LOCHNAGAR2_##ID##_CTRL, \ |
388 | .ena_mask = LOCHNAGAR2_AIF_ENA_MASK, \ |
389 | .master_mask = LOCHNAGAR2_AIF_LRCLK_DIR_MASK | \ |
390 | LOCHNAGAR2_AIF_BCLK_DIR_MASK, \ |
391 | } |
392 | |
393 | struct lochnagar_aif { |
394 | const char name[16]; |
395 | |
396 | unsigned int pins[4]; |
397 | |
398 | u16 src_reg; |
399 | u16 src_mask; |
400 | |
401 | u16 ctrl_reg; |
402 | u16 ena_mask; |
403 | u16 master_mask; |
404 | }; |
405 | |
406 | LN1_AIF(CDC_AIF1, CDC_AIF_CTRL1); |
407 | LN1_AIF(CDC_AIF2, CDC_AIF_CTRL1); |
408 | LN1_AIF(CDC_AIF3, CDC_AIF_CTRL2); |
409 | LN1_AIF(DSP_AIF1, DSP_AIF); |
410 | LN1_AIF(DSP_AIF2, DSP_AIF); |
411 | LN1_AIF(PSIA1, PSIA_AIF); |
412 | LN1_AIF(PSIA2, PSIA_AIF); |
413 | LN1_AIF(GF_AIF1, GF_AIF1); |
414 | LN1_AIF(GF_AIF2, GF_AIF2); |
415 | LN1_AIF(GF_AIF3, GF_AIF1); |
416 | LN1_AIF(GF_AIF4, GF_AIF2); |
417 | LN1_AIF(SPDIF_AIF, EXT_AIF_CTRL); |
418 | |
419 | LN2_AIF(CDC_AIF1); |
420 | LN2_AIF(CDC_AIF2); |
421 | LN2_AIF(CDC_AIF3); |
422 | LN2_AIF(DSP_AIF1); |
423 | LN2_AIF(DSP_AIF2); |
424 | LN2_AIF(PSIA1); |
425 | LN2_AIF(PSIA2); |
426 | LN2_AIF(GF_AIF1); |
427 | LN2_AIF(GF_AIF2); |
428 | LN2_AIF(GF_AIF3); |
429 | LN2_AIF(GF_AIF4); |
430 | LN2_AIF(SPDIF_AIF); |
431 | LN2_AIF(USB_AIF1); |
432 | LN2_AIF(USB_AIF2); |
433 | LN2_AIF(ADAT_AIF); |
434 | LN2_AIF(SOUNDCARD_AIF); |
435 | |
436 | #define LN2_OP_AIF 0x00 |
437 | #define LN2_OP_GPIO 0xFE |
438 | |
439 | #define LN_FUNC(NAME, TYPE, OP) \ |
440 | { .name = NAME, .type = LN_FTYPE_##TYPE, .op = OP } |
441 | |
442 | #define LN_FUNC_PIN(REV, ID, OP) \ |
443 | LN_FUNC(lochnagar##REV##_##ID##_pin.name, PIN, OP) |
444 | |
445 | #define LN1_FUNC_PIN(ID, OP) LN_FUNC_PIN(1, ID, OP) |
446 | #define LN2_FUNC_PIN(ID, OP) LN_FUNC_PIN(2, ID, OP) |
447 | |
448 | #define LN_FUNC_AIF(REV, ID, OP) \ |
449 | LN_FUNC(lochnagar##REV##_##ID##_aif.name, AIF, OP) |
450 | |
451 | #define LN1_FUNC_AIF(ID, OP) LN_FUNC_AIF(1, ID, OP) |
452 | #define LN2_FUNC_AIF(ID, OP) LN_FUNC_AIF(2, ID, OP) |
453 | |
454 | #define LN2_FUNC_GAI(ID, OP, BOP, LROP, RXOP, TXOP) \ |
455 | LN2_FUNC_AIF(ID, OP), \ |
456 | LN_FUNC(lochnagar2_##ID##_BCLK_pin.name, PIN, BOP), \ |
457 | LN_FUNC(lochnagar2_##ID##_LRCLK_pin.name, PIN, LROP), \ |
458 | LN_FUNC(lochnagar2_##ID##_RXDAT_pin.name, PIN, RXOP), \ |
459 | LN_FUNC(lochnagar2_##ID##_TXDAT_pin.name, PIN, TXOP) |
460 | |
461 | enum lochnagar_func_type { |
462 | LN_FTYPE_PIN, |
463 | LN_FTYPE_AIF, |
464 | LN_FTYPE_COUNT, |
465 | }; |
466 | |
467 | struct lochnagar_func { |
468 | const char * const name; |
469 | |
470 | enum lochnagar_func_type type; |
471 | |
472 | u8 op; |
473 | }; |
474 | |
475 | static const struct lochnagar_func lochnagar1_funcs[] = { |
476 | LN_FUNC("dsp-gpio1" , PIN, 0x01), |
477 | LN_FUNC("dsp-gpio2" , PIN, 0x02), |
478 | LN_FUNC("dsp-gpio3" , PIN, 0x03), |
479 | LN_FUNC("codec-gpio1" , PIN, 0x04), |
480 | LN_FUNC("codec-gpio2" , PIN, 0x05), |
481 | LN_FUNC("codec-gpio3" , PIN, 0x06), |
482 | LN_FUNC("codec-gpio4" , PIN, 0x07), |
483 | LN_FUNC("codec-gpio5" , PIN, 0x08), |
484 | LN_FUNC("codec-gpio6" , PIN, 0x09), |
485 | LN_FUNC("codec-gpio7" , PIN, 0x0A), |
486 | LN_FUNC("codec-gpio8" , PIN, 0x0B), |
487 | LN1_FUNC_PIN(GF_GPIO2, 0x0C), |
488 | LN1_FUNC_PIN(GF_GPIO3, 0x0D), |
489 | LN1_FUNC_PIN(GF_GPIO7, 0x0E), |
490 | |
491 | LN1_FUNC_AIF(SPDIF_AIF, 0x01), |
492 | LN1_FUNC_AIF(PSIA1, 0x02), |
493 | LN1_FUNC_AIF(PSIA2, 0x03), |
494 | LN1_FUNC_AIF(CDC_AIF1, 0x04), |
495 | LN1_FUNC_AIF(CDC_AIF2, 0x05), |
496 | LN1_FUNC_AIF(CDC_AIF3, 0x06), |
497 | LN1_FUNC_AIF(DSP_AIF1, 0x07), |
498 | LN1_FUNC_AIF(DSP_AIF2, 0x08), |
499 | LN1_FUNC_AIF(GF_AIF3, 0x09), |
500 | LN1_FUNC_AIF(GF_AIF4, 0x0A), |
501 | LN1_FUNC_AIF(GF_AIF1, 0x0B), |
502 | LN1_FUNC_AIF(GF_AIF2, 0x0C), |
503 | }; |
504 | |
505 | static const struct lochnagar_func lochnagar2_funcs[] = { |
506 | LN_FUNC("aif" , PIN, LN2_OP_AIF), |
507 | LN2_FUNC_PIN(FPGA_GPIO1, 0x01), |
508 | LN2_FUNC_PIN(FPGA_GPIO2, 0x02), |
509 | LN2_FUNC_PIN(FPGA_GPIO3, 0x03), |
510 | LN2_FUNC_PIN(FPGA_GPIO4, 0x04), |
511 | LN2_FUNC_PIN(FPGA_GPIO5, 0x05), |
512 | LN2_FUNC_PIN(FPGA_GPIO6, 0x06), |
513 | LN2_FUNC_PIN(CDC_GPIO1, 0x07), |
514 | LN2_FUNC_PIN(CDC_GPIO2, 0x08), |
515 | LN2_FUNC_PIN(CDC_GPIO3, 0x09), |
516 | LN2_FUNC_PIN(CDC_GPIO4, 0x0A), |
517 | LN2_FUNC_PIN(CDC_GPIO5, 0x0B), |
518 | LN2_FUNC_PIN(CDC_GPIO6, 0x0C), |
519 | LN2_FUNC_PIN(CDC_GPIO7, 0x0D), |
520 | LN2_FUNC_PIN(CDC_GPIO8, 0x0E), |
521 | LN2_FUNC_PIN(DSP_GPIO1, 0x0F), |
522 | LN2_FUNC_PIN(DSP_GPIO2, 0x10), |
523 | LN2_FUNC_PIN(DSP_GPIO3, 0x11), |
524 | LN2_FUNC_PIN(DSP_GPIO4, 0x12), |
525 | LN2_FUNC_PIN(DSP_GPIO5, 0x13), |
526 | LN2_FUNC_PIN(DSP_GPIO6, 0x14), |
527 | LN2_FUNC_PIN(GF_GPIO2, 0x15), |
528 | LN2_FUNC_PIN(GF_GPIO3, 0x16), |
529 | LN2_FUNC_PIN(GF_GPIO7, 0x17), |
530 | LN2_FUNC_PIN(GF_GPIO1, 0x18), |
531 | LN2_FUNC_PIN(GF_GPIO5, 0x19), |
532 | LN2_FUNC_PIN(DSP_GPIO20, 0x1A), |
533 | LN_FUNC("codec-clkout" , PIN, 0x20), |
534 | LN_FUNC("dsp-clkout" , PIN, 0x21), |
535 | LN_FUNC("pmic-32k" , PIN, 0x22), |
536 | LN_FUNC("spdif-clkout" , PIN, 0x23), |
537 | LN_FUNC("clk-12m288" , PIN, 0x24), |
538 | LN_FUNC("clk-11m2986" , PIN, 0x25), |
539 | LN_FUNC("clk-24m576" , PIN, 0x26), |
540 | LN_FUNC("clk-22m5792" , PIN, 0x27), |
541 | LN_FUNC("xmos-mclk" , PIN, 0x29), |
542 | LN_FUNC("gf-clkout1" , PIN, 0x2A), |
543 | LN_FUNC("gf-mclk1" , PIN, 0x2B), |
544 | LN_FUNC("gf-mclk3" , PIN, 0x2C), |
545 | LN_FUNC("gf-mclk2" , PIN, 0x2D), |
546 | LN_FUNC("gf-clkout2" , PIN, 0x2E), |
547 | LN2_FUNC_PIN(CDC_MCLK1, 0x2F), |
548 | LN2_FUNC_PIN(CDC_MCLK2, 0x30), |
549 | LN2_FUNC_PIN(DSP_CLKIN, 0x31), |
550 | LN2_FUNC_PIN(PSIA1_MCLK, 0x32), |
551 | LN2_FUNC_PIN(PSIA2_MCLK, 0x33), |
552 | LN_FUNC("spdif-mclk" , PIN, 0x34), |
553 | LN_FUNC("codec-irq" , PIN, 0x42), |
554 | LN2_FUNC_PIN(CDC_RESET, 0x43), |
555 | LN2_FUNC_PIN(DSP_RESET, 0x44), |
556 | LN_FUNC("dsp-irq" , PIN, 0x45), |
557 | LN2_FUNC_PIN(DSP_STANDBY, 0x46), |
558 | LN2_FUNC_PIN(CDC_PDMCLK1, 0x90), |
559 | LN2_FUNC_PIN(CDC_PDMDAT1, 0x91), |
560 | LN2_FUNC_PIN(CDC_PDMCLK2, 0x92), |
561 | LN2_FUNC_PIN(CDC_PDMDAT2, 0x93), |
562 | LN2_FUNC_PIN(CDC_DMICCLK1, 0xA0), |
563 | LN2_FUNC_PIN(CDC_DMICDAT1, 0xA1), |
564 | LN2_FUNC_PIN(CDC_DMICCLK2, 0xA2), |
565 | LN2_FUNC_PIN(CDC_DMICDAT2, 0xA3), |
566 | LN2_FUNC_PIN(CDC_DMICCLK3, 0xA4), |
567 | LN2_FUNC_PIN(CDC_DMICDAT3, 0xA5), |
568 | LN2_FUNC_PIN(CDC_DMICCLK4, 0xA6), |
569 | LN2_FUNC_PIN(CDC_DMICDAT4, 0xA7), |
570 | LN2_FUNC_PIN(DSP_DMICCLK1, 0xA8), |
571 | LN2_FUNC_PIN(DSP_DMICDAT1, 0xA9), |
572 | LN2_FUNC_PIN(DSP_DMICCLK2, 0xAA), |
573 | LN2_FUNC_PIN(DSP_DMICDAT2, 0xAB), |
574 | LN2_FUNC_PIN(DSP_UART1_RX, 0xC0), |
575 | LN2_FUNC_PIN(DSP_UART1_TX, 0xC1), |
576 | LN2_FUNC_PIN(DSP_UART2_RX, 0xC2), |
577 | LN2_FUNC_PIN(DSP_UART2_TX, 0xC3), |
578 | LN2_FUNC_PIN(GF_UART2_RX, 0xC4), |
579 | LN2_FUNC_PIN(GF_UART2_TX, 0xC5), |
580 | LN2_FUNC_PIN(USB_UART_RX, 0xC6), |
581 | LN_FUNC("usb-uart-tx" , PIN, 0xC7), |
582 | LN2_FUNC_PIN(I2C2_SCL, 0xE0), |
583 | LN2_FUNC_PIN(I2C2_SDA, 0xE1), |
584 | LN2_FUNC_PIN(I2C3_SCL, 0xE2), |
585 | LN2_FUNC_PIN(I2C3_SDA, 0xE3), |
586 | LN2_FUNC_PIN(I2C4_SCL, 0xE4), |
587 | LN2_FUNC_PIN(I2C4_SDA, 0xE5), |
588 | |
589 | LN2_FUNC_AIF(SPDIF_AIF, 0x01), |
590 | LN2_FUNC_GAI(PSIA1, 0x02, 0x50, 0x51, 0x52, 0x53), |
591 | LN2_FUNC_GAI(PSIA2, 0x03, 0x54, 0x55, 0x56, 0x57), |
592 | LN2_FUNC_GAI(CDC_AIF1, 0x04, 0x59, 0x5B, 0x5A, 0x58), |
593 | LN2_FUNC_GAI(CDC_AIF2, 0x05, 0x5D, 0x5F, 0x5E, 0x5C), |
594 | LN2_FUNC_GAI(CDC_AIF3, 0x06, 0x61, 0x62, 0x63, 0x60), |
595 | LN2_FUNC_GAI(DSP_AIF1, 0x07, 0x65, 0x67, 0x66, 0x64), |
596 | LN2_FUNC_GAI(DSP_AIF2, 0x08, 0x69, 0x6B, 0x6A, 0x68), |
597 | LN2_FUNC_GAI(GF_AIF3, 0x09, 0x6D, 0x6F, 0x6C, 0x6E), |
598 | LN2_FUNC_GAI(GF_AIF4, 0x0A, 0x71, 0x73, 0x70, 0x72), |
599 | LN2_FUNC_GAI(GF_AIF1, 0x0B, 0x75, 0x77, 0x74, 0x76), |
600 | LN2_FUNC_GAI(GF_AIF2, 0x0C, 0x79, 0x7B, 0x78, 0x7A), |
601 | LN2_FUNC_AIF(USB_AIF1, 0x0D), |
602 | LN2_FUNC_AIF(USB_AIF2, 0x0E), |
603 | LN2_FUNC_AIF(ADAT_AIF, 0x0F), |
604 | LN2_FUNC_AIF(SOUNDCARD_AIF, 0x10), |
605 | }; |
606 | |
607 | #define LN_GROUP_PIN(REV, ID) { \ |
608 | .name = lochnagar##REV##_##ID##_pin.name, \ |
609 | .type = LN_FTYPE_PIN, \ |
610 | .pins = &lochnagar##REV##_pins[LOCHNAGAR##REV##_PIN_##ID].number, \ |
611 | .npins = 1, \ |
612 | .priv = &lochnagar##REV##_pins[LOCHNAGAR##REV##_PIN_##ID], \ |
613 | } |
614 | |
615 | #define LN_GROUP_AIF(REV, ID) { \ |
616 | .name = lochnagar##REV##_##ID##_aif.name, \ |
617 | .type = LN_FTYPE_AIF, \ |
618 | .pins = lochnagar##REV##_##ID##_aif.pins, \ |
619 | .npins = ARRAY_SIZE(lochnagar##REV##_##ID##_aif.pins), \ |
620 | .priv = &lochnagar##REV##_##ID##_aif, \ |
621 | } |
622 | |
623 | #define LN1_GROUP_PIN(ID) LN_GROUP_PIN(1, ID) |
624 | #define LN2_GROUP_PIN(ID) LN_GROUP_PIN(2, ID) |
625 | |
626 | #define LN1_GROUP_AIF(ID) LN_GROUP_AIF(1, ID) |
627 | #define LN2_GROUP_AIF(ID) LN_GROUP_AIF(2, ID) |
628 | |
629 | #define LN2_GROUP_GAI(ID) \ |
630 | LN2_GROUP_AIF(ID), \ |
631 | LN2_GROUP_PIN(ID##_BCLK), LN2_GROUP_PIN(ID##_LRCLK), \ |
632 | LN2_GROUP_PIN(ID##_RXDAT), LN2_GROUP_PIN(ID##_TXDAT) |
633 | |
634 | struct lochnagar_group { |
635 | const char * const name; |
636 | |
637 | enum lochnagar_func_type type; |
638 | |
639 | const unsigned int *pins; |
640 | unsigned int npins; |
641 | |
642 | const void *priv; |
643 | }; |
644 | |
645 | static const struct lochnagar_group lochnagar1_groups[] = { |
646 | LN1_GROUP_PIN(GF_GPIO2), LN1_GROUP_PIN(GF_GPIO3), |
647 | LN1_GROUP_PIN(GF_GPIO7), |
648 | LN1_GROUP_PIN(LED1), LN1_GROUP_PIN(LED2), |
649 | LN1_GROUP_AIF(CDC_AIF1), LN1_GROUP_AIF(CDC_AIF2), |
650 | LN1_GROUP_AIF(CDC_AIF3), |
651 | LN1_GROUP_AIF(DSP_AIF1), LN1_GROUP_AIF(DSP_AIF2), |
652 | LN1_GROUP_AIF(PSIA1), LN1_GROUP_AIF(PSIA2), |
653 | LN1_GROUP_AIF(GF_AIF1), LN1_GROUP_AIF(GF_AIF2), |
654 | LN1_GROUP_AIF(GF_AIF3), LN1_GROUP_AIF(GF_AIF4), |
655 | LN1_GROUP_AIF(SPDIF_AIF), |
656 | }; |
657 | |
658 | static const struct lochnagar_group lochnagar2_groups[] = { |
659 | LN2_GROUP_PIN(FPGA_GPIO1), LN2_GROUP_PIN(FPGA_GPIO2), |
660 | LN2_GROUP_PIN(FPGA_GPIO3), LN2_GROUP_PIN(FPGA_GPIO4), |
661 | LN2_GROUP_PIN(FPGA_GPIO5), LN2_GROUP_PIN(FPGA_GPIO6), |
662 | LN2_GROUP_PIN(CDC_GPIO1), LN2_GROUP_PIN(CDC_GPIO2), |
663 | LN2_GROUP_PIN(CDC_GPIO3), LN2_GROUP_PIN(CDC_GPIO4), |
664 | LN2_GROUP_PIN(CDC_GPIO5), LN2_GROUP_PIN(CDC_GPIO6), |
665 | LN2_GROUP_PIN(CDC_GPIO7), LN2_GROUP_PIN(CDC_GPIO8), |
666 | LN2_GROUP_PIN(DSP_GPIO1), LN2_GROUP_PIN(DSP_GPIO2), |
667 | LN2_GROUP_PIN(DSP_GPIO3), LN2_GROUP_PIN(DSP_GPIO4), |
668 | LN2_GROUP_PIN(DSP_GPIO5), LN2_GROUP_PIN(DSP_GPIO6), |
669 | LN2_GROUP_PIN(DSP_GPIO20), |
670 | LN2_GROUP_PIN(GF_GPIO1), |
671 | LN2_GROUP_PIN(GF_GPIO2), LN2_GROUP_PIN(GF_GPIO5), |
672 | LN2_GROUP_PIN(GF_GPIO3), LN2_GROUP_PIN(GF_GPIO7), |
673 | LN2_GROUP_PIN(DSP_UART1_RX), LN2_GROUP_PIN(DSP_UART1_TX), |
674 | LN2_GROUP_PIN(DSP_UART2_RX), LN2_GROUP_PIN(DSP_UART2_TX), |
675 | LN2_GROUP_PIN(GF_UART2_RX), LN2_GROUP_PIN(GF_UART2_TX), |
676 | LN2_GROUP_PIN(USB_UART_RX), |
677 | LN2_GROUP_PIN(CDC_PDMCLK1), LN2_GROUP_PIN(CDC_PDMDAT1), |
678 | LN2_GROUP_PIN(CDC_PDMCLK2), LN2_GROUP_PIN(CDC_PDMDAT2), |
679 | LN2_GROUP_PIN(CDC_DMICCLK1), LN2_GROUP_PIN(CDC_DMICDAT1), |
680 | LN2_GROUP_PIN(CDC_DMICCLK2), LN2_GROUP_PIN(CDC_DMICDAT2), |
681 | LN2_GROUP_PIN(CDC_DMICCLK3), LN2_GROUP_PIN(CDC_DMICDAT3), |
682 | LN2_GROUP_PIN(CDC_DMICCLK4), LN2_GROUP_PIN(CDC_DMICDAT4), |
683 | LN2_GROUP_PIN(DSP_DMICCLK1), LN2_GROUP_PIN(DSP_DMICDAT1), |
684 | LN2_GROUP_PIN(DSP_DMICCLK2), LN2_GROUP_PIN(DSP_DMICDAT2), |
685 | LN2_GROUP_PIN(I2C2_SCL), LN2_GROUP_PIN(I2C2_SDA), |
686 | LN2_GROUP_PIN(I2C3_SCL), LN2_GROUP_PIN(I2C3_SDA), |
687 | LN2_GROUP_PIN(I2C4_SCL), LN2_GROUP_PIN(I2C4_SDA), |
688 | LN2_GROUP_PIN(DSP_STANDBY), |
689 | LN2_GROUP_PIN(CDC_MCLK1), LN2_GROUP_PIN(CDC_MCLK2), |
690 | LN2_GROUP_PIN(DSP_CLKIN), |
691 | LN2_GROUP_PIN(PSIA1_MCLK), LN2_GROUP_PIN(PSIA2_MCLK), |
692 | LN2_GROUP_GAI(CDC_AIF1), LN2_GROUP_GAI(CDC_AIF2), |
693 | LN2_GROUP_GAI(CDC_AIF3), |
694 | LN2_GROUP_GAI(DSP_AIF1), LN2_GROUP_GAI(DSP_AIF2), |
695 | LN2_GROUP_GAI(PSIA1), LN2_GROUP_GAI(PSIA2), |
696 | LN2_GROUP_GAI(GF_AIF1), LN2_GROUP_GAI(GF_AIF2), |
697 | LN2_GROUP_GAI(GF_AIF3), LN2_GROUP_GAI(GF_AIF4), |
698 | LN2_GROUP_AIF(SPDIF_AIF), |
699 | LN2_GROUP_AIF(USB_AIF1), LN2_GROUP_AIF(USB_AIF2), |
700 | LN2_GROUP_AIF(ADAT_AIF), |
701 | LN2_GROUP_AIF(SOUNDCARD_AIF), |
702 | }; |
703 | |
704 | struct lochnagar_func_groups { |
705 | const char **groups; |
706 | unsigned int ngroups; |
707 | }; |
708 | |
709 | struct lochnagar_pin_priv { |
710 | struct lochnagar *lochnagar; |
711 | struct device *dev; |
712 | |
713 | const struct lochnagar_func *funcs; |
714 | unsigned int nfuncs; |
715 | |
716 | const struct pinctrl_pin_desc *pins; |
717 | unsigned int npins; |
718 | |
719 | const struct lochnagar_group *groups; |
720 | unsigned int ngroups; |
721 | |
722 | struct lochnagar_func_groups func_groups[LN_FTYPE_COUNT]; |
723 | |
724 | struct gpio_chip gpio_chip; |
725 | }; |
726 | |
727 | static int lochnagar_get_groups_count(struct pinctrl_dev *pctldev) |
728 | { |
729 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
730 | |
731 | return priv->ngroups; |
732 | } |
733 | |
734 | static const char *lochnagar_get_group_name(struct pinctrl_dev *pctldev, |
735 | unsigned int group_idx) |
736 | { |
737 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
738 | |
739 | return priv->groups[group_idx].name; |
740 | } |
741 | |
742 | static int lochnagar_get_group_pins(struct pinctrl_dev *pctldev, |
743 | unsigned int group_idx, |
744 | const unsigned int **pins, |
745 | unsigned int *num_pins) |
746 | { |
747 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
748 | |
749 | *pins = priv->groups[group_idx].pins; |
750 | *num_pins = priv->groups[group_idx].npins; |
751 | |
752 | return 0; |
753 | } |
754 | |
755 | static const struct pinctrl_ops lochnagar_pin_group_ops = { |
756 | .get_groups_count = lochnagar_get_groups_count, |
757 | .get_group_name = lochnagar_get_group_name, |
758 | .get_group_pins = lochnagar_get_group_pins, |
759 | .dt_node_to_map = pinconf_generic_dt_node_to_map_all, |
760 | .dt_free_map = pinctrl_utils_free_map, |
761 | }; |
762 | |
763 | static int lochnagar_get_funcs_count(struct pinctrl_dev *pctldev) |
764 | { |
765 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
766 | |
767 | return priv->nfuncs; |
768 | } |
769 | |
770 | static const char *lochnagar_get_func_name(struct pinctrl_dev *pctldev, |
771 | unsigned int func_idx) |
772 | { |
773 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
774 | |
775 | return priv->funcs[func_idx].name; |
776 | } |
777 | |
778 | static int lochnagar_get_func_groups(struct pinctrl_dev *pctldev, |
779 | unsigned int func_idx, |
780 | const char * const **groups, |
781 | unsigned int * const num_groups) |
782 | { |
783 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
784 | int func_type; |
785 | |
786 | func_type = priv->funcs[func_idx].type; |
787 | |
788 | *groups = priv->func_groups[func_type].groups; |
789 | *num_groups = priv->func_groups[func_type].ngroups; |
790 | |
791 | return 0; |
792 | } |
793 | |
794 | static int lochnagar2_get_gpio_chan(struct lochnagar_pin_priv *priv, |
795 | unsigned int op) |
796 | { |
797 | struct regmap *regmap = priv->lochnagar->regmap; |
798 | unsigned int val; |
799 | int free = -1; |
800 | int i, ret; |
801 | |
802 | for (i = 0; i < LN2_NUM_GPIO_CHANNELS; i++) { |
803 | ret = regmap_read(map: regmap, LOCHNAGAR2_GPIO_CHANNEL1 + i, val: &val); |
804 | if (ret) |
805 | return ret; |
806 | |
807 | val &= LOCHNAGAR2_GPIO_CHANNEL_SRC_MASK; |
808 | |
809 | if (val == op) |
810 | return i + 1; |
811 | |
812 | if (free < 0 && !val) |
813 | free = i; |
814 | } |
815 | |
816 | if (free >= 0) { |
817 | ret = regmap_update_bits(map: regmap, |
818 | LOCHNAGAR2_GPIO_CHANNEL1 + free, |
819 | LOCHNAGAR2_GPIO_CHANNEL_SRC_MASK, val: op); |
820 | if (ret) |
821 | return ret; |
822 | |
823 | free++; |
824 | |
825 | dev_dbg(priv->dev, "Set channel %d to 0x%x\n" , free, op); |
826 | |
827 | return free; |
828 | } |
829 | |
830 | return -ENOSPC; |
831 | } |
832 | |
833 | static int lochnagar_pin_set_mux(struct lochnagar_pin_priv *priv, |
834 | const struct lochnagar_pin *pin, |
835 | unsigned int op) |
836 | { |
837 | int ret; |
838 | |
839 | switch (priv->lochnagar->type) { |
840 | case LOCHNAGAR1: |
841 | break; |
842 | default: |
843 | ret = lochnagar2_get_gpio_chan(priv, op); |
844 | if (ret < 0) { |
845 | dev_err(priv->dev, "Failed to get channel for %s: %d\n" , |
846 | pin->name, ret); |
847 | return ret; |
848 | } |
849 | |
850 | op = ret; |
851 | break; |
852 | } |
853 | |
854 | dev_dbg(priv->dev, "Set pin %s to 0x%x\n" , pin->name, op); |
855 | |
856 | ret = regmap_write(map: priv->lochnagar->regmap, reg: pin->reg, val: op); |
857 | if (ret) |
858 | dev_err(priv->dev, "Failed to set %s mux: %d\n" , |
859 | pin->name, ret); |
860 | |
861 | return 0; |
862 | } |
863 | |
864 | static int lochnagar_aif_set_mux(struct lochnagar_pin_priv *priv, |
865 | const struct lochnagar_group *group, |
866 | unsigned int op) |
867 | { |
868 | struct regmap *regmap = priv->lochnagar->regmap; |
869 | const struct lochnagar_aif *aif = group->priv; |
870 | const struct lochnagar_pin *pin; |
871 | int i, ret; |
872 | |
873 | ret = regmap_update_bits(map: regmap, reg: aif->src_reg, mask: aif->src_mask, val: op); |
874 | if (ret) { |
875 | dev_err(priv->dev, "Failed to set %s source: %d\n" , |
876 | group->name, ret); |
877 | return ret; |
878 | } |
879 | |
880 | ret = regmap_update_bits(map: regmap, reg: aif->ctrl_reg, |
881 | mask: aif->ena_mask, val: aif->ena_mask); |
882 | if (ret) { |
883 | dev_err(priv->dev, "Failed to set %s enable: %d\n" , |
884 | group->name, ret); |
885 | return ret; |
886 | } |
887 | |
888 | for (i = 0; i < group->npins; i++) { |
889 | pin = priv->pins[group->pins[i]].drv_data; |
890 | |
891 | if (pin->type != LN_PTYPE_MUX) |
892 | continue; |
893 | |
894 | dev_dbg(priv->dev, "Set pin %s to AIF\n" , pin->name); |
895 | |
896 | ret = regmap_update_bits(map: regmap, reg: pin->reg, |
897 | LOCHNAGAR2_GPIO_SRC_MASK, |
898 | LN2_OP_AIF); |
899 | if (ret) { |
900 | dev_err(priv->dev, "Failed to set %s to AIF: %d\n" , |
901 | pin->name, ret); |
902 | return ret; |
903 | } |
904 | } |
905 | |
906 | return 0; |
907 | } |
908 | |
909 | static int lochnagar_set_mux(struct pinctrl_dev *pctldev, |
910 | unsigned int func_idx, unsigned int group_idx) |
911 | { |
912 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
913 | const struct lochnagar_func *func = &priv->funcs[func_idx]; |
914 | const struct lochnagar_group *group = &priv->groups[group_idx]; |
915 | const struct lochnagar_pin *pin; |
916 | |
917 | switch (func->type) { |
918 | case LN_FTYPE_AIF: |
919 | dev_dbg(priv->dev, "Set group %s to %s\n" , |
920 | group->name, func->name); |
921 | |
922 | return lochnagar_aif_set_mux(priv, group, op: func->op); |
923 | case LN_FTYPE_PIN: |
924 | pin = priv->pins[*group->pins].drv_data; |
925 | |
926 | dev_dbg(priv->dev, "Set pin %s to %s\n" , pin->name, func->name); |
927 | |
928 | return lochnagar_pin_set_mux(priv, pin, op: func->op); |
929 | default: |
930 | return -EINVAL; |
931 | } |
932 | } |
933 | |
934 | static int lochnagar_gpio_request(struct pinctrl_dev *pctldev, |
935 | struct pinctrl_gpio_range *range, |
936 | unsigned int offset) |
937 | { |
938 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
939 | struct lochnagar *lochnagar = priv->lochnagar; |
940 | const struct lochnagar_pin *pin = priv->pins[offset].drv_data; |
941 | int ret; |
942 | |
943 | dev_dbg(priv->dev, "Requesting GPIO %s\n" , pin->name); |
944 | |
945 | if (lochnagar->type == LOCHNAGAR1 || pin->type != LN_PTYPE_MUX) |
946 | return 0; |
947 | |
948 | ret = lochnagar2_get_gpio_chan(priv, LN2_OP_GPIO); |
949 | if (ret < 0) { |
950 | dev_err(priv->dev, "Failed to get low channel: %d\n" , ret); |
951 | return ret; |
952 | } |
953 | |
954 | ret = lochnagar2_get_gpio_chan(priv, LN2_OP_GPIO | 0x1); |
955 | if (ret < 0) { |
956 | dev_err(priv->dev, "Failed to get high channel: %d\n" , ret); |
957 | return ret; |
958 | } |
959 | |
960 | return 0; |
961 | } |
962 | |
963 | static int lochnagar_gpio_set_direction(struct pinctrl_dev *pctldev, |
964 | struct pinctrl_gpio_range *range, |
965 | unsigned int offset, |
966 | bool input) |
967 | { |
968 | /* The GPIOs only support output */ |
969 | if (input) |
970 | return -EINVAL; |
971 | |
972 | return 0; |
973 | } |
974 | |
975 | static const struct pinmux_ops lochnagar_pin_mux_ops = { |
976 | .get_functions_count = lochnagar_get_funcs_count, |
977 | .get_function_name = lochnagar_get_func_name, |
978 | .get_function_groups = lochnagar_get_func_groups, |
979 | .set_mux = lochnagar_set_mux, |
980 | |
981 | .gpio_request_enable = lochnagar_gpio_request, |
982 | .gpio_set_direction = lochnagar_gpio_set_direction, |
983 | |
984 | .strict = true, |
985 | }; |
986 | |
987 | static int lochnagar_aif_set_master(struct lochnagar_pin_priv *priv, |
988 | unsigned int group_idx, bool master) |
989 | { |
990 | struct regmap *regmap = priv->lochnagar->regmap; |
991 | const struct lochnagar_group *group = &priv->groups[group_idx]; |
992 | const struct lochnagar_aif *aif = group->priv; |
993 | unsigned int val = 0; |
994 | int ret; |
995 | |
996 | if (group->type != LN_FTYPE_AIF) |
997 | return -EINVAL; |
998 | |
999 | if (!master) |
1000 | val = aif->master_mask; |
1001 | |
1002 | dev_dbg(priv->dev, "Set AIF %s to %s\n" , |
1003 | group->name, master ? "master" : "slave" ); |
1004 | |
1005 | ret = regmap_update_bits(map: regmap, reg: aif->ctrl_reg, mask: aif->master_mask, val); |
1006 | if (ret) { |
1007 | dev_err(priv->dev, "Failed to set %s mode: %d\n" , |
1008 | group->name, ret); |
1009 | return ret; |
1010 | } |
1011 | |
1012 | return 0; |
1013 | } |
1014 | |
1015 | static int lochnagar_conf_group_set(struct pinctrl_dev *pctldev, |
1016 | unsigned int group_idx, |
1017 | unsigned long *configs, |
1018 | unsigned int num_configs) |
1019 | { |
1020 | struct lochnagar_pin_priv *priv = pinctrl_dev_get_drvdata(pctldev); |
1021 | int i, ret; |
1022 | |
1023 | for (i = 0; i < num_configs; i++) { |
1024 | unsigned int param = pinconf_to_config_param(config: *configs); |
1025 | |
1026 | switch (param) { |
1027 | case PIN_CONFIG_OUTPUT_ENABLE: |
1028 | ret = lochnagar_aif_set_master(priv, group_idx, master: true); |
1029 | if (ret) |
1030 | return ret; |
1031 | break; |
1032 | case PIN_CONFIG_INPUT_ENABLE: |
1033 | ret = lochnagar_aif_set_master(priv, group_idx, master: false); |
1034 | if (ret) |
1035 | return ret; |
1036 | break; |
1037 | default: |
1038 | return -ENOTSUPP; |
1039 | } |
1040 | |
1041 | configs++; |
1042 | } |
1043 | |
1044 | return 0; |
1045 | } |
1046 | |
1047 | static const struct pinconf_ops lochnagar_pin_conf_ops = { |
1048 | .pin_config_group_set = lochnagar_conf_group_set, |
1049 | }; |
1050 | |
1051 | static const struct pinctrl_desc lochnagar_pin_desc = { |
1052 | .name = "lochnagar-pinctrl" , |
1053 | .owner = THIS_MODULE, |
1054 | |
1055 | .pctlops = &lochnagar_pin_group_ops, |
1056 | .pmxops = &lochnagar_pin_mux_ops, |
1057 | .confops = &lochnagar_pin_conf_ops, |
1058 | }; |
1059 | |
1060 | static void lochnagar_gpio_set(struct gpio_chip *chip, |
1061 | unsigned int offset, int value) |
1062 | { |
1063 | struct lochnagar_pin_priv *priv = gpiochip_get_data(gc: chip); |
1064 | struct lochnagar *lochnagar = priv->lochnagar; |
1065 | const struct lochnagar_pin *pin = priv->pins[offset].drv_data; |
1066 | int ret; |
1067 | |
1068 | value = !!value; |
1069 | |
1070 | dev_dbg(priv->dev, "Set GPIO %s to %s\n" , |
1071 | pin->name, value ? "high" : "low" ); |
1072 | |
1073 | switch (pin->type) { |
1074 | case LN_PTYPE_MUX: |
1075 | value |= LN2_OP_GPIO; |
1076 | |
1077 | ret = lochnagar_pin_set_mux(priv, pin, op: value); |
1078 | break; |
1079 | case LN_PTYPE_GPIO: |
1080 | if (pin->invert) |
1081 | value = !value; |
1082 | |
1083 | ret = regmap_update_bits(map: lochnagar->regmap, reg: pin->reg, |
1084 | BIT(pin->shift), val: value << pin->shift); |
1085 | break; |
1086 | default: |
1087 | ret = -EINVAL; |
1088 | break; |
1089 | } |
1090 | |
1091 | if (ret < 0) |
1092 | dev_err(chip->parent, "Failed to set %s value: %d\n" , |
1093 | pin->name, ret); |
1094 | } |
1095 | |
1096 | static int lochnagar_gpio_direction_out(struct gpio_chip *chip, |
1097 | unsigned int offset, int value) |
1098 | { |
1099 | lochnagar_gpio_set(chip, offset, value); |
1100 | |
1101 | return pinctrl_gpio_direction_output(gc: chip, offset); |
1102 | } |
1103 | |
1104 | static int lochnagar_fill_func_groups(struct lochnagar_pin_priv *priv) |
1105 | { |
1106 | struct lochnagar_func_groups *funcs; |
1107 | int i; |
1108 | |
1109 | for (i = 0; i < priv->ngroups; i++) |
1110 | priv->func_groups[priv->groups[i].type].ngroups++; |
1111 | |
1112 | for (i = 0; i < LN_FTYPE_COUNT; i++) { |
1113 | funcs = &priv->func_groups[i]; |
1114 | |
1115 | if (!funcs->ngroups) |
1116 | continue; |
1117 | |
1118 | funcs->groups = devm_kcalloc(dev: priv->dev, n: funcs->ngroups, |
1119 | size: sizeof(*funcs->groups), |
1120 | GFP_KERNEL); |
1121 | if (!funcs->groups) |
1122 | return -ENOMEM; |
1123 | |
1124 | funcs->ngroups = 0; |
1125 | } |
1126 | |
1127 | for (i = 0; i < priv->ngroups; i++) { |
1128 | funcs = &priv->func_groups[priv->groups[i].type]; |
1129 | |
1130 | funcs->groups[funcs->ngroups++] = priv->groups[i].name; |
1131 | } |
1132 | |
1133 | return 0; |
1134 | } |
1135 | |
1136 | static int lochnagar_pin_probe(struct platform_device *pdev) |
1137 | { |
1138 | struct lochnagar *lochnagar = dev_get_drvdata(dev: pdev->dev.parent); |
1139 | struct lochnagar_pin_priv *priv; |
1140 | struct pinctrl_desc *desc; |
1141 | struct pinctrl_dev *pctl; |
1142 | struct device *dev = &pdev->dev; |
1143 | int ret; |
1144 | |
1145 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
1146 | if (!priv) |
1147 | return -ENOMEM; |
1148 | |
1149 | priv->dev = dev; |
1150 | priv->lochnagar = lochnagar; |
1151 | |
1152 | desc = devm_kzalloc(dev, size: sizeof(*desc), GFP_KERNEL); |
1153 | if (!desc) |
1154 | return -ENOMEM; |
1155 | |
1156 | *desc = lochnagar_pin_desc; |
1157 | |
1158 | priv->gpio_chip.label = dev_name(dev); |
1159 | priv->gpio_chip.request = gpiochip_generic_request; |
1160 | priv->gpio_chip.free = gpiochip_generic_free; |
1161 | priv->gpio_chip.direction_output = lochnagar_gpio_direction_out; |
1162 | priv->gpio_chip.set = lochnagar_gpio_set; |
1163 | priv->gpio_chip.can_sleep = true; |
1164 | priv->gpio_chip.parent = dev; |
1165 | priv->gpio_chip.base = -1; |
1166 | |
1167 | switch (lochnagar->type) { |
1168 | case LOCHNAGAR1: |
1169 | priv->funcs = lochnagar1_funcs; |
1170 | priv->nfuncs = ARRAY_SIZE(lochnagar1_funcs); |
1171 | priv->pins = lochnagar1_pins; |
1172 | priv->npins = ARRAY_SIZE(lochnagar1_pins); |
1173 | priv->groups = lochnagar1_groups; |
1174 | priv->ngroups = ARRAY_SIZE(lochnagar1_groups); |
1175 | |
1176 | priv->gpio_chip.ngpio = LOCHNAGAR1_PIN_NUM_GPIOS; |
1177 | break; |
1178 | case LOCHNAGAR2: |
1179 | priv->funcs = lochnagar2_funcs; |
1180 | priv->nfuncs = ARRAY_SIZE(lochnagar2_funcs); |
1181 | priv->pins = lochnagar2_pins; |
1182 | priv->npins = ARRAY_SIZE(lochnagar2_pins); |
1183 | priv->groups = lochnagar2_groups; |
1184 | priv->ngroups = ARRAY_SIZE(lochnagar2_groups); |
1185 | |
1186 | priv->gpio_chip.ngpio = LOCHNAGAR2_PIN_NUM_GPIOS; |
1187 | break; |
1188 | default: |
1189 | dev_err(dev, "Unknown Lochnagar type: %d\n" , lochnagar->type); |
1190 | return -EINVAL; |
1191 | } |
1192 | |
1193 | ret = lochnagar_fill_func_groups(priv); |
1194 | if (ret < 0) |
1195 | return ret; |
1196 | |
1197 | desc->pins = priv->pins; |
1198 | desc->npins = priv->npins; |
1199 | |
1200 | pctl = devm_pinctrl_register(dev, pctldesc: desc, driver_data: priv); |
1201 | if (IS_ERR(ptr: pctl)) { |
1202 | ret = PTR_ERR(ptr: pctl); |
1203 | dev_err(priv->dev, "Failed to register pinctrl: %d\n" , ret); |
1204 | return ret; |
1205 | } |
1206 | |
1207 | ret = devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); |
1208 | if (ret < 0) { |
1209 | dev_err(&pdev->dev, "Failed to register gpiochip: %d\n" , ret); |
1210 | return ret; |
1211 | } |
1212 | |
1213 | return 0; |
1214 | } |
1215 | |
1216 | static const struct of_device_id lochnagar_of_match[] = { |
1217 | { .compatible = "cirrus,lochnagar-pinctrl" }, |
1218 | {} |
1219 | }; |
1220 | MODULE_DEVICE_TABLE(of, lochnagar_of_match); |
1221 | |
1222 | static struct platform_driver lochnagar_pin_driver = { |
1223 | .driver = { |
1224 | .name = "lochnagar-pinctrl" , |
1225 | .of_match_table = of_match_ptr(lochnagar_of_match), |
1226 | }, |
1227 | |
1228 | .probe = lochnagar_pin_probe, |
1229 | }; |
1230 | module_platform_driver(lochnagar_pin_driver); |
1231 | |
1232 | MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>" ); |
1233 | MODULE_DESCRIPTION("Pinctrl driver for Cirrus Logic Lochnagar Board" ); |
1234 | MODULE_LICENSE("GPL v2" ); |
1235 | |