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 <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-t931/t931-gpio.h>
11 #include <soc/aml-t931/t931-hw.h>
12
13 #include "sherlock.h"
14
15 namespace sherlock {
16
17 static const pbus_mmio_t gpio_mmios[] = {
18 {
19 .base = T931_GPIO_BASE,
20 .length = T931_GPIO_LENGTH,
21 },
22 {
23 .base = T931_GPIO_A0_BASE,
24 .length = T931_GPIO_AO_LENGTH,
25 },
26 {
27 .base = T931_GPIO_INTERRUPT_BASE,
28 .length = T931_GPIO_INTERRUPT_LENGTH,
29 },
30 };
31
32 static const pbus_irq_t gpio_irqs[] = {
33 {
34 .irq = T931_GPIO_IRQ_0,
35 .mode = ZX_INTERRUPT_MODE_DEFAULT,
36 },
37 {
38 .irq = T931_GPIO_IRQ_1,
39 .mode = ZX_INTERRUPT_MODE_DEFAULT,
40 },
41 {
42 .irq = T931_GPIO_IRQ_2,
43 .mode = ZX_INTERRUPT_MODE_DEFAULT,
44 },
45 {
46 .irq = T931_GPIO_IRQ_3,
47 .mode = ZX_INTERRUPT_MODE_DEFAULT,
48 },
49 {
50 .irq = T931_GPIO_IRQ_4,
51 .mode = ZX_INTERRUPT_MODE_DEFAULT,
52 },
53 {
54 .irq = T931_GPIO_IRQ_5,
55 .mode = ZX_INTERRUPT_MODE_DEFAULT,
56 },
57 {
58 .irq = T931_GPIO_IRQ_6,
59 .mode = ZX_INTERRUPT_MODE_DEFAULT,
60 },
61 {
62 .irq = T931_GPIO_IRQ_7,
63 .mode = ZX_INTERRUPT_MODE_DEFAULT,
64 },
65 };
66
__anon467c39760102()67 static pbus_dev_t gpio_dev = [](){
68 pbus_dev_t dev;
69 dev.name = "gpio";
70 dev.vid = PDEV_VID_AMLOGIC;
71 dev.pid = PDEV_PID_AMLOGIC_T931;
72 dev.did = PDEV_DID_AMLOGIC_GPIO;
73 dev.mmio_list = gpio_mmios;
74 dev.mmio_count = countof(gpio_mmios);
75 dev.irq_list = gpio_irqs;
76 dev.irq_count = countof(gpio_irqs);
77 return dev;
78 }();
79
GpioInit()80 zx_status_t Sherlock::GpioInit() {
81 zx_status_t status = pbus_.ProtocolDeviceAdd(ZX_PROTOCOL_GPIO_IMPL, &gpio_dev);
82 if (status != ZX_OK) {
83 zxlogf(ERROR, "%s: ProtocolDeviceAdd failed %d\n", __func__, status);
84 return status;
85 }
86 // This test binds to system/dev/gpio/gpio-test to check that GPIOs work at all.
87 // gpio-test enables interrupts and write/read on the test GPIOs configured below.
88 //#define GPIO_TEST
89 #ifdef GPIO_TEST
90 const pbus_gpio_t gpio_test_gpios[] = {
91 {
92 .gpio = T931_GPIOZ(5), // Volume down, not used in this test.
93 },
94 {
95 .gpio = T931_GPIOZ(4), // Volume up, to test gpio_get_interrupt().
96 },
97 };
98
99 pbus_dev_t gpio_test_dev = {};
100 gpio_test_dev.name = "sherlock-gpio-test";
101 gpio_test_dev.vid = PDEV_VID_GENERIC;
102 gpio_test_dev.pid = PDEV_PID_GENERIC;
103 gpio_test_dev.did = PDEV_DID_GPIO_TEST;
104 gpio_test_dev.gpio_list = gpio_test_gpios;
105 gpio_test_dev.gpio_count = countof(gpio_test_gpios);
106 if ((status = pbus_.DeviceAdd(&gpio_test_dev)) != ZX_OK) {
107 zxlogf(ERROR, "%s: Could not add gpio_test_dev %d\n", __FUNCTION__, status);
108 return status;
109 }
110 #endif
111
112 gpio_impl_ = ddk::GpioImplProtocolClient(parent());
113 if (!gpio_impl_.is_valid()) {
114 zxlogf(ERROR, "%s: device_get_protocol failed %d\n", __func__, status);
115 return ZX_ERR_INTERNAL;
116 }
117
118 return ZX_OK;
119 }
120
121 } // namespace sherlock
122