1 // Copyright 2017 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 <ddk/debug.h>
6 #include <ddk/device.h>
7 #include <ddk/platform-defs.h>
8 #include <ddk/protocol/platform/bus.h>
9 
10 #include <soc/aml-s905x/s905x-gpio.h>
11 #include <soc/aml-s912/s912-gpio.h>
12 #include <soc/aml-s912/s912-hw.h>
13 
14 #include <limits.h>
15 
16 #include "vim.h"
17 
18 // S905X and S912 have same MMIO addresses
19 static const pbus_mmio_t gpio_mmios[] = {
20     {
21         .base = S912_GPIO_BASE,
22         .length = S912_GPIO_LENGTH,
23     },
24     {
25         .base = S912_GPIO_AO_BASE,
26         .length = S912_GPIO_AO_LENGTH,
27     },
28     {
29         .base = S912_GPIO_INTERRUPT_BASE,
30         .length = S912_GPIO_INTERRUPT_LENGTH,
31     },
32 };
33 
34 // S905X and S912 have same GPIO IRQ numbers
35 static const pbus_irq_t gpio_irqs[] = {
36     {
37         .irq = S912_GPIO_IRQ_0,
38     },
39     {
40         .irq = S912_GPIO_IRQ_1,
41     },
42     {
43         .irq = S912_GPIO_IRQ_2,
44     },
45     {
46         .irq = S912_GPIO_IRQ_3,
47     },
48     {
49         .irq = S912_GPIO_IRQ_4,
50     },
51     {
52         .irq = S912_GPIO_IRQ_5,
53     },
54     {
55         .irq = S912_GPIO_IRQ_6,
56     },
57     {
58         .irq = S912_GPIO_IRQ_7,
59     },
60     {
61         .irq = S912_AO_GPIO_IRQ_0,
62     },
63     {
64         .irq = S912_AO_GPIO_IRQ_1,
65     },
66 };
67 
68 static const pbus_dev_t gpio_dev = {
69     .name = "gpio",
70     .vid = PDEV_VID_AMLOGIC,
71     .pid = PDEV_PID_AMLOGIC_S912,
72     .did = PDEV_DID_AMLOGIC_GPIO,
73     .mmio_list = gpio_mmios,
74     .mmio_count = countof(gpio_mmios),
75     .irq_list = gpio_irqs,
76     .irq_count = countof(gpio_irqs),
77 };
78 
79 
vim_gpio_init(vim_bus_t * bus,bool enable_test)80 zx_status_t vim_gpio_init(vim_bus_t* bus, bool enable_test) {
81 
82     zx_status_t status = pbus_protocol_device_add(&bus->pbus, ZX_PROTOCOL_GPIO_IMPL, &gpio_dev);
83     if (status != ZX_OK) {
84         zxlogf(ERROR, "vim_gpio_init: pbus_protocol_device_add failed: %d\n", status);
85         return status;
86     }
87 
88     status = device_get_protocol(bus->parent, ZX_PROTOCOL_GPIO_IMPL, &bus->gpio);
89     if (status != ZX_OK) {
90         zxlogf(ERROR, "vim_gpio_init: device_get_protocol failed: %d\n", status);
91         return status;
92     }
93 
94     if (enable_test) {
95         const pbus_gpio_t gpio_test_gpios[] = {
96             {
97                 // SYS_LED
98                 .gpio = S912_GPIOAO(9),
99             },
100             {
101                 // GPIO PIN
102                 .gpio = S912_GPIOAO(2),
103             },
104         };
105 
106         const pbus_dev_t gpio_test_dev = {
107             .name = "vim-gpio-test",
108             .vid = PDEV_VID_GENERIC,
109             .pid = PDEV_PID_GENERIC,
110             .did = PDEV_DID_GPIO_TEST,
111             .gpio_list = gpio_test_gpios,
112             .gpio_count = countof(gpio_test_gpios),
113         };
114 
115         status = pbus_device_add(&bus->pbus, &gpio_test_dev);
116         if (status != ZX_OK) {
117             zxlogf(ERROR, "vim_gpio_init could not add gpio_test_dev: %d\n", status);
118             return status;
119         }
120     }
121 
122     return ZX_OK;
123 }
124