1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <soc/aml-s905/s905-gpio.h>
6 
7 #include "aml-gxl-gpio.h"
8 
9 namespace gpio {
10 
11 constexpr AmlGpioBlock s905_gpio_blocks[] = {
12     // GPIOX Block
13     {
14         .pin_count = S905_GPIOX_PINS,
15         .oen_offset = S905_GPIOX_0EN,
16         .input_offset = S905_GPIOX_IN,
17         .output_offset = S905_GPIOX_OUT,
18         .output_shift = 0,
19         .mmio_index = 0,
20         .pull_offset = S905_PULL_UP_REG4,
21         .pull_en_offset = S905_PULL_UP_EN_REG4,
22         .pin_start = S905_GPIOX_PIN_START,
23     },
24     // GPIOY Block
25     {
26         .pin_count = S905_GPIOY_PINS,
27         .oen_offset = S905_GPIOY_0EN,
28         .input_offset = S905_GPIOY_IN,
29         .output_offset = S905_GPIOY_OUT,
30         .output_shift = 0,
31         .mmio_index = 0,
32         .pull_offset = S905_PULL_UP_REG1,
33         .pull_en_offset = S905_PULL_UP_EN_REG1,
34         .pin_start = S905_GPIOY_PIN_START,
35     },
36     // GPIOZ Block
37     {
38         .pin_count = S905_GPIOZ_PINS,
39         .oen_offset = S905_GPIOZ_0EN,
40         .input_offset = S905_GPIOZ_IN,
41         .output_offset = S905_GPIOZ_OUT,
42         .output_shift = 0,
43         .mmio_index = 0,
44         .pull_offset = 0, // not supported
45         .pull_en_offset = 0, // not supported
46         .pin_start = S905_GPIOZ_PIN_START,
47     },
48     // GPIODV Block
49     {
50         .pin_count = S905_GPIODV_PINS,
51         .oen_offset = S905_GPIODV_0EN,
52         .input_offset = S905_GPIODV_IN,
53         .output_offset = S905_GPIODV_OUT,
54         .output_shift = 0,
55         .mmio_index = 0,
56         .pull_offset = S905_PULL_UP_REG0,
57         .pull_en_offset = S905_PULL_UP_EN_REG0,
58         .pin_start = S905_GPIODV_PIN_START,
59     },
60     // GPIOH Block
61     {
62         .pin_count = S905_GPIOH_PINS,
63         .oen_offset = S905_GPIOH_0EN,
64         .input_offset = S905_GPIOH_IN,
65         .output_offset = S905_GPIOH_OUT,
66         .output_shift = 20,
67         .mmio_index = 0,
68         .pull_offset = S905_PULL_UP_REG1,
69         .pull_en_offset = S905_PULL_UP_EN_REG1,
70         .pin_start = S905_GPIOH_PIN_START,
71     },
72     // GPIOCLK Block
73     {
74         .pin_count = S905_GPIOCLK_PINS,
75         .oen_offset = S905_GPIOCLK_0EN,
76         .input_offset = S905_GPIOCLK_IN,
77         .output_offset = S905_GPIOCLK_OUT,
78         .output_shift = 28,
79         .mmio_index = 0,
80         .pull_offset = S905_PULL_UP_REG3,
81         .pull_en_offset = S905_PULL_UP_EN_REG3,
82         .pin_start = S905_GPIOCLK_PIN_START,
83     },
84     // GPIOBOOT Block
85     {
86         .pin_count = S905_GPIOBOOT_PINS,
87         .oen_offset = S905_GPIOBOOT_0EN,
88         .input_offset = S905_GPIOBOOT_IN,
89         .output_offset = S905_GPIOBOOT_OUT,
90         .output_shift = 0,
91         .mmio_index = 0,
92         .pull_offset = S905_PULL_UP_REG2,
93         .pull_en_offset = S905_PULL_UP_EN_REG2,
94         .pin_start = S905_GPIOBOOT_PIN_START,
95     },
96     // GPIOCARD Block
97     {
98         .pin_count = S905_GPIOCARD_PINS,
99         .oen_offset = S905_GPIOCARD_0EN,
100         .input_offset = S905_GPIOCARD_IN,
101         .output_offset = S905_GPIOCARD_OUT,
102         .output_shift = 20,
103         .mmio_index = 0,
104         .pull_offset = S905_PULL_UP_REG2,
105         .pull_en_offset = S905_PULL_UP_EN_REG2,
106         .pin_start = S905_GPIOCARD_PIN_START,
107     },
108     // GPIOAO Block
109     {
110         .pin_count = S905_GPIOAO_PINS,
111         .oen_offset = S905_AO_GPIO_OEN_OUT,
112         .input_offset = S905_AO_GPIO_IN,
113         .output_offset = S905_AO_GPIO_OEN_OUT,
114         .output_shift = 0,
115         .output_write_shift = 16, // output is shared with OEN
116         .mmio_index = 1,
117         .pull_offset = S905_PULL_UP_REG_AO,
118         .pull_en_offset = S905_PULL_UP_EN_REGAO,
119         .pin_start = S905_GPIOA0_PIN_START,
120     },
121 };
122 
123 #define REG_0 S905_PERIPHS_PIN_MUX_0
124 #define REG_1 S905_PERIPHS_PIN_MUX_1
125 #define REG_2 S905_PERIPHS_PIN_MUX_2
126 #define REG_3 S905_PERIPHS_PIN_MUX_3
127 #define REG_4 S905_PERIPHS_PIN_MUX_4
128 #define REG_5 S905_PERIPHS_PIN_MUX_5
129 #define REG_6 S905_PERIPHS_PIN_MUX_6
130 #define REG_7 S905_PERIPHS_PIN_MUX_7
131 #define REG_8 S905_PERIPHS_PIN_MUX_8
132 #define REG_9 S905_PERIPHS_PIN_MUX_9
133 #define AO_REG S905_AO_RTI_PIN_MUX_REG
134 #define AO_REG_2 S905_AO_RTI_PIN_MUX_REG2
135 
136 constexpr AmlGpioInterrupt s905_interrupt_block = {
137     .pin_0_3_select_offset =    S905_GPIO_0_3_PIN_SELECT,
138     .pin_4_7_select_offset =    S905_GPIO_4_7_PIN_SELECT,
139     .edge_polarity_offset =     S905_GPIO_INT_EDGE_POLARITY,
140     .filter_select_offset =     S905_GPIO_FILTER_SELECT,
141     .status_offset =            S905_GPIO_INT_STATUS,
142     .mask_offset =              S905_GPIO_INT_MASK,
143 };
144 
145 constexpr AmlPinMuxBlock s905_pinmux_blocks[] = {
146     // GPIOX Block
147     {
148         .mux = {
149             { .regs = { REG_8 }, .bits = { 5 }, },
150             { .regs = { REG_8 }, .bits = { 4 }, },
151             { .regs = { REG_8 }, .bits = { 3 }, },
152             { .regs = { REG_8 }, .bits = { 2 }, },
153             { .regs = { REG_8 }, .bits = { 1 }, },
154             { .regs = { REG_8 }, .bits = { 0 }, },
155             { .regs = { 0, 0, 0, REG_3, REG_3 }, .bits = { 0, 0, 0, 9, 17 }, },
156             { .regs = { REG_8, 0, 0, REG_3, REG_3 }, .bits = { 11, 0, 0, 8, 18 }, },
157             { .regs = { REG_4, 0, REG_3, REG_3 }, .bits = { 7, 0, 30, 10 }, },
158             { .regs = { REG_4, 0, REG_3, REG_3 }, .bits = { 6, 0, 29, 7 }, },
159             { .regs = { 0, 0, REG_3 }, .bits = { 0, 0, 28 }, },
160             { .regs = { 0, 0, REG_3 }, .bits = { 0, 0, 27 }, },
161             { .regs = { 0, REG_4, REG_4 }, .bits = { 0, 13, 17 }, },
162             { .regs = { 0, REG_4, REG_4 }, .bits = { 0, 12, 16 }, },
163             { .regs = { 0, REG_4, REG_4 }, .bits = { 0, 11, 15 }, },
164             { .regs = { 0, REG_4, REG_4 }, .bits = { 0, 10, 14 }, },
165             { .regs = { 0, REG_2, 0, 0, REG_2 }, .bits = { 0, 22, 0, 0, 30 }, },
166         },
167     },
168     // GPIOY Block
169     {
170         .mux = {
171             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 19, 2, 0, 0, 0 }, },
172             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 18, 1, 0, 0, 1 }, },
173             { .regs = { REG_2, REG_3 }, .bits = { 17, 0 }, },
174             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 16, 4, 0, 0, 1 }, },
175             { .regs = { REG_2, REG_3, 0, REG_1 }, .bits = { 16, 5, 0, 12 }, },
176             { .regs = { REG_2, REG_3, 0, REG_1 }, .bits = { 16, 5, 0, 13 }, },
177             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 16, 5, 0, 0, 3 }, },
178             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 16, 5, 0, 0, 4 }, },
179             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 16, 5, 0, 0, 5 }, },
180             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 16, 5, 0, 0, 6 }, },
181             { .regs = { REG_2, REG_3, 0, 0, REG_1 }, .bits = { 16, 5, 0, 0, 7 }, },
182             { .regs = { 0, REG_3, REG_1, 0, REG_1 }, .bits = { 0, 3, 19, 0, 8 }, },
183             { .regs = { 0, 0, REG_1, 0, REG_1 }, .bits = { 0, 0, 18, 0, 9 }, },
184             { .regs = { 0, 0, REG_1, 0, REG_1 }, .bits = { 0, 0, 17, 0, 10 }, },
185             { .regs = { 0, 0, REG_1, 0, REG_1 }, .bits = { 0, 0, 16, 0, 11 }, },
186             { .regs = { REG_2, 0, 0, REG_1, REG_1 }, .bits = { 20, 0, 0, 20, 22 }, },
187             { .regs = { REG_2, 0, 0, REG_1 }, .bits = { 21, 0, 0, 21 }, },
188         },
189     },
190     // GPIOZ Block
191     {
192         .mux = {
193             { .regs = { REG_6, REG_5 }, .bits = { 1, 5 }, },
194             { .regs = { REG_6, REG_5 }, .bits = { 0, 6 }, },
195             { .regs = { REG_6 }, .bits = { 13 }, },
196             { .regs = { REG_6, REG_5 }, .bits = { 12, 7 }, },
197             { .regs = { REG_6, REG_5 }, .bits = { 11, 4 }, },
198             { .regs = { REG_6, REG_5 }, .bits = { 10, 4 }, },
199             { .regs = { REG_6, REG_5, REG_5, REG_5, REG_4 }, .bits = { 9, 4, 27, 9 }, },
200             { .regs = { REG_6, REG_5, REG_5, REG_5, REG_4 }, .bits = { 8, 4, 26, 8 }, },
201             { .regs = { REG_6, REG_5 }, .bits = { 7, 4 }, },
202             { .regs = { REG_6, REG_5 }, .bits = { 6, 4 }, },
203             { .regs = { REG_6, REG_5 }, .bits = { 5, 4 }, },
204             { .regs = { REG_6, REG_5 }, .bits = { 4, 4 }, },
205             { .regs = { REG_6, 0, REG_5 }, .bits = { 3, 0, 28 }, },
206             { .regs = { REG_6, 0, REG_5 }, .bits = { 2, 0, 29 }, },
207             { },
208             { .regs = { 0, REG_6 }, .bits = { 0, 15 }, },
209         },
210     },
211     // GPIODV Block
212     {
213         .mux = {
214             { },
215             { },
216             { },
217             { },
218             { },
219             { },
220             { },
221             { },
222             { },
223             { },
224             { },
225             { },
226             { },
227             { },
228             { },
229             { },
230             { },
231             { },
232             { },
233             { },
234             { },
235             { },
236             { },
237             { },
238             { .regs = { REG_0, REG_0, REG_5, 0, REG_2, REG_7 }, .bits = { 7, 12, 12, 0, 29, 26 }, },
239             { .regs = { REG_0, REG_0, REG_5, 0, REG_2, REG_7 }, .bits = { 6, 11, 11, 0, 28, 27 }, },
240             { .regs = { 0, REG_0, REG_5, 0, REG_2, REG_7 }, .bits = { 0, 10, 10, 0, 27, 24 }, },
241             { .regs = { 0, REG_0, REG_5, REG_5, REG_2, REG_7 }, .bits = { 0, 9, 9, 8, 26, 25 }, },
242             { .regs = { 0, 0, 0, 0, REG_3, REG_7 }, .bits = { 0, 0, 0, 0, 20, 22 }, },
243             { .regs = { 0, 0, 0, REG_3, REG_3, REG_7 }, .bits = { 0, 0, 0, 22, 21, 23 }, },
244         },
245     },
246     // GPIOH Block
247     {
248         .mux = {
249             { .regs = { REG_1 }, .bits = { 26 }, },
250             { .regs = { REG_1 }, .bits = { 25 }, },
251             { .regs = { REG_1 }, .bits = { 24 }, },
252             {},
253         },
254     },
255     // GPIOCLK Block
256     {
257         .mux = {
258            {},
259            {},
260         },
261     },
262     // GPIOBOOT Block
263     {
264         .mux = {
265             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
266             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
267             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
268             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
269             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
270             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
271             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
272             { .regs = { 0, REG_4 }, .bits = { 0, 30 }, },
273             { .regs = { REG_4, REG_4 }, .bits = { 26, 18 }, },
274             { .regs = { REG_4 }, .bits = { 27 }, },
275             { .regs = { REG_4, REG_4 }, .bits = { 25, 19 }, },
276             { .regs = { REG_4, 0, REG_5 }, .bits = { 24, 0, 1 }, },
277             { .regs = { REG_4, 0, REG_5 }, .bits = { 23, 0, 3 }, },
278             { .regs = { REG_4, 0, REG_5 }, .bits = { 22, 0, 2 }, },
279             { .regs = { REG_4 }, .bits = { 21 }, },
280             { .regs = { REG_4, 0, REG_5 }, .bits = { 20, 0, 3 }, },
281          },
282     },
283     // GPIOCARD Block
284     {
285         .mux = {
286             { .regs = { REG_2 }, .bits = { 14 }, },
287             { .regs = { REG_2 }, .bits = { 15 }, },
288             { .regs = { REG_2 }, .bits = { 11 }, },
289             { .regs = { REG_2 }, .bits = { 10 }, },
290             { .regs = { REG_2, REG_8, REG_8 }, .bits = { 12, 10, 18 }, },
291             { .regs = { REG_2, REG_8, REG_8 }, .bits = { 13, 17, 9 }, },
292         },
293     },
294     // GPIOAO Block
295     {
296         .mux = {
297             { .regs = { AO_REG, AO_REG }, .bits = { 12, 26 }, },
298             { .regs = { AO_REG, AO_REG }, .bits = { 11, 25 }, },
299             { .regs = { AO_REG, AO_REG }, .bits = { 10, 8 }, },
300             { .regs = { AO_REG, AO_REG, AO_REG }, .bits = { 9, 7, 22 }, },
301             { .regs = { 0, AO_REG, AO_REG, AO_REG }, .bits = { 0, 24, 6, 2 }, },
302             { .regs = { 0, AO_REG, AO_REG, AO_REG }, .bits = { 0, 25, 5, 1 }, },
303             { .regs = { 0, AO_REG, AO_REG, AO_REG }, .bits = { 0, 0, 18, 16 }, },
304             { .regs = { AO_REG, AO_REG }, .bits = { 0, 2 }, },
305             { .regs = { 0, 0, 0, AO_REG }, .bits = { 0, 0, 0, 30 }, },
306             { .regs = { 0, 0, 0, AO_REG }, .bits = { 0, 0, 0, 29 }, },
307             { .regs = { 0, 0, 0, AO_REG }, .bits = { 0, 0, 0, 28 }, },
308             { .regs = { 0, 0, 0, AO_REG }, .bits = { 0, 0, 0, 27 }, },
309             { .regs = { AO_REG, AO_REG, AO_REG, AO_REG_2 }, .bits = { 15, 14, 17, 0 }, },
310             { .regs = { AO_REG, AO_REG, AO_REG, AO_REG_2 }, .bits = { 31, 4, 3, 2 }, },
311         },
312     },
313 };
314 
315 static_assert(countof(s905_gpio_blocks) == countof(s905_pinmux_blocks), "");
316 
317 #undef REG_0
318 #undef REG_1
319 #undef REG_2
320 #undef REG_3
321 #undef REG_4
322 #undef REG_5
323 #undef REG_6
324 #undef REG_7
325 #undef REG_8
326 #undef REG_9
327 #undef AO_REG
328 #undef AO_REG_2
329 
330 }  // namespace gpio
331