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