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