cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dp_aux.c (12943B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/delay.h>
      7#include <drm/drm_print.h>
      8
      9#include "dp_reg.h"
     10#include "dp_aux.h"
     11
     12enum msm_dp_aux_err {
     13	DP_AUX_ERR_NONE,
     14	DP_AUX_ERR_ADDR,
     15	DP_AUX_ERR_TOUT,
     16	DP_AUX_ERR_NACK,
     17	DP_AUX_ERR_DEFER,
     18	DP_AUX_ERR_NACK_DEFER,
     19	DP_AUX_ERR_PHY,
     20};
     21
     22struct dp_aux_private {
     23	struct device *dev;
     24	struct dp_catalog *catalog;
     25
     26	struct mutex mutex;
     27	struct completion comp;
     28
     29	enum msm_dp_aux_err aux_error_num;
     30	u32 retry_cnt;
     31	bool cmd_busy;
     32	bool native;
     33	bool read;
     34	bool no_send_addr;
     35	bool no_send_stop;
     36	bool initted;
     37	bool is_edp;
     38	u32 offset;
     39	u32 segment;
     40
     41	struct drm_dp_aux dp_aux;
     42};
     43
     44#define MAX_AUX_RETRIES			5
     45
     46static ssize_t dp_aux_write(struct dp_aux_private *aux,
     47			struct drm_dp_aux_msg *msg)
     48{
     49	u8 data[4];
     50	u32 reg;
     51	ssize_t len;
     52	u8 *msgdata = msg->buffer;
     53	int const AUX_CMD_FIFO_LEN = 128;
     54	int i = 0;
     55
     56	if (aux->read)
     57		len = 0;
     58	else
     59		len = msg->size;
     60
     61	/*
     62	 * cmd fifo only has depth of 144 bytes
     63	 * limit buf length to 128 bytes here
     64	 */
     65	if (len > AUX_CMD_FIFO_LEN - 4) {
     66		DRM_ERROR("buf size greater than allowed size of 128 bytes\n");
     67		return -EINVAL;
     68	}
     69
     70	/* Pack cmd and write to HW */
     71	data[0] = (msg->address >> 16) & 0xf;	/* addr[19:16] */
     72	if (aux->read)
     73		data[0] |=  BIT(4);		/* R/W */
     74
     75	data[1] = msg->address >> 8;		/* addr[15:8] */
     76	data[2] = msg->address;			/* addr[7:0] */
     77	data[3] = msg->size - 1;		/* len[7:0] */
     78
     79	for (i = 0; i < len + 4; i++) {
     80		reg = (i < 4) ? data[i] : msgdata[i - 4];
     81		reg <<= DP_AUX_DATA_OFFSET;
     82		reg &= DP_AUX_DATA_MASK;
     83		reg |= DP_AUX_DATA_WRITE;
     84		/* index = 0, write */
     85		if (i == 0)
     86			reg |= DP_AUX_DATA_INDEX_WRITE;
     87		aux->catalog->aux_data = reg;
     88		dp_catalog_aux_write_data(aux->catalog);
     89	}
     90
     91	dp_catalog_aux_clear_trans(aux->catalog, false);
     92	dp_catalog_aux_clear_hw_interrupts(aux->catalog);
     93
     94	reg = 0; /* Transaction number == 1 */
     95	if (!aux->native) { /* i2c */
     96		reg |= DP_AUX_TRANS_CTRL_I2C;
     97
     98		if (aux->no_send_addr)
     99			reg |= DP_AUX_TRANS_CTRL_NO_SEND_ADDR;
    100
    101		if (aux->no_send_stop)
    102			reg |= DP_AUX_TRANS_CTRL_NO_SEND_STOP;
    103	}
    104
    105	reg |= DP_AUX_TRANS_CTRL_GO;
    106	aux->catalog->aux_data = reg;
    107	dp_catalog_aux_write_trans(aux->catalog);
    108
    109	return len;
    110}
    111
    112static ssize_t dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
    113			      struct drm_dp_aux_msg *msg)
    114{
    115	ssize_t ret;
    116	unsigned long time_left;
    117
    118	reinit_completion(&aux->comp);
    119
    120	ret = dp_aux_write(aux, msg);
    121	if (ret < 0)
    122		return ret;
    123
    124	time_left = wait_for_completion_timeout(&aux->comp,
    125						msecs_to_jiffies(250));
    126	if (!time_left)
    127		return -ETIMEDOUT;
    128
    129	return ret;
    130}
    131
    132static ssize_t dp_aux_cmd_fifo_rx(struct dp_aux_private *aux,
    133		struct drm_dp_aux_msg *msg)
    134{
    135	u32 data;
    136	u8 *dp;
    137	u32 i, actual_i;
    138	u32 len = msg->size;
    139
    140	dp_catalog_aux_clear_trans(aux->catalog, true);
    141
    142	data = DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */
    143	data |= DP_AUX_DATA_READ;  /* read */
    144
    145	aux->catalog->aux_data = data;
    146	dp_catalog_aux_write_data(aux->catalog);
    147
    148	dp = msg->buffer;
    149
    150	/* discard first byte */
    151	data = dp_catalog_aux_read_data(aux->catalog);
    152
    153	for (i = 0; i < len; i++) {
    154		data = dp_catalog_aux_read_data(aux->catalog);
    155		*dp++ = (u8)((data >> DP_AUX_DATA_OFFSET) & 0xff);
    156
    157		actual_i = (data >> DP_AUX_DATA_INDEX_OFFSET) & 0xFF;
    158		if (i != actual_i)
    159			break;
    160	}
    161
    162	return i;
    163}
    164
    165static void dp_aux_native_handler(struct dp_aux_private *aux, u32 isr)
    166{
    167	if (isr & DP_INTR_AUX_I2C_DONE)
    168		aux->aux_error_num = DP_AUX_ERR_NONE;
    169	else if (isr & DP_INTR_WRONG_ADDR)
    170		aux->aux_error_num = DP_AUX_ERR_ADDR;
    171	else if (isr & DP_INTR_TIMEOUT)
    172		aux->aux_error_num = DP_AUX_ERR_TOUT;
    173	if (isr & DP_INTR_NACK_DEFER)
    174		aux->aux_error_num = DP_AUX_ERR_NACK;
    175	if (isr & DP_INTR_AUX_ERROR) {
    176		aux->aux_error_num = DP_AUX_ERR_PHY;
    177		dp_catalog_aux_clear_hw_interrupts(aux->catalog);
    178	}
    179}
    180
    181static void dp_aux_i2c_handler(struct dp_aux_private *aux, u32 isr)
    182{
    183	if (isr & DP_INTR_AUX_I2C_DONE) {
    184		if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER))
    185			aux->aux_error_num = DP_AUX_ERR_NACK;
    186		else
    187			aux->aux_error_num = DP_AUX_ERR_NONE;
    188	} else {
    189		if (isr & DP_INTR_WRONG_ADDR)
    190			aux->aux_error_num = DP_AUX_ERR_ADDR;
    191		else if (isr & DP_INTR_TIMEOUT)
    192			aux->aux_error_num = DP_AUX_ERR_TOUT;
    193		if (isr & DP_INTR_NACK_DEFER)
    194			aux->aux_error_num = DP_AUX_ERR_NACK_DEFER;
    195		if (isr & DP_INTR_I2C_NACK)
    196			aux->aux_error_num = DP_AUX_ERR_NACK;
    197		if (isr & DP_INTR_I2C_DEFER)
    198			aux->aux_error_num = DP_AUX_ERR_DEFER;
    199		if (isr & DP_INTR_AUX_ERROR) {
    200			aux->aux_error_num = DP_AUX_ERR_PHY;
    201			dp_catalog_aux_clear_hw_interrupts(aux->catalog);
    202		}
    203	}
    204}
    205
    206static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
    207					     struct drm_dp_aux_msg *input_msg)
    208{
    209	u32 edid_address = 0x50;
    210	u32 segment_address = 0x30;
    211	bool i2c_read = input_msg->request &
    212		(DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
    213	u8 *data;
    214
    215	if (aux->native || i2c_read || ((input_msg->address != edid_address) &&
    216		(input_msg->address != segment_address)))
    217		return;
    218
    219
    220	data = input_msg->buffer;
    221	if (input_msg->address == segment_address)
    222		aux->segment = *data;
    223	else
    224		aux->offset = *data;
    225}
    226
    227/**
    228 * dp_aux_transfer_helper() - helper function for EDID read transactions
    229 *
    230 * @aux: DP AUX private structure
    231 * @input_msg: input message from DRM upstream APIs
    232 * @send_seg: send the segment to sink
    233 *
    234 * return: void
    235 *
    236 * This helper function is used to fix EDID reads for non-compliant
    237 * sinks that do not handle the i2c middle-of-transaction flag correctly.
    238 */
    239static void dp_aux_transfer_helper(struct dp_aux_private *aux,
    240				   struct drm_dp_aux_msg *input_msg,
    241				   bool send_seg)
    242{
    243	struct drm_dp_aux_msg helper_msg;
    244	u32 message_size = 0x10;
    245	u32 segment_address = 0x30;
    246	u32 const edid_block_length = 0x80;
    247	bool i2c_mot = input_msg->request & DP_AUX_I2C_MOT;
    248	bool i2c_read = input_msg->request &
    249		(DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
    250
    251	if (!i2c_mot || !i2c_read || (input_msg->size == 0))
    252		return;
    253
    254	/*
    255	 * Sending the segment value and EDID offset will be performed
    256	 * from the DRM upstream EDID driver for each block. Avoid
    257	 * duplicate AUX transactions related to this while reading the
    258	 * first 16 bytes of each block.
    259	 */
    260	if (!(aux->offset % edid_block_length) || !send_seg)
    261		goto end;
    262
    263	aux->read = false;
    264	aux->cmd_busy = true;
    265	aux->no_send_addr = true;
    266	aux->no_send_stop = true;
    267
    268	/*
    269	 * Send the segment address for every i2c read in which the
    270	 * middle-of-tranaction flag is set. This is required to support EDID
    271	 * reads of more than 2 blocks as the segment address is reset to 0
    272	 * since we are overriding the middle-of-transaction flag for read
    273	 * transactions.
    274	 */
    275
    276	if (aux->segment) {
    277		memset(&helper_msg, 0, sizeof(helper_msg));
    278		helper_msg.address = segment_address;
    279		helper_msg.buffer = &aux->segment;
    280		helper_msg.size = 1;
    281		dp_aux_cmd_fifo_tx(aux, &helper_msg);
    282	}
    283
    284	/*
    285	 * Send the offset address for every i2c read in which the
    286	 * middle-of-transaction flag is set. This will ensure that the sink
    287	 * will update its read pointer and return the correct portion of the
    288	 * EDID buffer in the subsequent i2c read trasntion triggered in the
    289	 * native AUX transfer function.
    290	 */
    291	memset(&helper_msg, 0, sizeof(helper_msg));
    292	helper_msg.address = input_msg->address;
    293	helper_msg.buffer = &aux->offset;
    294	helper_msg.size = 1;
    295	dp_aux_cmd_fifo_tx(aux, &helper_msg);
    296
    297end:
    298	aux->offset += message_size;
    299	if (aux->offset == 0x80 || aux->offset == 0x100)
    300		aux->segment = 0x0; /* reset segment at end of block */
    301}
    302
    303/*
    304 * This function does the real job to process an AUX transaction.
    305 * It will call aux_reset() function to reset the AUX channel,
    306 * if the waiting is timeout.
    307 */
    308static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
    309			       struct drm_dp_aux_msg *msg)
    310{
    311	ssize_t ret;
    312	int const aux_cmd_native_max = 16;
    313	int const aux_cmd_i2c_max = 128;
    314	struct dp_aux_private *aux;
    315
    316	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
    317
    318	aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
    319
    320	/* Ignore address only message */
    321	if (msg->size == 0 || !msg->buffer) {
    322		msg->reply = aux->native ?
    323			DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
    324		return msg->size;
    325	}
    326
    327	/* msg sanity check */
    328	if ((aux->native && msg->size > aux_cmd_native_max) ||
    329	    msg->size > aux_cmd_i2c_max) {
    330		DRM_ERROR("%s: invalid msg: size(%zu), request(%x)\n",
    331			__func__, msg->size, msg->request);
    332		return -EINVAL;
    333	}
    334
    335	mutex_lock(&aux->mutex);
    336	if (!aux->initted) {
    337		ret = -EIO;
    338		goto exit;
    339	}
    340
    341	/*
    342	 * For eDP it's important to give a reasonably long wait here for HPD
    343	 * to be asserted. This is because the panel driver may have _just_
    344	 * turned on the panel and then tried to do an AUX transfer. The panel
    345	 * driver has no way of knowing when the panel is ready, so it's up
    346	 * to us to wait. For DP we never get into this situation so let's
    347	 * avoid ever doing the extra long wait for DP.
    348	 */
    349	if (aux->is_edp) {
    350		ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog);
    351		if (ret) {
    352			DRM_DEBUG_DP("Panel not ready for aux transactions\n");
    353			goto exit;
    354		}
    355	}
    356
    357	dp_aux_update_offset_and_segment(aux, msg);
    358	dp_aux_transfer_helper(aux, msg, true);
    359
    360	aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
    361	aux->cmd_busy = true;
    362
    363	if (aux->read) {
    364		aux->no_send_addr = true;
    365		aux->no_send_stop = false;
    366	} else {
    367		aux->no_send_addr = true;
    368		aux->no_send_stop = true;
    369	}
    370
    371	ret = dp_aux_cmd_fifo_tx(aux, msg);
    372	if (ret < 0) {
    373		if (aux->native) {
    374			aux->retry_cnt++;
    375			if (!(aux->retry_cnt % MAX_AUX_RETRIES))
    376				dp_catalog_aux_update_cfg(aux->catalog);
    377		}
    378		/* reset aux if link is in connected state */
    379		if (dp_catalog_link_is_connected(aux->catalog))
    380			dp_catalog_aux_reset(aux->catalog);
    381	} else {
    382		aux->retry_cnt = 0;
    383		switch (aux->aux_error_num) {
    384		case DP_AUX_ERR_NONE:
    385			if (aux->read)
    386				ret = dp_aux_cmd_fifo_rx(aux, msg);
    387			msg->reply = aux->native ? DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
    388			break;
    389		case DP_AUX_ERR_DEFER:
    390			msg->reply = aux->native ? DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
    391			break;
    392		case DP_AUX_ERR_PHY:
    393		case DP_AUX_ERR_ADDR:
    394		case DP_AUX_ERR_NACK:
    395		case DP_AUX_ERR_NACK_DEFER:
    396			msg->reply = aux->native ? DP_AUX_NATIVE_REPLY_NACK : DP_AUX_I2C_REPLY_NACK;
    397			break;
    398		case DP_AUX_ERR_TOUT:
    399			ret = -ETIMEDOUT;
    400			break;
    401		}
    402	}
    403
    404	aux->cmd_busy = false;
    405
    406exit:
    407	mutex_unlock(&aux->mutex);
    408
    409	return ret;
    410}
    411
    412void dp_aux_isr(struct drm_dp_aux *dp_aux)
    413{
    414	u32 isr;
    415	struct dp_aux_private *aux;
    416
    417	if (!dp_aux) {
    418		DRM_ERROR("invalid input\n");
    419		return;
    420	}
    421
    422	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
    423
    424	isr = dp_catalog_aux_get_irq(aux->catalog);
    425
    426	if (!aux->cmd_busy)
    427		return;
    428
    429	if (aux->native)
    430		dp_aux_native_handler(aux, isr);
    431	else
    432		dp_aux_i2c_handler(aux, isr);
    433
    434	complete(&aux->comp);
    435}
    436
    437void dp_aux_reconfig(struct drm_dp_aux *dp_aux)
    438{
    439	struct dp_aux_private *aux;
    440
    441	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
    442
    443	dp_catalog_aux_update_cfg(aux->catalog);
    444	dp_catalog_aux_reset(aux->catalog);
    445}
    446
    447void dp_aux_init(struct drm_dp_aux *dp_aux)
    448{
    449	struct dp_aux_private *aux;
    450
    451	if (!dp_aux) {
    452		DRM_ERROR("invalid input\n");
    453		return;
    454	}
    455
    456	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
    457
    458	mutex_lock(&aux->mutex);
    459
    460	dp_catalog_aux_enable(aux->catalog, true);
    461	aux->retry_cnt = 0;
    462	aux->initted = true;
    463
    464	mutex_unlock(&aux->mutex);
    465}
    466
    467void dp_aux_deinit(struct drm_dp_aux *dp_aux)
    468{
    469	struct dp_aux_private *aux;
    470
    471	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
    472
    473	mutex_lock(&aux->mutex);
    474
    475	aux->initted = false;
    476	dp_catalog_aux_enable(aux->catalog, false);
    477
    478	mutex_unlock(&aux->mutex);
    479}
    480
    481int dp_aux_register(struct drm_dp_aux *dp_aux)
    482{
    483	struct dp_aux_private *aux;
    484	int ret;
    485
    486	if (!dp_aux) {
    487		DRM_ERROR("invalid input\n");
    488		return -EINVAL;
    489	}
    490
    491	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
    492
    493	aux->dp_aux.name = "dpu_dp_aux";
    494	aux->dp_aux.dev = aux->dev;
    495	aux->dp_aux.transfer = dp_aux_transfer;
    496	ret = drm_dp_aux_register(&aux->dp_aux);
    497	if (ret) {
    498		DRM_ERROR("%s: failed to register drm aux: %d\n", __func__,
    499				ret);
    500		return ret;
    501	}
    502
    503	return 0;
    504}
    505
    506void dp_aux_unregister(struct drm_dp_aux *dp_aux)
    507{
    508	drm_dp_aux_unregister(dp_aux);
    509}
    510
    511struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
    512			      bool is_edp)
    513{
    514	struct dp_aux_private *aux;
    515
    516	if (!catalog) {
    517		DRM_ERROR("invalid input\n");
    518		return ERR_PTR(-ENODEV);
    519	}
    520
    521	aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL);
    522	if (!aux)
    523		return ERR_PTR(-ENOMEM);
    524
    525	init_completion(&aux->comp);
    526	aux->cmd_busy = false;
    527	aux->is_edp = is_edp;
    528	mutex_init(&aux->mutex);
    529
    530	aux->dev = dev;
    531	aux->catalog = catalog;
    532	aux->retry_cnt = 0;
    533
    534	return &aux->dp_aux;
    535}
    536
    537void dp_aux_put(struct drm_dp_aux *dp_aux)
    538{
    539	struct dp_aux_private *aux;
    540
    541	if (!dp_aux)
    542		return;
    543
    544	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
    545
    546	mutex_destroy(&aux->mutex);
    547
    548	devm_kfree(aux->dev, aux);
    549}