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

cdns-mhdp8546-hdcp.c (13369B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Cadence MHDP8546 DP bridge driver.
      4 *
      5 * Copyright (C) 2020 Cadence Design Systems, Inc.
      6 *
      7 */
      8
      9#include <linux/io.h>
     10#include <linux/iopoll.h>
     11
     12#include <asm/unaligned.h>
     13
     14#include <drm/display/drm_hdcp_helper.h>
     15
     16#include "cdns-mhdp8546-hdcp.h"
     17
     18static int cdns_mhdp_secure_mailbox_read(struct cdns_mhdp_device *mhdp)
     19{
     20	int ret, empty;
     21
     22	WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
     23
     24	ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_EMPTY,
     25				 empty, !empty, MAILBOX_RETRY_US,
     26				 MAILBOX_TIMEOUT_US);
     27	if (ret < 0)
     28		return ret;
     29
     30	return readl(mhdp->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff;
     31}
     32
     33static int cdns_mhdp_secure_mailbox_write(struct cdns_mhdp_device *mhdp,
     34					  u8 val)
     35{
     36	int ret, full;
     37
     38	WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
     39
     40	ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_FULL,
     41				 full, !full, MAILBOX_RETRY_US,
     42				 MAILBOX_TIMEOUT_US);
     43	if (ret < 0)
     44		return ret;
     45
     46	writel(val, mhdp->sapb_regs + CDNS_MAILBOX_TX_DATA);
     47
     48	return 0;
     49}
     50
     51static int cdns_mhdp_secure_mailbox_recv_header(struct cdns_mhdp_device *mhdp,
     52						u8 module_id,
     53						u8 opcode,
     54						u16 req_size)
     55{
     56	u32 mbox_size, i;
     57	u8 header[4];
     58	int ret;
     59
     60	/* read the header of the message */
     61	for (i = 0; i < sizeof(header); i++) {
     62		ret = cdns_mhdp_secure_mailbox_read(mhdp);
     63		if (ret < 0)
     64			return ret;
     65
     66		header[i] = ret;
     67	}
     68
     69	mbox_size = get_unaligned_be16(header + 2);
     70
     71	if (opcode != header[0] || module_id != header[1] ||
     72	    (opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) {
     73		for (i = 0; i < mbox_size; i++)
     74			if (cdns_mhdp_secure_mailbox_read(mhdp) < 0)
     75				break;
     76		return -EINVAL;
     77	}
     78
     79	return 0;
     80}
     81
     82static int cdns_mhdp_secure_mailbox_recv_data(struct cdns_mhdp_device *mhdp,
     83					      u8 *buff, u16 buff_size)
     84{
     85	int ret;
     86	u32 i;
     87
     88	for (i = 0; i < buff_size; i++) {
     89		ret = cdns_mhdp_secure_mailbox_read(mhdp);
     90		if (ret < 0)
     91			return ret;
     92
     93		buff[i] = ret;
     94	}
     95
     96	return 0;
     97}
     98
     99static int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_device *mhdp,
    100					 u8 module_id,
    101					 u8 opcode,
    102					 u16 size,
    103					 u8 *message)
    104{
    105	u8 header[4];
    106	int ret;
    107	u32 i;
    108
    109	header[0] = opcode;
    110	header[1] = module_id;
    111	put_unaligned_be16(size, header + 2);
    112
    113	for (i = 0; i < sizeof(header); i++) {
    114		ret = cdns_mhdp_secure_mailbox_write(mhdp, header[i]);
    115		if (ret)
    116			return ret;
    117	}
    118
    119	for (i = 0; i < size; i++) {
    120		ret = cdns_mhdp_secure_mailbox_write(mhdp, message[i]);
    121		if (ret)
    122			return ret;
    123	}
    124
    125	return 0;
    126}
    127
    128static int cdns_mhdp_hdcp_get_status(struct cdns_mhdp_device *mhdp,
    129				     u16 *hdcp_port_status)
    130{
    131	u8 hdcp_status[HDCP_STATUS_SIZE];
    132	int ret;
    133
    134	mutex_lock(&mhdp->mbox_mutex);
    135	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
    136					    HDCP_TRAN_STATUS_CHANGE, 0, NULL);
    137	if (ret)
    138		goto err_get_hdcp_status;
    139
    140	ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
    141						   HDCP_TRAN_STATUS_CHANGE,
    142						   sizeof(hdcp_status));
    143	if (ret)
    144		goto err_get_hdcp_status;
    145
    146	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_status,
    147						 sizeof(hdcp_status));
    148	if (ret)
    149		goto err_get_hdcp_status;
    150
    151	*hdcp_port_status = ((u16)(hdcp_status[0] << 8) | hdcp_status[1]);
    152
    153err_get_hdcp_status:
    154	mutex_unlock(&mhdp->mbox_mutex);
    155
    156	return ret;
    157}
    158
    159static u8 cdns_mhdp_hdcp_handle_status(struct cdns_mhdp_device *mhdp,
    160				       u16 status)
    161{
    162	u8 err = GET_HDCP_PORT_STS_LAST_ERR(status);
    163
    164	if (err)
    165		dev_dbg(mhdp->dev, "HDCP Error = %d", err);
    166
    167	return err;
    168}
    169
    170static int cdns_mhdp_hdcp_rx_id_valid_response(struct cdns_mhdp_device *mhdp,
    171					       u8 valid)
    172{
    173	int ret;
    174
    175	mutex_lock(&mhdp->mbox_mutex);
    176	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
    177					    HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
    178					    1, &valid);
    179	mutex_unlock(&mhdp->mbox_mutex);
    180
    181	return ret;
    182}
    183
    184static int cdns_mhdp_hdcp_rx_id_valid(struct cdns_mhdp_device *mhdp,
    185				      u8 *recv_num, u8 *hdcp_rx_id)
    186{
    187	u8 rec_id_hdr[2];
    188	u8 status;
    189	int ret;
    190
    191	mutex_lock(&mhdp->mbox_mutex);
    192	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
    193					    HDCP_TRAN_IS_REC_ID_VALID, 0, NULL);
    194	if (ret)
    195		goto err_rx_id_valid;
    196
    197	ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
    198						   HDCP_TRAN_IS_REC_ID_VALID,
    199						   sizeof(status));
    200	if (ret)
    201		goto err_rx_id_valid;
    202
    203	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, rec_id_hdr, 2);
    204	if (ret)
    205		goto err_rx_id_valid;
    206
    207	*recv_num = rec_id_hdr[0];
    208
    209	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_rx_id, 5 * *recv_num);
    210
    211err_rx_id_valid:
    212	mutex_unlock(&mhdp->mbox_mutex);
    213
    214	return ret;
    215}
    216
    217static int cdns_mhdp_hdcp_km_stored_resp(struct cdns_mhdp_device *mhdp,
    218					 u32 size, u8 *km)
    219{
    220	int ret;
    221
    222	mutex_lock(&mhdp->mbox_mutex);
    223	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
    224					    HDCP2X_TX_RESPOND_KM, size, km);
    225	mutex_unlock(&mhdp->mbox_mutex);
    226
    227	return ret;
    228}
    229
    230static int cdns_mhdp_hdcp_tx_is_km_stored(struct cdns_mhdp_device *mhdp,
    231					  u8 *resp, u32 size)
    232{
    233	int ret;
    234
    235	mutex_lock(&mhdp->mbox_mutex);
    236	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
    237					    HDCP2X_TX_IS_KM_STORED, 0, NULL);
    238	if (ret)
    239		goto err_is_km_stored;
    240
    241	ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
    242						   HDCP2X_TX_IS_KM_STORED,
    243						   size);
    244	if (ret)
    245		goto err_is_km_stored;
    246
    247	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, resp, size);
    248err_is_km_stored:
    249	mutex_unlock(&mhdp->mbox_mutex);
    250
    251	return ret;
    252}
    253
    254static int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp,
    255				    u8 hdcp_cfg)
    256{
    257	int ret;
    258
    259	mutex_lock(&mhdp->mbox_mutex);
    260	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
    261					    HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg);
    262	mutex_unlock(&mhdp->mbox_mutex);
    263
    264	return ret;
    265}
    266
    267static int cdns_mhdp_hdcp_set_config(struct cdns_mhdp_device *mhdp,
    268				     u8 hdcp_config, bool enable)
    269{
    270	u16 hdcp_port_status;
    271	u32 ret_event;
    272	u8 hdcp_cfg;
    273	int ret;
    274
    275	hdcp_cfg = hdcp_config | (enable ? 0x04 : 0) |
    276		   (HDCP_CONTENT_TYPE_0 << 3);
    277	cdns_mhdp_hdcp_tx_config(mhdp, hdcp_cfg);
    278	ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS);
    279	if (!ret_event)
    280		return -1;
    281
    282	ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
    283	if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
    284		return -1;
    285
    286	return 0;
    287}
    288
    289static int cdns_mhdp_hdcp_auth_check(struct cdns_mhdp_device *mhdp)
    290{
    291	u16 hdcp_port_status;
    292	u32 ret_event;
    293	int ret;
    294
    295	ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS);
    296	if (!ret_event)
    297		return -1;
    298
    299	ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
    300	if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
    301		return -1;
    302
    303	if (hdcp_port_status & 1) {
    304		dev_dbg(mhdp->dev, "Authentication completed successfully!\n");
    305		return 0;
    306	}
    307
    308	dev_dbg(mhdp->dev, "Authentication failed\n");
    309
    310	return -1;
    311}
    312
    313static int cdns_mhdp_hdcp_check_receviers(struct cdns_mhdp_device *mhdp)
    314{
    315	u8 hdcp_rec_id[HDCP_MAX_RECEIVERS][HDCP_RECEIVER_ID_SIZE_BYTES];
    316	u8 hdcp_num_rec;
    317	u32 ret_event;
    318
    319	ret_event = cdns_mhdp_wait_for_sw_event(mhdp,
    320						CDNS_HDCP_TX_IS_RCVR_ID_VALID);
    321	if (!ret_event)
    322		return -1;
    323
    324	hdcp_num_rec = 0;
    325	memset(&hdcp_rec_id, 0, sizeof(hdcp_rec_id));
    326	cdns_mhdp_hdcp_rx_id_valid(mhdp, &hdcp_num_rec, (u8 *)hdcp_rec_id);
    327	cdns_mhdp_hdcp_rx_id_valid_response(mhdp, 1);
    328
    329	return 0;
    330}
    331
    332static int cdns_mhdp_hdcp_auth_22(struct cdns_mhdp_device *mhdp)
    333{
    334	u8 resp[HDCP_STATUS_SIZE];
    335	u16 hdcp_port_status;
    336	u32 ret_event;
    337	int ret;
    338
    339	dev_dbg(mhdp->dev, "HDCP: Start 2.2 Authentication\n");
    340	ret_event = cdns_mhdp_wait_for_sw_event(mhdp,
    341						CDNS_HDCP2_TX_IS_KM_STORED);
    342	if (!ret_event)
    343		return -1;
    344
    345	if (ret_event & CDNS_HDCP_TX_STATUS) {
    346		mhdp->sw_events &= ~CDNS_HDCP_TX_STATUS;
    347		ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
    348		if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
    349			return -1;
    350	}
    351
    352	cdns_mhdp_hdcp_tx_is_km_stored(mhdp, resp, sizeof(resp));
    353	cdns_mhdp_hdcp_km_stored_resp(mhdp, 0, NULL);
    354
    355	if (cdns_mhdp_hdcp_check_receviers(mhdp))
    356		return -1;
    357
    358	return 0;
    359}
    360
    361static inline int cdns_mhdp_hdcp_auth_14(struct cdns_mhdp_device *mhdp)
    362{
    363	dev_dbg(mhdp->dev, "HDCP: Starting 1.4 Authentication\n");
    364	return cdns_mhdp_hdcp_check_receviers(mhdp);
    365}
    366
    367static int cdns_mhdp_hdcp_auth(struct cdns_mhdp_device *mhdp,
    368			       u8 hdcp_config)
    369{
    370	int ret;
    371
    372	ret = cdns_mhdp_hdcp_set_config(mhdp, hdcp_config, true);
    373	if (ret)
    374		goto auth_failed;
    375
    376	if (hdcp_config == HDCP_TX_1)
    377		ret = cdns_mhdp_hdcp_auth_14(mhdp);
    378	else
    379		ret = cdns_mhdp_hdcp_auth_22(mhdp);
    380
    381	if (ret)
    382		goto auth_failed;
    383
    384	ret = cdns_mhdp_hdcp_auth_check(mhdp);
    385	if (ret)
    386		ret = cdns_mhdp_hdcp_auth_check(mhdp);
    387
    388auth_failed:
    389	return ret;
    390}
    391
    392static int _cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
    393{
    394	int ret;
    395
    396	dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n",
    397		mhdp->connector.name, mhdp->connector.base.id);
    398
    399	ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false);
    400
    401	return ret;
    402}
    403
    404static int _cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
    405{
    406	int ret, tries = 3;
    407	u32 i;
    408
    409	for (i = 0; i < tries; i++) {
    410		if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0 ||
    411		    content_type == DRM_MODE_HDCP_CONTENT_TYPE1) {
    412			ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_2);
    413			if (!ret)
    414				return 0;
    415			_cdns_mhdp_hdcp_disable(mhdp);
    416		}
    417
    418		if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
    419			ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_1);
    420			if (!ret)
    421				return 0;
    422			_cdns_mhdp_hdcp_disable(mhdp);
    423		}
    424	}
    425
    426	dev_err(mhdp->dev, "HDCP authentication failed (%d tries/%d)\n",
    427		tries, ret);
    428
    429	return ret;
    430}
    431
    432static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
    433{
    434	u16 hdcp_port_status;
    435	int ret = 0;
    436
    437	mutex_lock(&mhdp->hdcp.mutex);
    438	if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
    439		goto out;
    440
    441	ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
    442	if (!ret && hdcp_port_status & HDCP_PORT_STS_AUTH)
    443		goto out;
    444
    445	dev_err(mhdp->dev,
    446		"[%s:%d] HDCP link failed, retrying authentication\n",
    447		mhdp->connector.name, mhdp->connector.base.id);
    448
    449	ret = _cdns_mhdp_hdcp_disable(mhdp);
    450	if (ret) {
    451		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
    452		schedule_work(&mhdp->hdcp.prop_work);
    453		goto out;
    454	}
    455
    456	ret = _cdns_mhdp_hdcp_enable(mhdp, mhdp->hdcp.hdcp_content_type);
    457	if (ret) {
    458		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
    459		schedule_work(&mhdp->hdcp.prop_work);
    460	}
    461out:
    462	mutex_unlock(&mhdp->hdcp.mutex);
    463	return ret;
    464}
    465
    466static void cdns_mhdp_hdcp_check_work(struct work_struct *work)
    467{
    468	struct delayed_work *d_work = to_delayed_work(work);
    469	struct cdns_mhdp_hdcp *hdcp = container_of(d_work,
    470						   struct cdns_mhdp_hdcp,
    471						   check_work);
    472	struct cdns_mhdp_device *mhdp = container_of(hdcp,
    473						     struct cdns_mhdp_device,
    474						     hdcp);
    475
    476	if (!cdns_mhdp_hdcp_check_link(mhdp))
    477		schedule_delayed_work(&hdcp->check_work,
    478				      DRM_HDCP_CHECK_PERIOD_MS);
    479}
    480
    481static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
    482{
    483	struct cdns_mhdp_hdcp *hdcp = container_of(work,
    484						   struct cdns_mhdp_hdcp,
    485						   prop_work);
    486	struct cdns_mhdp_device *mhdp = container_of(hdcp,
    487						     struct cdns_mhdp_device,
    488						     hdcp);
    489	struct drm_device *dev = mhdp->connector.dev;
    490	struct drm_connector_state *state;
    491
    492	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
    493	mutex_lock(&mhdp->hdcp.mutex);
    494	if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
    495		state = mhdp->connector.state;
    496		state->content_protection = mhdp->hdcp.value;
    497	}
    498	mutex_unlock(&mhdp->hdcp.mutex);
    499	drm_modeset_unlock(&dev->mode_config.connection_mutex);
    500}
    501
    502int cdns_mhdp_hdcp_set_lc(struct cdns_mhdp_device *mhdp, u8 *val)
    503{
    504	int ret;
    505
    506	mutex_lock(&mhdp->mbox_mutex);
    507	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_GENERAL,
    508					    HDCP_GENERAL_SET_LC_128,
    509					    16, val);
    510	mutex_unlock(&mhdp->mbox_mutex);
    511
    512	return ret;
    513}
    514
    515int
    516cdns_mhdp_hdcp_set_public_key_param(struct cdns_mhdp_device *mhdp,
    517				    struct cdns_hdcp_tx_public_key_param *val)
    518{
    519	int ret;
    520
    521	mutex_lock(&mhdp->mbox_mutex);
    522	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
    523					    HDCP2X_TX_SET_PUBLIC_KEY_PARAMS,
    524					    sizeof(*val), (u8 *)val);
    525	mutex_unlock(&mhdp->mbox_mutex);
    526
    527	return ret;
    528}
    529
    530int cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
    531{
    532	int ret;
    533
    534	mutex_lock(&mhdp->hdcp.mutex);
    535	ret = _cdns_mhdp_hdcp_enable(mhdp, content_type);
    536	if (ret)
    537		goto out;
    538
    539	mhdp->hdcp.hdcp_content_type = content_type;
    540	mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
    541	schedule_work(&mhdp->hdcp.prop_work);
    542	schedule_delayed_work(&mhdp->hdcp.check_work,
    543			      DRM_HDCP_CHECK_PERIOD_MS);
    544out:
    545	mutex_unlock(&mhdp->hdcp.mutex);
    546	return ret;
    547}
    548
    549int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
    550{
    551	int ret = 0;
    552
    553	mutex_lock(&mhdp->hdcp.mutex);
    554	if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
    555		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
    556		schedule_work(&mhdp->hdcp.prop_work);
    557		ret = _cdns_mhdp_hdcp_disable(mhdp);
    558	}
    559	mutex_unlock(&mhdp->hdcp.mutex);
    560	cancel_delayed_work_sync(&mhdp->hdcp.check_work);
    561
    562	return ret;
    563}
    564
    565void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp)
    566{
    567	INIT_DELAYED_WORK(&mhdp->hdcp.check_work, cdns_mhdp_hdcp_check_work);
    568	INIT_WORK(&mhdp->hdcp.prop_work, cdns_mhdp_hdcp_prop_work);
    569	mutex_init(&mhdp->hdcp.mutex);
    570}