1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "hdf_log.h"
32 #include "device_resource_if.h"
33 #include "hdf_usb.h"
34
35 #define USB_CONTROLLER_LIST_NAME "controller_list"
36 #define USB_NODE_MATCH_ATTR "hisilicon,hi35xx-xhci"
37 #define USB_MAX_CFG_LEN 8
38 #define USB_CONTROL_NAME_LEN 32
39 #define USB_CFG_UNIT 2
40
41 struct UsbConfig {
42 uint32_t type;
43 uint32_t unit;
44 uint32_t start;
45 uint32_t end;
46 uint32_t count;
47 };
48
49 struct UsbInfo {
50 struct UsbConfig cfg[USB_MAX_CFG_LEN];
51 uint32_t len;
52 };
53
GetHdfUsbNode(const struct DeviceResourceIface * instance)54 static const struct DeviceResourceNode *GetHdfUsbNode(const struct DeviceResourceIface *instance)
55 {
56 const struct DeviceResourceNode *root = instance->GetRootNode();
57
58 if (root == NULL) {
59 HDF_LOGE("%s get root node is null\n", __func__);
60 return NULL;
61 }
62
63 return instance->GetNodeByMatchAttr(root, USB_NODE_MATCH_ATTR);
64 }
65
GetUsbControllerParam(const struct DeviceResourceIface * instance,const struct DeviceResourceNode * node,struct UsbConfig * cfg)66 static int GetUsbControllerParam(const struct DeviceResourceIface *instance, const struct DeviceResourceNode *node,
67 struct UsbConfig *cfg)
68 {
69 int ret;
70
71 ret = instance->GetUint32(node, "res_type", &cfg->type, 0);
72 if (ret != HDF_SUCCESS) {
73 HDF_LOGE("%s: read res_type fail", __func__);
74 return HDF_FAILURE;
75 }
76 ret = instance->GetUint32(node, "res_unit", &cfg->unit, 0);
77 if (ret != HDF_SUCCESS) {
78 HDF_LOGE("%s: read res unit fail", __func__);
79 return HDF_FAILURE;
80 }
81 ret = instance->GetUint32(node, "res_start", &cfg->start, 0);
82 if (ret != HDF_SUCCESS) {
83 HDF_LOGE("%s: read res type fail", __func__);
84 return HDF_FAILURE;
85 }
86 ret = instance->GetUint32(node, "res_end", &cfg->end, 0);
87 if (ret != HDF_SUCCESS) {
88 HDF_LOGE("%s: read res end fail", __func__);
89 return HDF_FAILURE;
90 }
91 ret = instance->GetUint32(node, "res_count", &cfg->count, 0);
92 if (ret != HDF_SUCCESS) {
93 HDF_LOGE("%s: read res count fail", __func__);
94 return HDF_FAILURE;
95 }
96 return HDF_SUCCESS;
97 }
98
ProcControllorParam(const struct DeviceResourceIface * instance,const struct DeviceResourceNode * node,const char * name,add_res_callback_t callback,struct UsbInfo * info)99 static int ProcControllorParam(const struct DeviceResourceIface *instance, const struct DeviceResourceNode *node,
100 const char *name, add_res_callback_t callback, struct UsbInfo *info)
101 {
102 const char *ctrlName = NULL;
103 uint32_t index = 0;
104
105 const struct DeviceResourceNode *subNode = node->child;
106 if (subNode == NULL) {
107 return HDF_FAILURE;
108 }
109
110 DEV_RES_NODE_FOR_EACH_CHILD_NODE(node, subNode) {
111 if (index >= info->len) {
112 break;
113 }
114 struct UsbConfig *cfg = &(info->cfg[index]);
115 int32_t ret = instance->GetString(subNode, "controller", &ctrlName, NULL);
116 if (ret != HDF_SUCCESS) {
117 HDF_LOGE("%s: read res_type fail", __func__);
118 return HDF_FAILURE;
119 }
120
121 if (strcmp(name, ctrlName) != 0) {
122 HDF_LOGI("%s: no match name", __func__);
123 continue;
124 }
125
126 ret = GetUsbControllerParam(instance, subNode, cfg);
127 if (ret != HDF_SUCCESS) {
128 HDF_LOGE("%s: read controller param fail", __func__);
129 return HDF_FAILURE;
130 }
131 callback(name, cfg->type, cfg->unit, cfg->start, cfg->end, cfg->count);
132 index++;
133 }
134
135 return HDF_SUCCESS;
136 }
137
HdfUsbInitParam(device_t dev,add_res_callback_t callback)138 static void HdfUsbInitParam(device_t dev, add_res_callback_t callback)
139 {
140 const struct DeviceResourceIface *devResInstance = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
141 if (devResInstance == NULL) {
142 HDF_LOGE("%s get devResInstance node is null", __func__);
143 return;
144 }
145 const struct DeviceResourceNode *hdfUsbNode = GetHdfUsbNode(devResInstance);
146 if (hdfUsbNode == NULL) {
147 HDF_LOGE("%s get hdf usb node is null", __func__);
148 return;
149 }
150
151 int32_t count = devResInstance->GetElemNum(hdfUsbNode, USB_CONTROLLER_LIST_NAME);
152 if ((count <= 0) || (count > USB_MAX_CFG_LEN / USB_CFG_UNIT)) {
153 HDF_LOGE("%s get elemnum failed", __func__);
154 return;
155 }
156
157 struct UsbInfo info = {0};
158 info.len = USB_MAX_CFG_LEN;
159 const char *ctrlName = NULL;
160 for (int32_t i = 0; i < count; i++) {
161 int32_t ret = devResInstance->GetStringArrayElem(hdfUsbNode, USB_CONTROLLER_LIST_NAME, i, &ctrlName, NULL);
162 if (ret != HDF_SUCCESS) {
163 HDF_LOGE("%s get hdf usb list name fail", __func__);
164 return;
165 }
166
167 device_add_child(dev, ctrlName, 0);
168 ret = ProcControllorParam(devResInstance, hdfUsbNode, ctrlName, callback, &info);
169 if (ret != HDF_SUCCESS) {
170 HDF_LOGI("%s proc usb controllor not match, goto next", __func__);
171 }
172 }
173 }
174
UsbResourceInit(device_t dev,add_res_callback_t callback)175 void UsbResourceInit(device_t dev, add_res_callback_t callback)
176 {
177 if (callback == NULL) {
178 HDF_LOGE("usb resource init failed");
179 return;
180 }
181
182 HdfUsbInitParam(dev, callback);
183 }
184