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 /*
29  * Pre-requisites: headers required by header of this unit
30  */
31 #include "include/i2caux_interface.h"
32 #include "../engine.h"
33 #include "../aux_engine.h"
34 
35 /*
36  * Header of this unit
37  */
38 
39 #include "aux_engine_dce110.h"
40 
41 /*
42  * Post-requisites: headers required by this unit
43  */
44 #include "dce/dce_11_0_sh_mask.h"
45 
46 #define CTX \
47 	aux110->base.base.ctx
48 #define REG(reg_name)\
49 	(aux110->regs->reg_name)
50 #include "reg_helper.h"
51 
52 /*
53  * This unit
54  */
55 
56 /*
57  * @brief
58  * Cast 'struct aux_engine *'
59  * to 'struct aux_engine_dce110 *'
60  */
61 #define FROM_AUX_ENGINE(ptr) \
62 	container_of((ptr), struct aux_engine_dce110, base)
63 
64 /*
65  * @brief
66  * Cast 'struct engine *'
67  * to 'struct aux_engine_dce110 *'
68  */
69 #define FROM_ENGINE(ptr) \
70 	FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
71 
72 static void release_engine(
73 	struct engine *engine)
74 {
75 	struct aux_engine_dce110 *aux110 = FROM_ENGINE(engine);
76 
77 	REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1);
78 }
79 
80 static void destruct(
81 	struct aux_engine_dce110 *engine);
82 
83 static void destroy(
84 	struct aux_engine **aux_engine)
85 {
86 	struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine);
87 
88 	destruct(engine);
89 
90 	kfree(engine);
91 
92 	*aux_engine = NULL;
93 }
94 
95 #define SW_CAN_ACCESS_AUX 1
96 #define DMCU_CAN_ACCESS_AUX 2
97 
98 static bool is_engine_available(
99 	struct aux_engine *engine)
100 {
101 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
102 
103 	uint32_t value = REG_READ(AUX_ARB_CONTROL);
104 	uint32_t field = get_reg_field_value(
105 			value,
106 			AUX_ARB_CONTROL,
107 			AUX_REG_RW_CNTL_STATUS);
108 
109 	return (field != DMCU_CAN_ACCESS_AUX);
110 }
111 static bool acquire_engine(
112 	struct aux_engine *engine)
113 {
114 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
115 
116 	uint32_t value = REG_READ(AUX_ARB_CONTROL);
117 	uint32_t field = get_reg_field_value(
118 			value,
119 			AUX_ARB_CONTROL,
120 			AUX_REG_RW_CNTL_STATUS);
121 	if (field == DMCU_CAN_ACCESS_AUX)
122 	 return false;
123 	/* enable AUX before request SW to access AUX */
124 	value = REG_READ(AUX_CONTROL);
125 	field = get_reg_field_value(value,
126 				AUX_CONTROL,
127 				AUX_EN);
128 
129 	if (field == 0) {
130 		set_reg_field_value(
131 				value,
132 				1,
133 				AUX_CONTROL,
134 				AUX_EN);
135 
136 		if (REG(AUX_RESET_MASK)) {
137 			/*DP_AUX block as part of the enable sequence*/
138 			set_reg_field_value(
139 				value,
140 				1,
141 				AUX_CONTROL,
142 				AUX_RESET);
143 		}
144 
145 		REG_WRITE(AUX_CONTROL, value);
146 
147 		if (REG(AUX_RESET_MASK)) {
148 			/*poll HW to make sure reset it done*/
149 
150 			REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
151 					1, 11);
152 
153 			set_reg_field_value(
154 				value,
155 				0,
156 				AUX_CONTROL,
157 				AUX_RESET);
158 
159 			REG_WRITE(AUX_CONTROL, value);
160 
161 			REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
162 					1, 11);
163 		}
164 	} /*if (field)*/
165 
166 	/* request SW to access AUX */
167 	REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
168 
169 	value = REG_READ(AUX_ARB_CONTROL);
170 	field = get_reg_field_value(
171 			value,
172 			AUX_ARB_CONTROL,
173 			AUX_REG_RW_CNTL_STATUS);
174 
175 	return (field == SW_CAN_ACCESS_AUX);
176 }
177 
178 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \
179 	((command) | ((0xF0000 & (address)) >> 16))
180 
181 #define COMPOSE_AUX_SW_DATA_8_15(address) \
182 	((0xFF00 & (address)) >> 8)
183 
184 #define COMPOSE_AUX_SW_DATA_0_7(address) \
185 	(0xFF & (address))
186 
187 static void submit_channel_request(
188 	struct aux_engine *engine,
189 	struct aux_request_transaction_data *request)
190 {
191 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
192 	uint32_t value;
193 	uint32_t length;
194 
195 	bool is_write =
196 		((request->type == AUX_TRANSACTION_TYPE_DP) &&
197 		 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
198 		((request->type == AUX_TRANSACTION_TYPE_I2C) &&
199 		((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
200 		 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
201 	if (REG(AUXN_IMPCAL)) {
202 		/* clear_aux_error */
203 		REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK,
204 				1,
205 				0);
206 
207 		REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK,
208 				1,
209 				0);
210 
211 		/* force_default_calibrate */
212 		REG_UPDATE_1BY1_2(AUXN_IMPCAL,
213 				AUXN_IMPCAL_ENABLE, 1,
214 				AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
215 
216 		/* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
217 
218 		REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE,
219 				1,
220 				0);
221 	}
222 	/* set the delay and the number of bytes to write */
223 
224 	/* The length include
225 	 * the 4 bit header and the 20 bit address
226 	 * (that is 3 byte).
227 	 * If the requested length is non zero this means
228 	 * an addition byte specifying the length is required. */
229 
230 	length = request->length ? 4 : 3;
231 	if (is_write)
232 		length += request->length;
233 
234 	REG_UPDATE_2(AUX_SW_CONTROL,
235 			AUX_SW_START_DELAY, request->delay,
236 			AUX_SW_WR_BYTES, length);
237 
238 	/* program action and address and payload data (if 'is_write') */
239 	value = REG_UPDATE_4(AUX_SW_DATA,
240 			AUX_SW_INDEX, 0,
241 			AUX_SW_DATA_RW, 0,
242 			AUX_SW_AUTOINCREMENT_DISABLE, 1,
243 			AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
244 
245 	value = REG_SET_2(AUX_SW_DATA, value,
246 			AUX_SW_AUTOINCREMENT_DISABLE, 0,
247 			AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
248 
249 	value = REG_SET(AUX_SW_DATA, value,
250 			AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
251 
252 	if (request->length) {
253 		value = REG_SET(AUX_SW_DATA, value,
254 				AUX_SW_DATA, request->length - 1);
255 	}
256 
257 	if (is_write) {
258 		/* Load the HW buffer with the Data to be sent.
259 		 * This is relevant for write operation.
260 		 * For read, the data recived data will be
261 		 * processed in process_channel_reply(). */
262 		uint32_t i = 0;
263 
264 		while (i < request->length) {
265 			value = REG_SET(AUX_SW_DATA, value,
266 					AUX_SW_DATA, request->data[i]);
267 
268 			++i;
269 		}
270 	}
271 
272 	REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
273 	REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
274 				10, aux110->timeout_period/10);
275 	REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
276 }
277 
278 static int read_channel_reply(struct aux_engine *engine, uint32_t size,
279 			      uint8_t *buffer, uint8_t *reply_result,
280 			      uint32_t *sw_status)
281 {
282 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
283 	uint32_t bytes_replied;
284 	uint32_t reply_result_32;
285 
286 	*sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
287 			     &bytes_replied);
288 
289 	/* In case HPD is LOW, exit AUX transaction */
290 	if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
291 		return -1;
292 
293 	/* Need at least the status byte */
294 	if (!bytes_replied)
295 		return -1;
296 
297 	REG_UPDATE_1BY1_3(AUX_SW_DATA,
298 			  AUX_SW_INDEX, 0,
299 			  AUX_SW_AUTOINCREMENT_DISABLE, 1,
300 			  AUX_SW_DATA_RW, 1);
301 
302 	REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
303 	reply_result_32 = reply_result_32 >> 4;
304 	*reply_result = (uint8_t)reply_result_32;
305 
306 	if (reply_result_32 == 0) { /* ACK */
307 		uint32_t i = 0;
308 
309 		/* First byte was already used to get the command status */
310 		--bytes_replied;
311 
312 		/* Do not overflow buffer */
313 		if (bytes_replied > size)
314 			return -1;
315 
316 		while (i < bytes_replied) {
317 			uint32_t aux_sw_data_val;
318 
319 			REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
320 			buffer[i] = aux_sw_data_val;
321 			++i;
322 		}
323 
324 		return i;
325 	}
326 
327 	return 0;
328 }
329 
330 static void process_channel_reply(
331 	struct aux_engine *engine,
332 	struct aux_reply_transaction_data *reply)
333 {
334 	int bytes_replied;
335 	uint8_t reply_result;
336 	uint32_t sw_status;
337 
338 	bytes_replied = read_channel_reply(engine, reply->length, reply->data,
339 					   &reply_result, &sw_status);
340 
341 	/* in case HPD is LOW, exit AUX transaction */
342 	if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
343 		reply->status = AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
344 		return;
345 	}
346 
347 	if (bytes_replied < 0) {
348 		/* Need to handle an error case...
349 		 * Hopefully, upper layer function won't call this function if
350 		 * the number of bytes in the reply was 0, because there was
351 		 * surely an error that was asserted that should have been
352 		 * handled for hot plug case, this could happens
353 		 */
354 		if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
355 			reply->status = AUX_TRANSACTION_REPLY_INVALID;
356 			ASSERT_CRITICAL(false);
357 			return;
358 		}
359 	} else {
360 
361 		switch (reply_result) {
362 		case 0: /* ACK */
363 			reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
364 		break;
365 		case 1: /* NACK */
366 			reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
367 		break;
368 		case 2: /* DEFER */
369 			reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
370 		break;
371 		case 4: /* AUX ACK / I2C NACK */
372 			reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
373 		break;
374 		case 8: /* AUX ACK / I2C DEFER */
375 			reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
376 		break;
377 		default:
378 			reply->status = AUX_TRANSACTION_REPLY_INVALID;
379 		}
380 	}
381 }
382 
383 static enum aux_channel_operation_result get_channel_status(
384 	struct aux_engine *engine,
385 	uint8_t *returned_bytes)
386 {
387 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
388 
389 	uint32_t value;
390 
391 	if (returned_bytes == NULL) {
392 		/*caller pass NULL pointer*/
393 		ASSERT_CRITICAL(false);
394 		return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
395 	}
396 	*returned_bytes = 0;
397 
398 	/* poll to make sure that SW_DONE is asserted */
399 	value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
400 				10, aux110->timeout_period/10);
401 
402 	/* in case HPD is LOW, exit AUX transaction */
403 	if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
404 		return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
405 
406 	/* Note that the following bits are set in 'status.bits'
407 	 * during CTS 4.2.1.2 (FW 3.3.1):
408 	 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
409 	 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
410 	 *
411 	 * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
412 	 * HW debugging bit and should be ignored. */
413 	if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
414 		if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
415 			(value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
416 			return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
417 
418 		else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
419 			(value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
420 			(value &
421 				AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
422 			(value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
423 			return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
424 
425 		*returned_bytes = get_reg_field_value(value,
426 				AUX_SW_STATUS,
427 				AUX_SW_REPLY_BYTE_COUNT);
428 
429 		if (*returned_bytes == 0)
430 			return
431 			AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
432 		else {
433 			*returned_bytes -= 1;
434 			return AUX_CHANNEL_OPERATION_SUCCEEDED;
435 		}
436 	} else {
437 		/*time_elapsed >= aux_engine->timeout_period
438 		 *  AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
439 		 */
440 		ASSERT_CRITICAL(false);
441 		return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
442 	}
443 }
444 
445 static const struct aux_engine_funcs aux_engine_funcs = {
446 	.destroy = destroy,
447 	.acquire_engine = acquire_engine,
448 	.submit_channel_request = submit_channel_request,
449 	.process_channel_reply = process_channel_reply,
450 	.read_channel_reply = read_channel_reply,
451 	.get_channel_status = get_channel_status,
452 	.is_engine_available = is_engine_available,
453 };
454 
455 static const struct engine_funcs engine_funcs = {
456 	.release_engine = release_engine,
457 	.submit_request = dal_aux_engine_submit_request,
458 	.get_engine_type = dal_aux_engine_get_engine_type,
459 	.acquire = dal_aux_engine_acquire,
460 };
461 
462 static void construct(
463 	struct aux_engine_dce110 *engine,
464 	const struct aux_engine_dce110_init_data *aux_init_data)
465 {
466 	dal_aux_engine_construct(&engine->base, aux_init_data->ctx);
467 	engine->base.base.funcs = &engine_funcs;
468 	engine->base.funcs = &aux_engine_funcs;
469 
470 	engine->timeout_period = aux_init_data->timeout_period;
471 	engine->regs = aux_init_data->regs;
472 }
473 
474 static void destruct(
475 	struct aux_engine_dce110 *engine)
476 {
477 	dal_aux_engine_destruct(&engine->base);
478 }
479 
480 struct aux_engine *dal_aux_engine_dce110_create(
481 	const struct aux_engine_dce110_init_data *aux_init_data)
482 {
483 	struct aux_engine_dce110 *engine;
484 
485 	if (!aux_init_data) {
486 		ASSERT_CRITICAL(false);
487 		return NULL;
488 	}
489 
490 	engine = kzalloc(sizeof(*engine), GFP_KERNEL);
491 
492 	if (!engine) {
493 		ASSERT_CRITICAL(false);
494 		return NULL;
495 	}
496 
497 	construct(engine, aux_init_data);
498 	return &engine->base;
499 }
500