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