1 /*
2 * Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include "dm_services.h"
27
28 #include "include/gpio_interface.h"
29 #include "include/gpio_types.h"
30 #include "hw_gpio.h"
31 #include "hw_ddc.h"
32
33 #include "reg_helper.h"
34 #include "gpio_regs.h"
35
36
37 #undef FN
38 #define FN(reg_name, field_name) \
39 gpio_reg_shift(ddc->shifts->field_name), ddc->masks->field_name
40
41 #define CTX \
42 ddc->base.base.ctx
43 #define REG(reg)\
44 (ddc->regs->reg)
45
46 struct gpio;
47
dal_hw_ddc_destruct(struct hw_ddc * pin)48 static void dal_hw_ddc_destruct(
49 struct hw_ddc *pin)
50 {
51 dal_hw_gpio_destruct(&pin->base);
52 }
53
dal_hw_ddc_destroy(struct hw_gpio_pin ** ptr)54 static void dal_hw_ddc_destroy(
55 struct hw_gpio_pin **ptr)
56 {
57 struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr);
58
59 dal_hw_ddc_destruct(pin);
60
61 kfree(pin);
62
63 *ptr = NULL;
64 }
65
set_config(struct hw_gpio_pin * ptr,const struct gpio_config_data * config_data)66 static enum gpio_result set_config(
67 struct hw_gpio_pin *ptr,
68 const struct gpio_config_data *config_data)
69 {
70 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
71 struct hw_gpio *hw_gpio = NULL;
72 uint32_t regval;
73 uint32_t ddc_data_pd_en = 0;
74 uint32_t ddc_clk_pd_en = 0;
75 uint32_t aux_pad_mode = 0;
76
77 hw_gpio = &ddc->base;
78
79 if (hw_gpio == NULL) {
80 ASSERT_CRITICAL(false);
81 return GPIO_RESULT_NULL_HANDLE;
82 }
83
84 regval = REG_GET_3(gpio.MASK_reg,
85 DC_GPIO_DDC1DATA_PD_EN, &ddc_data_pd_en,
86 DC_GPIO_DDC1CLK_PD_EN, &ddc_clk_pd_en,
87 AUX_PAD1_MODE, &aux_pad_mode);
88
89 switch (config_data->config.ddc.type) {
90 case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
91 /* On plug-in, there is a transient level on the pad
92 * which must be discharged through the internal pull-down.
93 * Enable internal pull-down, 2.5msec discharge time
94 * is required for detection of AUX mode */
95 if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) {
96 if (!ddc_data_pd_en || !ddc_clk_pd_en) {
97 if (hw_gpio->base.en == GPIO_DDC_LINE_DDC_VGA) {
98 // bit 4 of mask has different usage in some cases
99 REG_SET(gpio.MASK_reg, regval, DC_GPIO_DDC1DATA_PD_EN, 1);
100 } else {
101 REG_SET_2(gpio.MASK_reg, regval,
102 DC_GPIO_DDC1DATA_PD_EN, 1,
103 DC_GPIO_DDC1CLK_PD_EN, 1);
104 }
105 if (config_data->type ==
106 GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
107 msleep(3);
108 }
109 } else {
110 uint32_t sda_pd_dis = 0;
111 uint32_t scl_pd_dis = 0;
112
113 REG_GET_2(gpio.MASK_reg,
114 DC_GPIO_SDA_PD_DIS, &sda_pd_dis,
115 DC_GPIO_SCL_PD_DIS, &scl_pd_dis);
116
117 if (sda_pd_dis) {
118 REG_SET(gpio.MASK_reg, regval,
119 DC_GPIO_SDA_PD_DIS, 0);
120
121 if (config_data->type ==
122 GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
123 msleep(3);
124 }
125
126 if (!scl_pd_dis) {
127 REG_SET(gpio.MASK_reg, regval,
128 DC_GPIO_SCL_PD_DIS, 1);
129
130 if (config_data->type ==
131 GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
132 msleep(3);
133 }
134 }
135
136 if (aux_pad_mode) {
137 /* let pins to get de-asserted
138 * before setting pad to I2C mode */
139 if (config_data->config.ddc.data_en_bit_present ||
140 config_data->config.ddc.clock_en_bit_present)
141 /* [anaumov] in DAL2, there was
142 * dc_service_delay_in_microseconds(2000); */
143 msleep(2);
144
145 /* set the I2C pad mode */
146 /* read the register again,
147 * some bits may have been changed */
148 REG_UPDATE(gpio.MASK_reg,
149 AUX_PAD1_MODE, 0);
150 }
151
152 if (ddc->regs->dc_gpio_aux_ctrl_5 != 0) {
153 REG_UPDATE(dc_gpio_aux_ctrl_5, DDC_PAD_I2CMODE, 1);
154 }
155 //set DC_IO_aux_rxsel = 2'b01
156 if (ddc->regs->phy_aux_cntl != 0) {
157 REG_UPDATE(phy_aux_cntl, AUX_PAD_RXSEL, 1);
158 }
159 return GPIO_RESULT_OK;
160 case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
161 /* set the AUX pad mode */
162 if (!aux_pad_mode) {
163 REG_SET(gpio.MASK_reg, regval,
164 AUX_PAD1_MODE, 1);
165 }
166 if (ddc->regs->dc_gpio_aux_ctrl_5 != 0) {
167 REG_UPDATE(dc_gpio_aux_ctrl_5,
168 DDC_PAD_I2CMODE, 0);
169 }
170
171 return GPIO_RESULT_OK;
172 case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
173 if (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA) {
174 REG_UPDATE_3(ddc_setup,
175 DC_I2C_DDC1_ENABLE, 1,
176 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
177 DC_I2C_DDC1_EDID_DETECT_MODE, 0);
178 return GPIO_RESULT_OK;
179 }
180 break;
181 case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
182 if (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA) {
183 REG_UPDATE_3(ddc_setup,
184 DC_I2C_DDC1_ENABLE, 1,
185 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
186 DC_I2C_DDC1_EDID_DETECT_MODE, 1);
187 return GPIO_RESULT_OK;
188 }
189 break;
190 case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
191 if (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA) {
192 REG_UPDATE_2(ddc_setup,
193 DC_I2C_DDC1_ENABLE, 0,
194 DC_I2C_DDC1_EDID_DETECT_ENABLE, 0);
195 return GPIO_RESULT_OK;
196 }
197 break;
198 }
199
200 BREAK_TO_DEBUGGER();
201
202 return GPIO_RESULT_NON_SPECIFIC_ERROR;
203 }
204
205 static const struct hw_gpio_pin_funcs funcs = {
206 .destroy = dal_hw_ddc_destroy,
207 .open = dal_hw_gpio_open,
208 .get_value = dal_hw_gpio_get_value,
209 .set_value = dal_hw_gpio_set_value,
210 .set_config = set_config,
211 .change_mode = dal_hw_gpio_change_mode,
212 .close = dal_hw_gpio_close,
213 };
214
dal_hw_ddc_construct(struct hw_ddc * ddc,enum gpio_id id,uint32_t en,struct dc_context * ctx)215 static void dal_hw_ddc_construct(
216 struct hw_ddc *ddc,
217 enum gpio_id id,
218 uint32_t en,
219 struct dc_context *ctx)
220 {
221 dal_hw_gpio_construct(&ddc->base, id, en, ctx);
222 ddc->base.base.funcs = &funcs;
223 }
224
dal_hw_ddc_init(struct hw_ddc ** hw_ddc,struct dc_context * ctx,enum gpio_id id,uint32_t en)225 void dal_hw_ddc_init(
226 struct hw_ddc **hw_ddc,
227 struct dc_context *ctx,
228 enum gpio_id id,
229 uint32_t en)
230 {
231 if (en > GPIO_DDC_LINE_MAX) {
232 ASSERT_CRITICAL(false);
233 *hw_ddc = NULL;
234 }
235
236 *hw_ddc = kzalloc_obj(struct hw_ddc);
237 if (!*hw_ddc) {
238 ASSERT_CRITICAL(false);
239 return;
240 }
241
242 dal_hw_ddc_construct(*hw_ddc, id, en, ctx);
243 }
244
dal_hw_ddc_get_pin(struct gpio * gpio)245 struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio)
246 {
247 struct hw_ddc *hw_ddc = dal_gpio_get_ddc(gpio);
248
249 return &hw_ddc->base.base;
250 }
251
store_registers_ddc_i3cpad(struct hw_ddc * ddc)252 static void store_registers_ddc_i3cpad(
253 struct hw_ddc *ddc)
254 {
255 switch (ddc->base.base.id) {
256 case GPIO_ID_DDC_DATA:
257 REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, &ddc->base.store.mask);
258 REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_A, &ddc->base.store.a);
259 REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, &ddc->base.store.en);
260 break;
261 case GPIO_ID_DDC_CLOCK:
262 REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, &ddc->base.store.mask);
263 REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_A, &ddc->base.store.a);
264 REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, &ddc->base.store.en);
265 break;
266 default:
267 break;
268 }
269 }
270
restore_registers_ddc_i3cpad(struct hw_ddc * ddc)271 static void restore_registers_ddc_i3cpad(
272 struct hw_ddc *ddc)
273 {
274 switch (ddc->base.base.id) {
275 case GPIO_ID_DDC_DATA:
276 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, ddc->base.store.mask);
277 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, ddc->base.store.a);
278 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, ddc->base.store.en);
279 break;
280 case GPIO_ID_DDC_CLOCK:
281 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, ddc->base.store.mask);
282 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, ddc->base.store.a);
283 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, ddc->base.store.en);
284 break;
285 default:
286 break;
287 }
288 }
289
dal_hw_ddc_open_i3cpad(struct hw_gpio_pin * ptr,enum gpio_mode mode)290 bool dal_hw_ddc_open_i3cpad(
291 struct hw_gpio_pin *ptr,
292 enum gpio_mode mode)
293 {
294 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
295
296 store_registers_ddc_i3cpad(ddc);
297
298 ptr->opened = (dal_hw_ddc_config_mode_i3cpad(ddc, mode) == GPIO_RESULT_OK);
299
300 return ptr->opened;
301 }
302
dal_hw_ddc_get_value_i3cpad(const struct hw_gpio_pin * ptr,uint32_t * value)303 enum gpio_result dal_hw_ddc_get_value_i3cpad(
304 const struct hw_gpio_pin *ptr,
305 uint32_t *value)
306 {
307 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
308 enum gpio_result result = GPIO_RESULT_OK;
309
310 switch (ptr->mode) {
311 case GPIO_MODE_INPUT:
312 case GPIO_MODE_OUTPUT:
313 case GPIO_MODE_HARDWARE:
314 case GPIO_MODE_FAST_OUTPUT:
315 switch (ddc->base.base.id) {
316 case GPIO_ID_DDC_DATA:
317 REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_Y, value);
318 break;
319 case GPIO_ID_DDC_CLOCK:
320 REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_Y, value);
321 break;
322 default:
323 break;
324 }
325 break;
326 default:
327 result = GPIO_RESULT_NON_SPECIFIC_ERROR;
328 }
329 return result;
330 }
331
dal_hw_ddc_set_value_i3cpad(const struct hw_gpio_pin * ptr,uint32_t value)332 enum gpio_result dal_hw_ddc_set_value_i3cpad(
333 const struct hw_gpio_pin *ptr,
334 uint32_t value)
335 {
336 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
337
338 switch (ptr->mode) {
339 case GPIO_MODE_OUTPUT:
340 switch (ddc->base.base.id) {
341 case GPIO_ID_DDC_DATA:
342 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, value);
343 break;
344 case GPIO_ID_DDC_CLOCK:
345 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, value);
346 break;
347 default:
348 break;
349 }
350 return GPIO_RESULT_OK;
351 case GPIO_MODE_FAST_OUTPUT:
352 /* We use (EN) to faster switch (used in DDC GPIO).
353 * So (A) is grounded, output is driven by (EN = 0)
354 * to pull the line down (output == 0) and (EN=1)
355 * then output is tri-state */
356 switch (ddc->base.base.id) {
357 case GPIO_ID_DDC_DATA:
358 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, value);
359 break;
360 case GPIO_ID_DDC_CLOCK:
361 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, value);
362 break;
363 default:
364 break;
365 }
366 return GPIO_RESULT_OK;
367 default:
368 return GPIO_RESULT_NON_SPECIFIC_ERROR;
369 }
370 }
371
dal_hw_ddc_change_mode_i3cpad(struct hw_gpio_pin * ptr,enum gpio_mode mode)372 enum gpio_result dal_hw_ddc_change_mode_i3cpad(
373 struct hw_gpio_pin *ptr,
374 enum gpio_mode mode)
375 {
376 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
377
378 return dal_hw_ddc_config_mode_i3cpad(ddc, mode);
379 }
380
dal_hw_ddc_config_mode_i3cpad(struct hw_ddc * ddc,enum gpio_mode mode)381 enum gpio_result dal_hw_ddc_config_mode_i3cpad(
382 struct hw_ddc *ddc,
383 enum gpio_mode mode)
384 {
385 ddc->base.base.mode = mode;
386
387 switch (mode) {
388 case GPIO_MODE_INPUT:
389 /* turn off output enable, act as input pin;
390 * program the pin as GPIO, mask out signal driven by HW
391 */
392 switch (ddc->base.base.id) {
393 case GPIO_ID_DDC_DATA:
394 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, 0);
395 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
396 break;
397 case GPIO_ID_DDC_CLOCK:
398 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, 0);
399 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
400 break;
401 default:
402 break;
403 }
404 return GPIO_RESULT_OK;
405
406 case GPIO_MODE_OUTPUT:
407 /* turn on output enable, act as output pin;
408 * program the pin as GPIO, mask out signal driven by HW
409 */
410 switch (ddc->base.base.id) {
411 case GPIO_ID_DDC_DATA:
412 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0);
413 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
414 break;
415 case GPIO_ID_DDC_CLOCK:
416 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0);
417 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
418 break;
419 default:
420 break;
421 }
422 return GPIO_RESULT_OK;
423
424 case GPIO_MODE_FAST_OUTPUT:
425 /* grounding the A register then use the EN register bit
426 * will have faster effect on the rise time
427 */
428 switch (ddc->base.base.id) {
429 case GPIO_ID_DDC_DATA:
430 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0);
431 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
432 break;
433 case GPIO_ID_DDC_CLOCK:
434 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0);
435 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
436 break;
437 default:
438 break;
439 }
440 return GPIO_RESULT_OK;
441
442 case GPIO_MODE_HARDWARE:
443 /* program the pin as tri-state, pin is driven by HW */
444 switch (ddc->base.base.id) {
445 case GPIO_ID_DDC_DATA:
446 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 0);
447 break;
448 case GPIO_ID_DDC_CLOCK:
449 REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 0);
450 break;
451 default:
452 break;
453 }
454 return GPIO_RESULT_OK;
455
456 default:
457 case GPIO_MODE_INTERRUPT:
458 /* Interrupt mode supported only by HPD (IrqGpio) old pins. */
459 return GPIO_RESULT_NON_SPECIFIC_ERROR;
460 }
461 }
462
dal_hw_ddc_set_config_i3cpad(struct hw_gpio_pin * ptr,const struct gpio_config_data * config_data)463 static enum gpio_result dal_hw_ddc_set_config_i3cpad(
464 struct hw_gpio_pin *ptr,
465 const struct gpio_config_data *config_data)
466 {
467 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
468
469 switch (config_data->config.ddc.type) {
470 /* For ASICs with i3cpad module there is no dual pad mode for i3cpads */
471 case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
472 /* Enable the RX for the PAD (it is disabled by default). */
473 REG_UPDATE(dc_i3cpad_control1, DC_I3CPAD_RXSEL, 0);
474 return GPIO_RESULT_OK;
475 case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
476 return GPIO_RESULT_OK;
477
478 case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
479 REG_UPDATE_3(ddc_setup,
480 DC_I2C_DDC1_ENABLE, 1,
481 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
482 DC_I2C_DDC1_EDID_DETECT_MODE, 0);
483 return GPIO_RESULT_OK;
484
485 case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
486 REG_UPDATE_3(ddc_setup,
487 DC_I2C_DDC1_ENABLE, 1,
488 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
489 DC_I2C_DDC1_EDID_DETECT_MODE, 1);
490 return GPIO_RESULT_OK;
491
492 case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
493 REG_UPDATE_2(ddc_setup,
494 DC_I2C_DDC1_ENABLE, 0,
495 DC_I2C_DDC1_EDID_DETECT_ENABLE, 0);
496 return GPIO_RESULT_OK;
497 }
498
499 BREAK_TO_DEBUGGER();
500 return GPIO_RESULT_NON_SPECIFIC_ERROR;
501 }
502
dal_hw_ddc_close_i3cpad(struct hw_gpio_pin * ptr)503 void dal_hw_ddc_close_i3cpad(
504 struct hw_gpio_pin *ptr)
505 {
506 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
507
508 restore_registers_ddc_i3cpad(ddc);
509
510 ptr->mode = GPIO_MODE_UNKNOWN;
511 ptr->opened = false;
512 }
513
514 static const struct hw_gpio_pin_funcs funcs_i3cpad = {
515 .destroy = dal_hw_ddc_destroy,
516 .open = dal_hw_ddc_open_i3cpad,
517 .get_value = dal_hw_ddc_get_value_i3cpad,
518 .set_value = dal_hw_ddc_set_value_i3cpad,
519 .set_config = dal_hw_ddc_set_config_i3cpad,
520 .change_mode = dal_hw_ddc_change_mode_i3cpad,
521 .close = dal_hw_ddc_close_i3cpad,
522 };
523
dal_hw_ddc_construct_i3cpad(struct hw_ddc * ddc,enum gpio_id id,uint32_t en,struct dc_context * ctx)524 static void dal_hw_ddc_construct_i3cpad(
525 struct hw_ddc *ddc,
526 enum gpio_id id,
527 uint32_t en,
528 struct dc_context *ctx)
529 {
530 dal_hw_gpio_construct(&ddc->base, id, en, ctx);
531 ddc->base.base.funcs = &funcs_i3cpad;
532 }
533
dal_hw_ddc_init_i3cpad(struct hw_ddc ** hw_ddc,struct dc_context * ctx,enum gpio_id id,uint32_t en)534 void dal_hw_ddc_init_i3cpad(
535 struct hw_ddc **hw_ddc,
536 struct dc_context *ctx,
537 enum gpio_id id,
538 uint32_t en)
539 {
540 if (en > GPIO_DDC_LINE_MAX) {
541 ASSERT_CRITICAL(false);
542 *hw_ddc = NULL;
543 }
544
545 *hw_ddc = kzalloc_obj(struct hw_ddc);
546 if (!*hw_ddc) {
547 ASSERT_CRITICAL(false);
548 return;
549 }
550
551 dal_hw_ddc_construct_i3cpad(*hw_ddc, id, en, ctx);
552 }
553