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 "sherlock.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 #include <fbl/algorithm.h>
21 #include <fbl/unique_ptr.h>
22
23 namespace sherlock {
24
Create(zx_device_t * parent)25 zx_status_t Sherlock::Create(zx_device_t* parent) {
26 pbus_protocol_t pbus;
27 iommu_protocol_t iommu;
28
29 auto status = device_get_protocol(parent, ZX_PROTOCOL_PBUS, &pbus);
30 if (status != ZX_OK) {
31 return status;
32 }
33
34 status = device_get_protocol(parent, ZX_PROTOCOL_IOMMU, &iommu);
35 if (status != ZX_OK) {
36 return status;
37 }
38
39 fbl::AllocChecker ac;
40 auto board = fbl::make_unique_checked<Sherlock>(&ac, parent, &pbus, &iommu);
41 if (!ac.check()) {
42 return ZX_ERR_NO_MEMORY;
43 }
44
45 status = board->DdkAdd("sherlock", DEVICE_ADD_NON_BINDABLE);
46 if (status != ZX_OK) {
47 return status;
48 }
49
50 // Start up our protocol helpers and platform devices.
51 status = board->Start();
52 if (status == ZX_OK) {
53 // devmgr is now in charge of the device.
54 __UNUSED auto* dummy = board.release();
55 }
56 return status;
57 }
58
Thread()59 int Sherlock::Thread() {
60 // Load protocol implementation drivers first.
61 if (GpioInit() != ZX_OK) {
62 zxlogf(ERROR, "GpioInit() failed\n");
63 return -1;
64 }
65
66 if (ClkInit() != ZX_OK) {
67 zxlogf(ERROR, "ClkInit() failed\n");
68 return -1;
69 }
70
71 if (I2cInit() != ZX_OK) {
72 zxlogf(ERROR, "I2cInit() failed\n");
73 }
74
75 if (CanvasInit() != ZX_OK) {
76 zxlogf(ERROR, "CanvasInit() failed\n");
77 }
78
79 if (DisplayInit() != ZX_OK) {
80 zxlogf(ERROR, "DisplayInit()failed\n");
81 }
82
83 // Then the platform device drivers.
84 if (UsbInit() != ZX_OK) {
85 zxlogf(ERROR, "UsbInit() failed\n");
86 }
87
88 if (EmmcInit() != ZX_OK) {
89 zxlogf(ERROR, "EmmcInit() failed\n");
90 }
91
92 // The BMC43458 chip requires this hardware clock for bluetooth and wifi.
93 // Called here to avoid a dep. between sdio and bluetooth init order.
94 if (BCM43458LpoClockInit() != ZX_OK) {
95 zxlogf(ERROR, "Bcm43458LpoClockInit() failed\n");
96 }
97
98 if (SdioInit() != ZX_OK) {
99 zxlogf(ERROR, "SdioInit() failed\n");
100 }
101
102 if (BluetoothInit() != ZX_OK) {
103 zxlogf(ERROR, "BluetoothInit() failed\n");
104 }
105
106 if (CameraInit() != ZX_OK) {
107 zxlogf(ERROR, "CameraInit() failed\n");
108 }
109
110 if (VideoInit() != ZX_OK) {
111 zxlogf(ERROR, "VideoInit() failed\n");
112 }
113
114 if (MaliInit() != ZX_OK) {
115 zxlogf(ERROR, "MaliInit() failed\n");
116 }
117
118 if (BacklightInit() != ZX_OK) {
119 zxlogf(ERROR, "BacklightInit() failed\n");
120 }
121
122 if (ButtonsInit() != ZX_OK) {
123 zxlogf(ERROR, "ButtonsInit() failed\n");
124 }
125
126 if (AudioInit() != ZX_OK) {
127 zxlogf(ERROR, "AudioInit() failed\n");
128 return -1;
129 }
130 return 0;
131 }
132
Start()133 zx_status_t Sherlock::Start() {
134 int rc = thrd_create_with_name(&thread_,
135 [](void* arg) -> int {
136 return reinterpret_cast<Sherlock*>(arg)->Thread();
137 },
138 this,
139 "sherlock-start-thread");
140 if (rc != thrd_success) {
141 return ZX_ERR_INTERNAL;
142 }
143 return ZX_OK;
144 }
145
DdkRelease()146 void Sherlock::DdkRelease() {
147 delete this;
148 }
149
150 } // namespace sherlock
151
sherlock_bind(void * ctx,zx_device_t * parent)152 zx_status_t sherlock_bind(void* ctx, zx_device_t* parent) {
153 return sherlock::Sherlock::Create(parent);
154 }
155