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 <limits.h>
6
7 #include <ddk/debug.h>
8 #include <ddk/device.h>
9 #include <ddk/platform-defs.h>
10 #include <ddk/protocol/platform/bus.h>
11 #include <ddktl/mmio.h>
12 #include <fbl/algorithm.h>
13 #include <hwreg/bitfields.h>
14 #include <soc/mt8167/mt8167-hw.h>
15
16 #include "mt8167.h"
17
18 namespace {
19
20 constexpr uintptr_t kPmicBaseAligned =
21 fbl::round_down<uintptr_t, uintptr_t>(MT8167_PMIC_WRAP_BASE, PAGE_SIZE);
22 constexpr size_t kPmicOffset = MT8167_PMIC_WRAP_BASE - kPmicBaseAligned;
23 constexpr size_t kPmicSizeAligned =
24 fbl::round_up<size_t, size_t>(kPmicOffset + MT8167_PMIC_WRAP_SIZE, PAGE_SIZE);
25
26 constexpr uint32_t kDigLdoCon7 = 0x285;
27 constexpr uint16_t kVgp1Enable = 0x8000;
28
29 } // namespace
30
31 namespace board_mt8167 {
32
33 class PmicCmd : public hwreg::RegisterBase<PmicCmd, uint32_t> {
34 public:
Get()35 static auto Get() { return hwreg::RegisterAddr<PmicCmd>(0xa0 + kPmicOffset); }
36
37 DEF_BIT(31, write);
38 DEF_FIELD(30, 16, addr);
39 DEF_FIELD(15, 0, data);
40 };
41
42 class PmicReadData : public hwreg::RegisterBase<PmicReadData, uint32_t> {
43 public:
44 static constexpr uint32_t kStateIdle = 0;
45
Get()46 static auto Get() { return hwreg::RegisterAddr<PmicReadData>(0xa4 + kPmicOffset); }
47
48 DEF_FIELD(18, 16, status);
49 };
50
TouchInit()51 zx_status_t Mt8167::TouchInit() {
52 if (board_info_.vid != PDEV_VID_GOOGLE || board_info_.pid != PDEV_PID_CLEO) {
53 return ZX_OK;
54 }
55
56 static constexpr pbus_gpio_t touch_gpios[] = {
57 {
58 .gpio = MT8167_GPIO_TOUCH_INT
59 },
60 {
61 .gpio = MT8167_GPIO_TOUCH_RST
62 },
63 };
64
65 static constexpr pbus_i2c_channel_t touch_i2cs[] = {
66 {
67 .bus_id = 0,
68 .address = 0x38
69 },
70 };
71
72 pbus_dev_t touch_dev = {};
73 touch_dev.name = "touch";
74 touch_dev.vid = PDEV_VID_GENERIC;
75 touch_dev.did = PDEV_DID_FOCALTOUCH;
76 touch_dev.i2c_channel_list = touch_i2cs;
77 touch_dev.i2c_channel_count = countof(touch_i2cs);
78 touch_dev.gpio_list = touch_gpios;
79 touch_dev.gpio_count = countof(touch_gpios);
80
81 zx::unowned_resource root_resource(get_root_resource());
82 std::optional<ddk::MmioBuffer> pmic_mmio;
83 auto status = ddk::MmioBuffer::Create(kPmicBaseAligned, kPmicSizeAligned, *root_resource,
84 ZX_CACHE_POLICY_UNCACHED_DEVICE, &pmic_mmio);
85 if (status != ZX_OK) {
86 zxlogf(ERROR, "%s: Failed to enable VGP1 regulator: %d\n", __FUNCTION__, status);
87 return status;
88 }
89
90 while (PmicReadData::Get().ReadFrom(&(*pmic_mmio)).status() != PmicReadData::kStateIdle) {}
91
92 PmicCmd::Get()
93 .FromValue(0)
94 .set_write(1)
95 .set_addr(kDigLdoCon7)
96 .set_data(kVgp1Enable)
97 .WriteTo(&(*pmic_mmio));
98
99 if ((status = pbus_.DeviceAdd(&touch_dev)) != ZX_OK) {
100 zxlogf(ERROR, "%s: Failed to add touch device: %d\n", __FUNCTION__, status);
101 }
102
103 return status;
104 }
105
106 } // namespace board_mt8167
107