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 "mt8167.h"
6 
7 #include <assert.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include <ddk/binding.h>
14 #include <ddk/debug.h>
15 #include <ddk/device.h>
16 #include <ddk/driver.h>
17 #include <ddk/platform-defs.h>
18 #include <ddk/protocol/gpio.h>
19 #include <ddk/protocol/platform/device.h>
20 
21 #include <fbl/algorithm.h>
22 #include <fbl/unique_ptr.h>
23 
24 namespace board_mt8167 {
25 
Create(zx_device_t * parent)26 zx_status_t Mt8167::Create(zx_device_t* parent) {
27     pbus_protocol_t pbus;
28 
29     auto status = device_get_protocol(parent, ZX_PROTOCOL_PBUS, &pbus);
30     if (status != ZX_OK) {
31         return status;
32     }
33 
34     pdev_board_info_t board_info;
35     status = pbus_get_board_info(&pbus, &board_info);
36     if (status != ZX_OK) {
37         zxlogf(ERROR, "%s: GetBoardInfo failed\n", __FILE__);
38         return status;
39     }
40 
41     fbl::AllocChecker ac;
42     auto board = fbl::make_unique_checked<Mt8167>(&ac, parent, &pbus, &board_info);
43     if (!ac.check()) {
44         return ZX_ERR_NO_MEMORY;
45     }
46 
47     status = board->DdkAdd("mt8167s_ref", DEVICE_ADD_NON_BINDABLE);
48     if (status != ZX_OK) {
49         return status;
50     }
51 
52     // Start up our protocol helpers and platform devices.
53     status = board->Start();
54     if (status == ZX_OK) {
55         // devmgr is now in charge of the device.
56         __UNUSED auto* dummy = board.release();
57     }
58     return status;
59 }
60 
Thread()61 int Mt8167::Thread() {
62     if (SocInit() != ZX_OK) {
63         zxlogf(ERROR, "SocInit() failed\n");
64         return -1;
65     }
66     // Load protocol implementation drivers first.
67     if (GpioInit() != ZX_OK) {
68         zxlogf(ERROR, "GpioInit() failed\n");
69     }
70     if (I2cInit() != ZX_OK) {
71         zxlogf(ERROR, "I2cInit() failed\n");
72     }
73     if (ClkInit() != ZX_OK) {
74         zxlogf(ERROR, "ClkInit() failed\n");
75     }
76 
77     // Then the platform device drivers.
78     if (EmmcInit() != ZX_OK) {
79         zxlogf(ERROR, "EmmcInit() failed\n");
80     }
81     if (SdioInit() != ZX_OK) {
82         zxlogf(ERROR, "SdioInit() failed\n");
83     }
84     if (DisplayInit() != ZX_OK) {
85         zxlogf(ERROR, "DisplayInit() failed\n");
86     }
87     if (ButtonsInit() != ZX_OK) {
88         zxlogf(ERROR, "DisplayInit() failed\n");
89     }
90     if (GpuInit() != ZX_OK) {
91         zxlogf(ERROR, "GpuInit() failed\n");
92     }
93     if (UsbInit() != ZX_OK) {
94         zxlogf(ERROR, "UsbInit() failed\n");
95     }
96     // TouchInit() must be called before ThermalInit() as the touch driver uses the PMIC wrapper to
97     // enable the VGP1 regulator.
98     if (TouchInit() != ZX_OK) {
99         zxlogf(ERROR, "TouchInit() failed\n");
100     }
101     if (ThermalInit() != ZX_OK) {
102         zxlogf(ERROR, "ThermalInit() failed\n");
103     }
104 
105     return 0;
106 }
107 
Start()108 zx_status_t Mt8167::Start() {
109     int rc = thrd_create_with_name(&thread_,
110                                    [](void* arg) -> int {
111                                        return reinterpret_cast<Mt8167*>(arg)->Thread();
112                                    },
113                                    this,
114                                    "mt8167-start-thread");
115     if (rc != thrd_success) {
116         return ZX_ERR_INTERNAL;
117     }
118     return ZX_OK;
119 }
120 
DdkRelease()121 void Mt8167::DdkRelease() {
122     delete this;
123 }
124 
mt8167_bind(void * ctx,zx_device_t * parent)125 zx_status_t mt8167_bind(void* ctx, zx_device_t* parent) {
126     return board_mt8167::Mt8167::Create(parent);
127 }
128 
__anon72ff4dc10202()129 static zx_driver_ops_t driver_ops = [](){
130     zx_driver_ops_t ops;
131     ops.version = DRIVER_OPS_VERSION;
132     ops.bind = mt8167_bind;
133     return ops;
134 }();
135 
136 } // namespace board_mt8167
137 
138 ZIRCON_DRIVER_BEGIN(mt8167, board_mt8167::driver_ops, "zircon", "0.1", 7)
139     BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PBUS),
140     BI_GOTO_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_MEDIATEK, 0),
141     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_MEDIATEK_8167S_REF),
142     BI_LABEL(0),
143     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GOOGLE),
144     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_CLEO),
145     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_EAGLE),
146 ZIRCON_DRIVER_END(mt8167)
147 
148