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/device.h>
7 #include <ddk/metadata.h>
8 #include <ddk/metadata/camera.h>
9 #include <ddk/platform-defs.h>
10 #include <ddktl/protocol/gpioimpl.h>
11 #include <fbl/unique_ptr.h>
12 #include <hw/reg.h>
13 #include <soc/aml-meson/g12b-clk.h>
14 #include <soc/aml-t931/t931-gpio.h>
15 #include <soc/aml-t931/t931-hw.h>
16 
17 #include "sherlock.h"
18 
19 namespace sherlock {
20 
21 namespace {
22 
23 constexpr uint32_t kClk24MAltFunc = 7;
24 constexpr uint32_t kI2cSDAAltFunc = 2;
25 constexpr uint32_t kI2cSCLAltFunc = 2;
26 
27 constexpr pbus_mmio_t mipi_mmios[] = {
28     // CSI PHY0
29     {
30         .base = T931_CSI_PHY0_BASE,
31         .length = T931_CSI_PHY0_LENGTH,
32     },
33     // Analog PHY
34     {
35         .base = T931_APHY_BASE,
36         .length = T931_APHY_LENGTH,
37     },
38     // CSI HOST0
39     {
40         .base = T931_CSI_HOST0_BASE,
41         .length = T931_CSI_HOST0_LENGTH,
42     },
43     // MIPI Adapter
44     {
45         .base = T931_MIPI_ADAPTER_BASE,
46         .length = T931_MIPI_ADAPTER_LENGTH,
47     },
48     // HIU for clocks.
49     {
50         .base = T931_HIU_BASE,
51         .length = T931_HIU_LENGTH,
52     },
53     // Power domain
54     {
55         .base = T931_POWER_DOMAIN_BASE,
56         .length = T931_POWER_DOMAIN_LENGTH,
57     },
58     // Memory PD
59     {
60         .base = T931_MEMORY_PD_BASE,
61         .length = T931_MEMORY_PD_LENGTH,
62     },
63     // Reset
64     {
65         .base = T931_RESET_BASE,
66         .length = T931_RESET_LENGTH,
67     },
68 };
69 
70 constexpr camera_sensor_t mipi_sensor[] = {
71     {
72         .vid = PDEV_VID_SONY,
73         .pid = PDEV_PID_SONY_IMX227,
74         .did = PDEV_DID_CAMERA_SENSOR,
75     },
76 };
77 
78 constexpr pbus_bti_t mipi_btis[] = {
79     {
80         .iommu_index = 0,
81         .bti_id = BTI_CAMERA,
82     },
83 };
84 
85 constexpr pbus_irq_t mipi_irqs[] = {
86     {
87         .irq = T931_MIPI_ADAPTER_IRQ,
88         .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
89     }};
90 
91 constexpr pbus_metadata_t mipi_metadata[] = {
92     {
93         .type = DEVICE_METADATA_PRIVATE,
94         .data_buffer = &mipi_sensor,
95         .data_size = sizeof(camera_sensor_t),
96     },
97 };
98 
99 constexpr pbus_i2c_channel_t sensor_i2c[] = {
100     {
101         .bus_id = SHERLOCK_I2C_3,
102         .address = 0x36,
103     },
104 };
105 
106 constexpr pbus_gpio_t sensor_gpios[] = {
107     {
108         // vana-enable
109         .gpio = T931_GPIOA(6),
110     },
111     {
112         // vdig-enable
113         .gpio = T931_GPIOZ(12),
114     },
115     {
116         // camera sensor reset
117         .gpio = T931_GPIOZ(0),
118     },
119 };
120 
121 static const pbus_clk_t sensor_clk_gates[] = {
122     {
123         .clk = G12B_CLK_CAM_INCK_24M,
124     },
125 };
126 
__anon4092bfb00202() 127 static const pbus_dev_t mipi_children = []() {
128     // Sony IMX 227 Camera Sensor
129     pbus_dev_t dev;
130     dev.name = "imx227";
131     dev.i2c_channel_list = sensor_i2c;
132     dev.i2c_channel_count = countof(sensor_i2c);
133     dev.gpio_list = sensor_gpios;
134     dev.gpio_count = countof(sensor_gpios);
135     dev.clk_list = sensor_clk_gates;
136     dev.clk_count = countof(sensor_clk_gates);
137     return dev;
138 }();
139 
__anon4092bfb00302() 140 static pbus_dev_t mipi_dev = []() {
141     pbus_dev_t dev;
142     dev.name = "mipi-csi2";
143     dev.vid = PDEV_VID_AMLOGIC;
144     dev.pid = PDEV_PID_AMLOGIC_T931;
145     dev.did = PDEV_DID_AMLOGIC_MIPI;
146     dev.mmio_list = mipi_mmios;
147     dev.mmio_count = countof(mipi_mmios);
148     dev.metadata_list = mipi_metadata;
149     dev.metadata_count = countof(mipi_metadata);
150     dev.child_list = &mipi_children;
151     dev.child_count = 1;
152     dev.bti_list = mipi_btis;
153     dev.bti_count = countof(mipi_btis);
154     dev.irq_list = mipi_irqs;
155     dev.irq_count = countof(mipi_irqs);
156     return dev;
157 }();
158 
159 } // namespace
160 
CameraInit()161 zx_status_t Sherlock::CameraInit() {
162 
163     // Set GPIO alternate functions.
164     gpio_impl_.SetAltFunction(T931_GPIOAO(10), kClk24MAltFunc);
165 
166     gpio_impl_.SetAltFunction(T931_GPIOA(14), kI2cSDAAltFunc);
167     gpio_impl_.SetAltFunction(T931_GPIOA(15), kI2cSCLAltFunc);
168 
169     zx_status_t status = pbus_.DeviceAdd(&mipi_dev);
170     if (status != ZX_OK) {
171         zxlogf(ERROR, "%s: DeviceAdd failed %d\n", __func__, status);
172         return status;
173     }
174 
175     return status;
176 }
177 
178 } // namespace sherlock
179