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 /*
27  * Pre-requisites: headers required by header of this unit
28  */
29 
30 #include "dm_services.h"
31 #include "include/gpio_interface.h"
32 #include "include/gpio_service_interface.h"
33 #include "hw_translate.h"
34 #include "hw_factory.h"
35 
36 /*
37  * Header of this unit
38  */
39 
40 #include "gpio_service.h"
41 
42 /*
43  * Post-requisites: headers required by this unit
44  */
45 
46 #include "hw_gpio.h"
47 
48 /*
49  * @brief
50  * Public API.
51  */
52 
53 struct gpio_service *dal_gpio_service_create(
54 	enum dce_version dce_version_major,
55 	enum dce_version dce_version_minor,
56 	struct dc_context *ctx)
57 {
58 	struct gpio_service *service;
59 	uint32_t index_of_id;
60 
61 	service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
62 
63 	if (!service) {
64 		BREAK_TO_DEBUGGER();
65 		return NULL;
66 	}
67 
68 	if (!dal_hw_translate_init(&service->translate, dce_version_major,
69 			dce_version_minor)) {
70 		BREAK_TO_DEBUGGER();
71 		goto failure_1;
72 	}
73 
74 	if (!dal_hw_factory_init(&service->factory, dce_version_major,
75 			dce_version_minor)) {
76 		BREAK_TO_DEBUGGER();
77 		goto failure_1;
78 	}
79 
80 	/* allocate and initialize busyness storage */
81 	{
82 		index_of_id = 0;
83 		service->ctx = ctx;
84 
85 		do {
86 			uint32_t number_of_bits =
87 				service->factory.number_of_pins[index_of_id];
88 			uint32_t i = 0;
89 
90 			if (number_of_bits)  {
91 				service->busyness[index_of_id] =
92 					kcalloc(number_of_bits, sizeof(char),
93 						GFP_KERNEL);
94 
95 				if (!service->busyness[index_of_id]) {
96 					BREAK_TO_DEBUGGER();
97 					goto failure_2;
98 				}
99 
100 				do {
101 					service->busyness[index_of_id][i] = 0;
102 					++i;
103 				} while (i < number_of_bits);
104 			} else {
105 				service->busyness[index_of_id] = NULL;
106 			}
107 
108 			++index_of_id;
109 		} while (index_of_id < GPIO_ID_COUNT);
110 	}
111 
112 	return service;
113 
114 failure_2:
115 	while (index_of_id) {
116 		--index_of_id;
117 		kfree(service->busyness[index_of_id]);
118 	}
119 
120 failure_1:
121 	kfree(service);
122 
123 	return NULL;
124 }
125 
126 struct gpio *dal_gpio_service_create_irq(
127 	struct gpio_service *service,
128 	uint32_t offset,
129 	uint32_t mask)
130 {
131 	enum gpio_id id;
132 	uint32_t en;
133 
134 	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
135 		ASSERT_CRITICAL(false);
136 		return NULL;
137 	}
138 
139 	return dal_gpio_create_irq(service, id, en);
140 }
141 
142 void dal_gpio_service_destroy(
143 	struct gpio_service **ptr)
144 {
145 	if (!ptr || !*ptr) {
146 		BREAK_TO_DEBUGGER();
147 		return;
148 	}
149 
150 	/* free business storage */
151 	{
152 		uint32_t index_of_id = 0;
153 
154 		do {
155 			kfree((*ptr)->busyness[index_of_id]);
156 
157 			++index_of_id;
158 		} while (index_of_id < GPIO_ID_COUNT);
159 	}
160 
161 	kfree(*ptr);
162 
163 	*ptr = NULL;
164 }
165 
166 /*
167  * @brief
168  * Private API.
169  */
170 
171 static bool is_pin_busy(
172 	const struct gpio_service *service,
173 	enum gpio_id id,
174 	uint32_t en)
175 {
176 	return service->busyness[id][en];
177 }
178 
179 static void set_pin_busy(
180 	struct gpio_service *service,
181 	enum gpio_id id,
182 	uint32_t en)
183 {
184 	service->busyness[id][en] = true;
185 }
186 
187 static void set_pin_free(
188 	struct gpio_service *service,
189 	enum gpio_id id,
190 	uint32_t en)
191 {
192 	service->busyness[id][en] = false;
193 }
194 
195 enum gpio_result dal_gpio_service_lock(
196 	struct gpio_service *service,
197 	enum gpio_id id,
198 	uint32_t en)
199 {
200 	if (!service->busyness[id]) {
201 		ASSERT_CRITICAL(false);
202 		return GPIO_RESULT_OPEN_FAILED;
203 	}
204 
205 	set_pin_busy(service, id, en);
206 	return GPIO_RESULT_OK;
207 }
208 
209 enum gpio_result dal_gpio_service_unlock(
210 	struct gpio_service *service,
211 	enum gpio_id id,
212 	uint32_t en)
213 {
214 	if (!service->busyness[id]) {
215 		ASSERT_CRITICAL(false);
216 		return GPIO_RESULT_OPEN_FAILED;
217 	}
218 
219 	set_pin_free(service, id, en);
220 	return GPIO_RESULT_OK;
221 }
222 
223 enum gpio_result dal_gpio_service_open(
224 	struct gpio_service *service,
225 	enum gpio_id id,
226 	uint32_t en,
227 	enum gpio_mode mode,
228 	struct hw_gpio_pin **ptr)
229 {
230 	struct hw_gpio_pin *pin;
231 
232 	if (!service->busyness[id]) {
233 		ASSERT_CRITICAL(false);
234 		return GPIO_RESULT_OPEN_FAILED;
235 	}
236 
237 	if (is_pin_busy(service, id, en)) {
238 		ASSERT_CRITICAL(false);
239 		return GPIO_RESULT_DEVICE_BUSY;
240 	}
241 
242 	switch (id) {
243 	case GPIO_ID_DDC_DATA:
244 		pin = service->factory.funcs->create_ddc_data(
245 			service->ctx, id, en);
246 		service->factory.funcs->define_ddc_registers(pin, en);
247 	break;
248 	case GPIO_ID_DDC_CLOCK:
249 		pin = service->factory.funcs->create_ddc_clock(
250 			service->ctx, id, en);
251 		service->factory.funcs->define_ddc_registers(pin, en);
252 	break;
253 	case GPIO_ID_GENERIC:
254 		pin = service->factory.funcs->create_generic(
255 			service->ctx, id, en);
256 	break;
257 	case GPIO_ID_HPD:
258 		pin = service->factory.funcs->create_hpd(
259 			service->ctx, id, en);
260 		service->factory.funcs->define_hpd_registers(pin, en);
261 	break;
262 	case GPIO_ID_SYNC:
263 		pin = service->factory.funcs->create_sync(
264 			service->ctx, id, en);
265 	break;
266 	case GPIO_ID_GSL:
267 		pin = service->factory.funcs->create_gsl(
268 			service->ctx, id, en);
269 	break;
270 	default:
271 		ASSERT_CRITICAL(false);
272 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
273 	}
274 
275 	if (!pin) {
276 		ASSERT_CRITICAL(false);
277 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
278 	}
279 
280 	if (!pin->funcs->open(pin, mode)) {
281 		ASSERT_CRITICAL(false);
282 		dal_gpio_service_close(service, &pin);
283 		return GPIO_RESULT_OPEN_FAILED;
284 	}
285 
286 	set_pin_busy(service, id, en);
287 	*ptr = pin;
288 	return GPIO_RESULT_OK;
289 }
290 
291 void dal_gpio_service_close(
292 	struct gpio_service *service,
293 	struct hw_gpio_pin **ptr)
294 {
295 	struct hw_gpio_pin *pin;
296 
297 	if (!ptr) {
298 		ASSERT_CRITICAL(false);
299 		return;
300 	}
301 
302 	pin = *ptr;
303 
304 	if (pin) {
305 		set_pin_free(service, pin->id, pin->en);
306 
307 		pin->funcs->close(pin);
308 
309 		pin->funcs->destroy(ptr);
310 	}
311 }
312 
313 
314 enum dc_irq_source dal_irq_get_source(
315 	const struct gpio *irq)
316 {
317 	enum gpio_id id = dal_gpio_get_id(irq);
318 
319 	switch (id) {
320 	case GPIO_ID_HPD:
321 		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
322 			dal_gpio_get_enum(irq));
323 	case GPIO_ID_GPIO_PAD:
324 		return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
325 			dal_gpio_get_enum(irq));
326 	default:
327 		return DC_IRQ_SOURCE_INVALID;
328 	}
329 }
330 
331 enum dc_irq_source dal_irq_get_rx_source(
332 	const struct gpio *irq)
333 {
334 	enum gpio_id id = dal_gpio_get_id(irq);
335 
336 	switch (id) {
337 	case GPIO_ID_HPD:
338 		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
339 			dal_gpio_get_enum(irq));
340 	default:
341 		return DC_IRQ_SOURCE_INVALID;
342 	}
343 }
344 
345 enum gpio_result dal_irq_setup_hpd_filter(
346 	struct gpio *irq,
347 	struct gpio_hpd_config *config)
348 {
349 	struct gpio_config_data config_data;
350 
351 	if (!config)
352 		return GPIO_RESULT_INVALID_DATA;
353 
354 	config_data.type = GPIO_CONFIG_TYPE_HPD;
355 	config_data.config.hpd = *config;
356 
357 	return dal_gpio_set_config(irq, &config_data);
358 }
359 
360 /*
361  * @brief
362  * Creation and destruction
363  */
364 
365 struct gpio *dal_gpio_create_irq(
366 	struct gpio_service *service,
367 	enum gpio_id id,
368 	uint32_t en)
369 {
370 	struct gpio *irq;
371 
372 	switch (id) {
373 	case GPIO_ID_HPD:
374 	case GPIO_ID_GPIO_PAD:
375 	break;
376 	default:
377 		id = GPIO_ID_HPD;
378 		ASSERT_CRITICAL(false);
379 		return NULL;
380 	}
381 
382 	irq = dal_gpio_create(
383 		service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
384 
385 	if (irq)
386 		return irq;
387 
388 	ASSERT_CRITICAL(false);
389 	return NULL;
390 }
391 
392 void dal_gpio_destroy_irq(
393 	struct gpio **irq)
394 {
395 	if (!irq || !*irq) {
396 		ASSERT_CRITICAL(false);
397 		return;
398 	}
399 
400 	dal_gpio_close(*irq);
401 	dal_gpio_destroy(irq);
402 	kfree(*irq);
403 
404 	*irq = NULL;
405 }
406 
407 struct ddc *dal_gpio_create_ddc(
408 	struct gpio_service *service,
409 	uint32_t offset,
410 	uint32_t mask,
411 	struct gpio_ddc_hw_info *info)
412 {
413 	enum gpio_id id;
414 	uint32_t en;
415 	struct ddc *ddc;
416 
417 	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
418 		return NULL;
419 
420 	ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
421 
422 	if (!ddc) {
423 		BREAK_TO_DEBUGGER();
424 		return NULL;
425 	}
426 
427 	ddc->pin_data = dal_gpio_create(
428 		service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
429 
430 	if (!ddc->pin_data) {
431 		BREAK_TO_DEBUGGER();
432 		goto failure_1;
433 	}
434 
435 	ddc->pin_clock = dal_gpio_create(
436 		service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
437 
438 	if (!ddc->pin_clock) {
439 		BREAK_TO_DEBUGGER();
440 		goto failure_2;
441 	}
442 
443 	ddc->hw_info = *info;
444 
445 	ddc->ctx = service->ctx;
446 
447 	return ddc;
448 
449 failure_2:
450 	dal_gpio_destroy(&ddc->pin_data);
451 
452 failure_1:
453 	kfree(ddc);
454 
455 	return NULL;
456 }
457 
458 void dal_gpio_destroy_ddc(
459 	struct ddc **ddc)
460 {
461 	if (!ddc || !*ddc) {
462 		BREAK_TO_DEBUGGER();
463 		return;
464 	}
465 
466 	dal_ddc_close(*ddc);
467 	dal_gpio_destroy(&(*ddc)->pin_data);
468 	dal_gpio_destroy(&(*ddc)->pin_clock);
469 	kfree(*ddc);
470 
471 	*ddc = NULL;
472 }
473 
474 enum gpio_result dal_ddc_open(
475 	struct ddc *ddc,
476 	enum gpio_mode mode,
477 	enum gpio_ddc_config_type config_type)
478 {
479 	enum gpio_result result;
480 
481 	struct gpio_config_data config_data;
482 	struct hw_gpio *hw_data;
483 	struct hw_gpio *hw_clock;
484 
485 	result = dal_gpio_open_ex(ddc->pin_data, mode);
486 
487 	if (result != GPIO_RESULT_OK) {
488 		BREAK_TO_DEBUGGER();
489 		return result;
490 	}
491 
492 	result = dal_gpio_open_ex(ddc->pin_clock, mode);
493 
494 	if (result != GPIO_RESULT_OK) {
495 		BREAK_TO_DEBUGGER();
496 		goto failure;
497 	}
498 
499 	/* DDC clock and data pins should belong
500 	 * to the same DDC block id,
501 	 * we use the data pin to set the pad mode. */
502 
503 	if (mode == GPIO_MODE_INPUT)
504 		/* this is from detect_sink_type,
505 		 * we need extra delay there */
506 		config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
507 	else
508 		config_data.type = GPIO_CONFIG_TYPE_DDC;
509 
510 	config_data.config.ddc.type = config_type;
511 
512 	hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
513 	hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
514 
515 	config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
516 	config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
517 
518 	result = dal_gpio_set_config(ddc->pin_data, &config_data);
519 
520 	if (result == GPIO_RESULT_OK)
521 		return result;
522 
523 	BREAK_TO_DEBUGGER();
524 
525 	dal_gpio_close(ddc->pin_clock);
526 
527 failure:
528 	dal_gpio_close(ddc->pin_data);
529 
530 	return result;
531 }
532 
533 enum gpio_result dal_ddc_change_mode(
534 	struct ddc *ddc,
535 	enum gpio_mode mode)
536 {
537 	enum gpio_result result;
538 
539 	enum gpio_mode original_mode =
540 		dal_gpio_get_mode(ddc->pin_data);
541 
542 	result = dal_gpio_change_mode(ddc->pin_data, mode);
543 
544 	/* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
545 	 * in case of failures;
546 	 * set_mode() is so that, in case of failure,
547 	 * we must explicitly set original mode */
548 
549 	if (result != GPIO_RESULT_OK)
550 		goto failure;
551 
552 	result = dal_gpio_change_mode(ddc->pin_clock, mode);
553 
554 	if (result == GPIO_RESULT_OK)
555 		return result;
556 
557 	dal_gpio_change_mode(ddc->pin_clock, original_mode);
558 
559 failure:
560 	dal_gpio_change_mode(ddc->pin_data, original_mode);
561 
562 	return result;
563 }
564 
565 enum gpio_ddc_line dal_ddc_get_line(
566 	const struct ddc *ddc)
567 {
568 	return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
569 }
570 
571 enum gpio_result dal_ddc_set_config(
572 	struct ddc *ddc,
573 	enum gpio_ddc_config_type config_type)
574 {
575 	struct gpio_config_data config_data;
576 
577 	config_data.type = GPIO_CONFIG_TYPE_DDC;
578 
579 	config_data.config.ddc.type = config_type;
580 	config_data.config.ddc.data_en_bit_present = false;
581 	config_data.config.ddc.clock_en_bit_present = false;
582 
583 	return dal_gpio_set_config(ddc->pin_data, &config_data);
584 }
585 
586 void dal_ddc_close(
587 	struct ddc *ddc)
588 {
589 	dal_gpio_close(ddc->pin_clock);
590 	dal_gpio_close(ddc->pin_data);
591 }
592 
593