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 <ddk/debug.h>
6 #include <ddk/metadata.h>
7 #include <ddk/platform-defs.h>
8 #include <ddktl/mmio.h>
9 #include <ddktl/protocol/gpioimpl.h>
10 #include <hw/reg.h>
11 #include <lib/zx/handle.h>
12 #include <soc/aml-common/aml-sd-emmc.h>
13 #include <soc/aml-t931/t931-gpio.h>
14 #include <soc/aml-t931/t931-hw.h>
15 #include <wifi/wifi-config.h>
16
17 #include <optional>
18
19 #include "sherlock.h"
20
21 namespace sherlock {
22
23 namespace {
24
25 constexpr pbus_gpio_t wifi_gpios[] = {
26 {
27 .gpio = T931_WIFI_HOST_WAKE,
28 },
29 };
30
31 constexpr wifi_config_t wifi_config = {
32 .oob_irq_mode = ZX_INTERRUPT_MODE_LEVEL_HIGH,
33 };
34
35 constexpr pbus_metadata_t wifi_metadata[] = {
36 {
37 .type = DEVICE_METADATA_PRIVATE,
38 .data_buffer = &wifi_config,
39 .data_size = sizeof(wifi_config),
40 },
41 };
42
43 constexpr pbus_boot_metadata_t wifi_boot_metadata[] = {
44 {
45 .zbi_type = DEVICE_METADATA_MAC_ADDRESS,
46 .zbi_extra = MACADDR_WIFI,
47 },
48 };
49
50 const pbus_dev_t sdio_children[] = {
__anonbdd75af60202() 51 []() {
52 pbus_dev_t dev;
53 dev.name = "sherlock-wifi";
54 dev.gpio_list = wifi_gpios;
55 dev.gpio_count = countof(wifi_gpios);
56 dev.metadata_list = wifi_metadata;
57 dev.metadata_count = countof(wifi_metadata);
58 dev.boot_metadata_list = wifi_boot_metadata;
59 dev.boot_metadata_count = countof(wifi_boot_metadata);
60 return dev;
61 }(),
62 };
63
64 const pbus_dev_t sd_emmc_children[] = {
__anonbdd75af60302() 65 []() {
66 pbus_dev_t dev;
67 dev.name = "sherlock-sdio";
68 dev.child_list = sdio_children;
69 dev.child_count = countof(sdio_children);
70 return dev;
71 }(),
72 };
73
74 constexpr pbus_mmio_t sd_emmc_mmios[] = {
75 {
76 .base = T931_SD_EMMC_A_BASE,
77 .length = T931_SD_EMMC_A_LENGTH,
78 },
79 };
80
81 constexpr pbus_irq_t sd_emmc_irqs[] = {
82 {
83 .irq = T931_SD_EMMC_A_IRQ,
84 .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
85 },
86 };
87
88 constexpr pbus_bti_t sd_emmc_btis[] = {
89 {
90 .iommu_index = 0,
91 .bti_id = BTI_SDIO,
92 },
93 };
94
95 constexpr pbus_gpio_t sd_emmc_gpios[] = {
96 {
97 .gpio = T931_WIFI_REG_ON,
98 },
99 };
100
101 constexpr aml_sd_emmc_config_t sd_emmc_config = {
102 .supports_dma = false,
103 .min_freq = 500000, // 500KHz
104 .max_freq = 50000000, // 50MHz
105 };
106
107 constexpr pbus_metadata_t sd_emmc_metadata[] = {
108 {
109 .type = DEVICE_METADATA_PRIVATE,
110 .data_buffer = &sd_emmc_config,
111 .data_size = sizeof(sd_emmc_config),
112 },
113 };
114
__anonbdd75af60402() 115 const pbus_dev_t sdio_dev = []() {
116 pbus_dev_t dev;
117 dev.name = "sherlock-sd-emmc";
118 dev.vid = PDEV_VID_AMLOGIC;
119 dev.pid = PDEV_PID_GENERIC;
120 dev.did = PDEV_DID_AMLOGIC_SD_EMMC;
121 dev.mmio_list = sd_emmc_mmios;
122 dev.mmio_count = countof(sd_emmc_mmios);
123 dev.bti_list = sd_emmc_btis;
124 dev.bti_count = countof(sd_emmc_btis);
125 dev.irq_list = sd_emmc_irqs;
126 dev.irq_count = countof(sd_emmc_irqs);
127 dev.gpio_list = sd_emmc_gpios,
128 dev.gpio_count = countof(sd_emmc_gpios);
129 dev.metadata_list = sd_emmc_metadata;
130 dev.metadata_count = countof(sd_emmc_metadata);
131 dev.child_list = sd_emmc_children;
132 dev.child_count = countof(sd_emmc_children);
133 return dev;
134 }();
135
136 } // namespace
137
BCM43458LpoClockInit()138 zx_status_t Sherlock::BCM43458LpoClockInit() {
139 auto status = gpio_impl_.SetAltFunction(T931_WIFI_LPO_CLK, T931_WIFI_LPO_CLK_FN);
140 if (status != ZX_OK) {
141 return status;
142 }
143
144 zx::bti bti;
145 status = iommu_.GetBti(BTI_BOARD, 0, &bti);
146 if (status != ZX_OK) {
147 zxlogf(ERROR, "%s: GetBti() error: %d\n", __func__, status);
148 return status;
149 }
150
151 std::optional<ddk::MmioBuffer> buf;
152 zx::unowned_resource res(get_root_resource());
153 status = ddk::MmioBuffer::Create(T931_PWM_EF_BASE, T931_PWM_LENGTH, *res,
154 ZX_CACHE_POLICY_UNCACHED_DEVICE, &buf);
155 if (status != ZX_OK) {
156 zxlogf(ERROR, "%s: ddk::MmioBuffer::Create() error: %d\n", __func__, status);
157 return status;
158 }
159
160 // Enable PWM_E to satisfy the 32.7KHz LPO clock source.
161 // These values were taken from:
162 // linux/drivers/amlogic/pwm/pwm_meson.c
163 buf->Write32(0x016d016e, T931_PWM_PWM_E);
164 buf->Write32(0x016d016d, T931_PWM_E2);
165 buf->Write32(0x0a0a0609, T931_PWM_TIME_EF);
166 buf->Write32(0x02808003, T931_PWM_MISC_REG_EF);
167
168 return ZX_OK;
169 }
170
SdioInit()171 zx_status_t Sherlock::SdioInit() {
172 zx_status_t status;
173
174 // Configure eMMC-SD soc pads.
175 if (((status = gpio_impl_.SetAltFunction(T931_SDIO_D0, T931_SDIO_D0_FN)) != ZX_OK) ||
176 ((status = gpio_impl_.SetAltFunction(T931_SDIO_D1, T931_SDIO_D1_FN)) != ZX_OK) ||
177 ((status = gpio_impl_.SetAltFunction(T931_SDIO_D2, T931_SDIO_D2_FN)) != ZX_OK) ||
178 ((status = gpio_impl_.SetAltFunction(T931_SDIO_D3, T931_SDIO_D3_FN)) != ZX_OK) ||
179 ((status = gpio_impl_.SetAltFunction(T931_SDIO_CLK, T931_SDIO_CLK_FN)) != ZX_OK) ||
180 ((status = gpio_impl_.SetAltFunction(T931_SDIO_CMD, T931_SDIO_CMD_FN)) != ZX_OK)) {
181 return status;
182 }
183
184 status = gpio_impl_.SetAltFunction(T931_WIFI_REG_ON, T931_WIFI_REG_ON_FN);
185 if (status != ZX_OK) {
186 return status;
187 }
188
189 status = gpio_impl_.SetAltFunction(T931_WIFI_HOST_WAKE, T931_WIFI_HOST_WAKE_FN);
190 if (status != ZX_OK) {
191 return status;
192 }
193
194 status = pbus_.DeviceAdd(&sdio_dev);
195 if (status != ZX_OK) {
196 zxlogf(ERROR, "%s: DeviceAdd() error: %d\n", __func__, status);
197 return status;
198 }
199 return ZX_OK;
200 }
201
202 } // namespace sherlock
203