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

dpaux.c (19133B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2013 NVIDIA Corporation
      4 */
      5
      6#include <linux/clk.h>
      7#include <linux/delay.h>
      8#include <linux/interrupt.h>
      9#include <linux/io.h>
     10#include <linux/module.h>
     11#include <linux/of_device.h>
     12#include <linux/pinctrl/pinconf-generic.h>
     13#include <linux/pinctrl/pinctrl.h>
     14#include <linux/pinctrl/pinmux.h>
     15#include <linux/platform_device.h>
     16#include <linux/pm_runtime.h>
     17#include <linux/regulator/consumer.h>
     18#include <linux/reset.h>
     19#include <linux/workqueue.h>
     20
     21#include <drm/display/drm_dp_helper.h>
     22#include <drm/display/drm_dp_aux_bus.h>
     23#include <drm/drm_panel.h>
     24
     25#include "dp.h"
     26#include "dpaux.h"
     27#include "drm.h"
     28#include "trace.h"
     29
     30static DEFINE_MUTEX(dpaux_lock);
     31static LIST_HEAD(dpaux_list);
     32
     33struct tegra_dpaux_soc {
     34	unsigned int cmh;
     35	unsigned int drvz;
     36	unsigned int drvi;
     37};
     38
     39struct tegra_dpaux {
     40	struct drm_dp_aux aux;
     41	struct device *dev;
     42
     43	const struct tegra_dpaux_soc *soc;
     44
     45	void __iomem *regs;
     46	int irq;
     47
     48	struct tegra_output *output;
     49
     50	struct reset_control *rst;
     51	struct clk *clk_parent;
     52	struct clk *clk;
     53
     54	struct regulator *vdd;
     55
     56	struct completion complete;
     57	struct work_struct work;
     58	struct list_head list;
     59
     60#ifdef CONFIG_GENERIC_PINCONF
     61	struct pinctrl_dev *pinctrl;
     62	struct pinctrl_desc desc;
     63#endif
     64};
     65
     66static inline struct tegra_dpaux *to_dpaux(struct drm_dp_aux *aux)
     67{
     68	return container_of(aux, struct tegra_dpaux, aux);
     69}
     70
     71static inline struct tegra_dpaux *work_to_dpaux(struct work_struct *work)
     72{
     73	return container_of(work, struct tegra_dpaux, work);
     74}
     75
     76static inline u32 tegra_dpaux_readl(struct tegra_dpaux *dpaux,
     77				    unsigned int offset)
     78{
     79	u32 value = readl(dpaux->regs + (offset << 2));
     80
     81	trace_dpaux_readl(dpaux->dev, offset, value);
     82
     83	return value;
     84}
     85
     86static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux,
     87				      u32 value, unsigned int offset)
     88{
     89	trace_dpaux_writel(dpaux->dev, offset, value);
     90	writel(value, dpaux->regs + (offset << 2));
     91}
     92
     93static void tegra_dpaux_write_fifo(struct tegra_dpaux *dpaux, const u8 *buffer,
     94				   size_t size)
     95{
     96	size_t i, j;
     97
     98	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
     99		size_t num = min_t(size_t, size - i * 4, 4);
    100		u32 value = 0;
    101
    102		for (j = 0; j < num; j++)
    103			value |= buffer[i * 4 + j] << (j * 8);
    104
    105		tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXDATA_WRITE(i));
    106	}
    107}
    108
    109static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer,
    110				  size_t size)
    111{
    112	size_t i, j;
    113
    114	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
    115		size_t num = min_t(size_t, size - i * 4, 4);
    116		u32 value;
    117
    118		value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXDATA_READ(i));
    119
    120		for (j = 0; j < num; j++)
    121			buffer[i * 4 + j] = value >> (j * 8);
    122	}
    123}
    124
    125static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
    126				    struct drm_dp_aux_msg *msg)
    127{
    128	unsigned long timeout = msecs_to_jiffies(250);
    129	struct tegra_dpaux *dpaux = to_dpaux(aux);
    130	unsigned long status;
    131	ssize_t ret = 0;
    132	u8 reply = 0;
    133	u32 value;
    134
    135	/* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */
    136	if (msg->size > 16)
    137		return -EINVAL;
    138
    139	/*
    140	 * Allow zero-sized messages only for I2C, in which case they specify
    141	 * address-only transactions.
    142	 */
    143	if (msg->size < 1) {
    144		switch (msg->request & ~DP_AUX_I2C_MOT) {
    145		case DP_AUX_I2C_WRITE_STATUS_UPDATE:
    146		case DP_AUX_I2C_WRITE:
    147		case DP_AUX_I2C_READ:
    148			value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY;
    149			break;
    150
    151		default:
    152			return -EINVAL;
    153		}
    154	} else {
    155		/* For non-zero-sized messages, set the CMDLEN field. */
    156		value = DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
    157	}
    158
    159	switch (msg->request & ~DP_AUX_I2C_MOT) {
    160	case DP_AUX_I2C_WRITE:
    161		if (msg->request & DP_AUX_I2C_MOT)
    162			value |= DPAUX_DP_AUXCTL_CMD_MOT_WR;
    163		else
    164			value |= DPAUX_DP_AUXCTL_CMD_I2C_WR;
    165
    166		break;
    167
    168	case DP_AUX_I2C_READ:
    169		if (msg->request & DP_AUX_I2C_MOT)
    170			value |= DPAUX_DP_AUXCTL_CMD_MOT_RD;
    171		else
    172			value |= DPAUX_DP_AUXCTL_CMD_I2C_RD;
    173
    174		break;
    175
    176	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
    177		if (msg->request & DP_AUX_I2C_MOT)
    178			value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ;
    179		else
    180			value |= DPAUX_DP_AUXCTL_CMD_I2C_RQ;
    181
    182		break;
    183
    184	case DP_AUX_NATIVE_WRITE:
    185		value |= DPAUX_DP_AUXCTL_CMD_AUX_WR;
    186		break;
    187
    188	case DP_AUX_NATIVE_READ:
    189		value |= DPAUX_DP_AUXCTL_CMD_AUX_RD;
    190		break;
    191
    192	default:
    193		return -EINVAL;
    194	}
    195
    196	tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
    197	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
    198
    199	if ((msg->request & DP_AUX_I2C_READ) == 0) {
    200		tegra_dpaux_write_fifo(dpaux, msg->buffer, msg->size);
    201		ret = msg->size;
    202	}
    203
    204	/* start transaction */
    205	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXCTL);
    206	value |= DPAUX_DP_AUXCTL_TRANSACTREQ;
    207	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
    208
    209	status = wait_for_completion_timeout(&dpaux->complete, timeout);
    210	if (!status)
    211		return -ETIMEDOUT;
    212
    213	/* read status and clear errors */
    214	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
    215	tegra_dpaux_writel(dpaux, 0xf00, DPAUX_DP_AUXSTAT);
    216
    217	if (value & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR)
    218		return -ETIMEDOUT;
    219
    220	if ((value & DPAUX_DP_AUXSTAT_RX_ERROR) ||
    221	    (value & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR) ||
    222	    (value & DPAUX_DP_AUXSTAT_NO_STOP_ERROR))
    223		return -EIO;
    224
    225	switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) {
    226	case 0x00:
    227		reply = DP_AUX_NATIVE_REPLY_ACK;
    228		break;
    229
    230	case 0x01:
    231		reply = DP_AUX_NATIVE_REPLY_NACK;
    232		break;
    233
    234	case 0x02:
    235		reply = DP_AUX_NATIVE_REPLY_DEFER;
    236		break;
    237
    238	case 0x04:
    239		reply = DP_AUX_I2C_REPLY_NACK;
    240		break;
    241
    242	case 0x08:
    243		reply = DP_AUX_I2C_REPLY_DEFER;
    244		break;
    245	}
    246
    247	if ((msg->size > 0) && (msg->reply == DP_AUX_NATIVE_REPLY_ACK)) {
    248		if (msg->request & DP_AUX_I2C_READ) {
    249			size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
    250
    251			/*
    252			 * There might be a smarter way to do this, but since
    253			 * the DP helpers will already retry transactions for
    254			 * an -EBUSY return value, simply reuse that instead.
    255			 */
    256			if (count != msg->size) {
    257				ret = -EBUSY;
    258				goto out;
    259			}
    260
    261			tegra_dpaux_read_fifo(dpaux, msg->buffer, count);
    262			ret = count;
    263		}
    264	}
    265
    266	msg->reply = reply;
    267
    268out:
    269	return ret;
    270}
    271
    272static void tegra_dpaux_hotplug(struct work_struct *work)
    273{
    274	struct tegra_dpaux *dpaux = work_to_dpaux(work);
    275
    276	if (dpaux->output)
    277		drm_helper_hpd_irq_event(dpaux->output->connector.dev);
    278}
    279
    280static irqreturn_t tegra_dpaux_irq(int irq, void *data)
    281{
    282	struct tegra_dpaux *dpaux = data;
    283	u32 value;
    284
    285	/* clear interrupts */
    286	value = tegra_dpaux_readl(dpaux, DPAUX_INTR_AUX);
    287	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
    288
    289	if (value & (DPAUX_INTR_PLUG_EVENT | DPAUX_INTR_UNPLUG_EVENT))
    290		schedule_work(&dpaux->work);
    291
    292	if (value & DPAUX_INTR_IRQ_EVENT) {
    293		/* TODO: handle this */
    294	}
    295
    296	if (value & DPAUX_INTR_AUX_DONE)
    297		complete(&dpaux->complete);
    298
    299	return IRQ_HANDLED;
    300}
    301
    302enum tegra_dpaux_functions {
    303	DPAUX_PADCTL_FUNC_AUX,
    304	DPAUX_PADCTL_FUNC_I2C,
    305	DPAUX_PADCTL_FUNC_OFF,
    306};
    307
    308static void tegra_dpaux_pad_power_down(struct tegra_dpaux *dpaux)
    309{
    310	u32 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
    311
    312	value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
    313
    314	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
    315}
    316
    317static void tegra_dpaux_pad_power_up(struct tegra_dpaux *dpaux)
    318{
    319	u32 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
    320
    321	value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
    322
    323	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
    324}
    325
    326static int tegra_dpaux_pad_config(struct tegra_dpaux *dpaux, unsigned function)
    327{
    328	u32 value;
    329
    330	switch (function) {
    331	case DPAUX_PADCTL_FUNC_AUX:
    332		value = DPAUX_HYBRID_PADCTL_AUX_CMH(dpaux->soc->cmh) |
    333			DPAUX_HYBRID_PADCTL_AUX_DRVZ(dpaux->soc->drvz) |
    334			DPAUX_HYBRID_PADCTL_AUX_DRVI(dpaux->soc->drvi) |
    335			DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV |
    336			DPAUX_HYBRID_PADCTL_MODE_AUX;
    337		break;
    338
    339	case DPAUX_PADCTL_FUNC_I2C:
    340		value = DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV |
    341			DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
    342			DPAUX_HYBRID_PADCTL_AUX_CMH(dpaux->soc->cmh) |
    343			DPAUX_HYBRID_PADCTL_AUX_DRVZ(dpaux->soc->drvz) |
    344			DPAUX_HYBRID_PADCTL_AUX_DRVI(dpaux->soc->drvi) |
    345			DPAUX_HYBRID_PADCTL_MODE_I2C;
    346		break;
    347
    348	case DPAUX_PADCTL_FUNC_OFF:
    349		tegra_dpaux_pad_power_down(dpaux);
    350		return 0;
    351
    352	default:
    353		return -ENOTSUPP;
    354	}
    355
    356	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL);
    357	tegra_dpaux_pad_power_up(dpaux);
    358
    359	return 0;
    360}
    361
    362#ifdef CONFIG_GENERIC_PINCONF
    363static const struct pinctrl_pin_desc tegra_dpaux_pins[] = {
    364	PINCTRL_PIN(0, "DP_AUX_CHx_P"),
    365	PINCTRL_PIN(1, "DP_AUX_CHx_N"),
    366};
    367
    368static const unsigned tegra_dpaux_pin_numbers[] = { 0, 1 };
    369
    370static const char * const tegra_dpaux_groups[] = {
    371	"dpaux-io",
    372};
    373
    374static const char * const tegra_dpaux_functions[] = {
    375	"aux",
    376	"i2c",
    377	"off",
    378};
    379
    380static int tegra_dpaux_get_groups_count(struct pinctrl_dev *pinctrl)
    381{
    382	return ARRAY_SIZE(tegra_dpaux_groups);
    383}
    384
    385static const char *tegra_dpaux_get_group_name(struct pinctrl_dev *pinctrl,
    386					      unsigned int group)
    387{
    388	return tegra_dpaux_groups[group];
    389}
    390
    391static int tegra_dpaux_get_group_pins(struct pinctrl_dev *pinctrl,
    392				      unsigned group, const unsigned **pins,
    393				      unsigned *num_pins)
    394{
    395	*pins = tegra_dpaux_pin_numbers;
    396	*num_pins = ARRAY_SIZE(tegra_dpaux_pin_numbers);
    397
    398	return 0;
    399}
    400
    401static const struct pinctrl_ops tegra_dpaux_pinctrl_ops = {
    402	.get_groups_count = tegra_dpaux_get_groups_count,
    403	.get_group_name = tegra_dpaux_get_group_name,
    404	.get_group_pins = tegra_dpaux_get_group_pins,
    405	.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
    406	.dt_free_map = pinconf_generic_dt_free_map,
    407};
    408
    409static int tegra_dpaux_get_functions_count(struct pinctrl_dev *pinctrl)
    410{
    411	return ARRAY_SIZE(tegra_dpaux_functions);
    412}
    413
    414static const char *tegra_dpaux_get_function_name(struct pinctrl_dev *pinctrl,
    415						 unsigned int function)
    416{
    417	return tegra_dpaux_functions[function];
    418}
    419
    420static int tegra_dpaux_get_function_groups(struct pinctrl_dev *pinctrl,
    421					   unsigned int function,
    422					   const char * const **groups,
    423					   unsigned * const num_groups)
    424{
    425	*num_groups = ARRAY_SIZE(tegra_dpaux_groups);
    426	*groups = tegra_dpaux_groups;
    427
    428	return 0;
    429}
    430
    431static int tegra_dpaux_set_mux(struct pinctrl_dev *pinctrl,
    432			       unsigned int function, unsigned int group)
    433{
    434	struct tegra_dpaux *dpaux = pinctrl_dev_get_drvdata(pinctrl);
    435
    436	return tegra_dpaux_pad_config(dpaux, function);
    437}
    438
    439static const struct pinmux_ops tegra_dpaux_pinmux_ops = {
    440	.get_functions_count = tegra_dpaux_get_functions_count,
    441	.get_function_name = tegra_dpaux_get_function_name,
    442	.get_function_groups = tegra_dpaux_get_function_groups,
    443	.set_mux = tegra_dpaux_set_mux,
    444};
    445#endif
    446
    447static int tegra_dpaux_probe(struct platform_device *pdev)
    448{
    449	struct tegra_dpaux *dpaux;
    450	struct resource *regs;
    451	u32 value;
    452	int err;
    453
    454	dpaux = devm_kzalloc(&pdev->dev, sizeof(*dpaux), GFP_KERNEL);
    455	if (!dpaux)
    456		return -ENOMEM;
    457
    458	dpaux->soc = of_device_get_match_data(&pdev->dev);
    459	INIT_WORK(&dpaux->work, tegra_dpaux_hotplug);
    460	init_completion(&dpaux->complete);
    461	INIT_LIST_HEAD(&dpaux->list);
    462	dpaux->dev = &pdev->dev;
    463
    464	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    465	dpaux->regs = devm_ioremap_resource(&pdev->dev, regs);
    466	if (IS_ERR(dpaux->regs))
    467		return PTR_ERR(dpaux->regs);
    468
    469	dpaux->irq = platform_get_irq(pdev, 0);
    470	if (dpaux->irq < 0)
    471		return -ENXIO;
    472
    473	if (!pdev->dev.pm_domain) {
    474		dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
    475		if (IS_ERR(dpaux->rst)) {
    476			dev_err(&pdev->dev,
    477				"failed to get reset control: %ld\n",
    478				PTR_ERR(dpaux->rst));
    479			return PTR_ERR(dpaux->rst);
    480		}
    481	}
    482
    483	dpaux->clk = devm_clk_get(&pdev->dev, NULL);
    484	if (IS_ERR(dpaux->clk)) {
    485		dev_err(&pdev->dev, "failed to get module clock: %ld\n",
    486			PTR_ERR(dpaux->clk));
    487		return PTR_ERR(dpaux->clk);
    488	}
    489
    490	dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
    491	if (IS_ERR(dpaux->clk_parent)) {
    492		dev_err(&pdev->dev, "failed to get parent clock: %ld\n",
    493			PTR_ERR(dpaux->clk_parent));
    494		return PTR_ERR(dpaux->clk_parent);
    495	}
    496
    497	err = clk_set_rate(dpaux->clk_parent, 270000000);
    498	if (err < 0) {
    499		dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n",
    500			err);
    501		return err;
    502	}
    503
    504	dpaux->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
    505	if (IS_ERR(dpaux->vdd)) {
    506		if (PTR_ERR(dpaux->vdd) != -ENODEV) {
    507			if (PTR_ERR(dpaux->vdd) != -EPROBE_DEFER)
    508				dev_err(&pdev->dev,
    509					"failed to get VDD supply: %ld\n",
    510					PTR_ERR(dpaux->vdd));
    511
    512			return PTR_ERR(dpaux->vdd);
    513		}
    514
    515		dpaux->vdd = NULL;
    516	}
    517
    518	platform_set_drvdata(pdev, dpaux);
    519	pm_runtime_enable(&pdev->dev);
    520	pm_runtime_get_sync(&pdev->dev);
    521
    522	err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0,
    523			       dev_name(dpaux->dev), dpaux);
    524	if (err < 0) {
    525		dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
    526			dpaux->irq, err);
    527		return err;
    528	}
    529
    530	disable_irq(dpaux->irq);
    531
    532	dpaux->aux.transfer = tegra_dpaux_transfer;
    533	dpaux->aux.dev = &pdev->dev;
    534
    535	drm_dp_aux_init(&dpaux->aux);
    536
    537	/*
    538	 * Assume that by default the DPAUX/I2C pads will be used for HDMI,
    539	 * so power them up and configure them in I2C mode.
    540	 *
    541	 * The DPAUX code paths reconfigure the pads in AUX mode, but there
    542	 * is no possibility to perform the I2C mode configuration in the
    543	 * HDMI path.
    544	 */
    545	err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
    546	if (err < 0)
    547		return err;
    548
    549#ifdef CONFIG_GENERIC_PINCONF
    550	dpaux->desc.name = dev_name(&pdev->dev);
    551	dpaux->desc.pins = tegra_dpaux_pins;
    552	dpaux->desc.npins = ARRAY_SIZE(tegra_dpaux_pins);
    553	dpaux->desc.pctlops = &tegra_dpaux_pinctrl_ops;
    554	dpaux->desc.pmxops = &tegra_dpaux_pinmux_ops;
    555	dpaux->desc.owner = THIS_MODULE;
    556
    557	dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux);
    558	if (IS_ERR(dpaux->pinctrl)) {
    559		dev_err(&pdev->dev, "failed to register pincontrol\n");
    560		return PTR_ERR(dpaux->pinctrl);
    561	}
    562#endif
    563	/* enable and clear all interrupts */
    564	value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT |
    565		DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT;
    566	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_EN_AUX);
    567	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
    568
    569	mutex_lock(&dpaux_lock);
    570	list_add_tail(&dpaux->list, &dpaux_list);
    571	mutex_unlock(&dpaux_lock);
    572
    573	err = devm_of_dp_aux_populate_ep_devices(&dpaux->aux);
    574	if (err < 0) {
    575		dev_err(dpaux->dev, "failed to populate AUX bus: %d\n", err);
    576		return err;
    577	}
    578
    579	return 0;
    580}
    581
    582static int tegra_dpaux_remove(struct platform_device *pdev)
    583{
    584	struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);
    585
    586	cancel_work_sync(&dpaux->work);
    587
    588	/* make sure pads are powered down when not in use */
    589	tegra_dpaux_pad_power_down(dpaux);
    590
    591	pm_runtime_put_sync(&pdev->dev);
    592	pm_runtime_disable(&pdev->dev);
    593
    594	mutex_lock(&dpaux_lock);
    595	list_del(&dpaux->list);
    596	mutex_unlock(&dpaux_lock);
    597
    598	return 0;
    599}
    600
    601#ifdef CONFIG_PM
    602static int tegra_dpaux_suspend(struct device *dev)
    603{
    604	struct tegra_dpaux *dpaux = dev_get_drvdata(dev);
    605	int err = 0;
    606
    607	if (dpaux->rst) {
    608		err = reset_control_assert(dpaux->rst);
    609		if (err < 0) {
    610			dev_err(dev, "failed to assert reset: %d\n", err);
    611			return err;
    612		}
    613	}
    614
    615	usleep_range(1000, 2000);
    616
    617	clk_disable_unprepare(dpaux->clk_parent);
    618	clk_disable_unprepare(dpaux->clk);
    619
    620	return err;
    621}
    622
    623static int tegra_dpaux_resume(struct device *dev)
    624{
    625	struct tegra_dpaux *dpaux = dev_get_drvdata(dev);
    626	int err;
    627
    628	err = clk_prepare_enable(dpaux->clk);
    629	if (err < 0) {
    630		dev_err(dev, "failed to enable clock: %d\n", err);
    631		return err;
    632	}
    633
    634	err = clk_prepare_enable(dpaux->clk_parent);
    635	if (err < 0) {
    636		dev_err(dev, "failed to enable parent clock: %d\n", err);
    637		goto disable_clk;
    638	}
    639
    640	usleep_range(1000, 2000);
    641
    642	if (dpaux->rst) {
    643		err = reset_control_deassert(dpaux->rst);
    644		if (err < 0) {
    645			dev_err(dev, "failed to deassert reset: %d\n", err);
    646			goto disable_parent;
    647		}
    648
    649		usleep_range(1000, 2000);
    650	}
    651
    652	return 0;
    653
    654disable_parent:
    655	clk_disable_unprepare(dpaux->clk_parent);
    656disable_clk:
    657	clk_disable_unprepare(dpaux->clk);
    658	return err;
    659}
    660#endif
    661
    662static const struct dev_pm_ops tegra_dpaux_pm_ops = {
    663	SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL)
    664};
    665
    666static const struct tegra_dpaux_soc tegra124_dpaux_soc = {
    667	.cmh = 0x02,
    668	.drvz = 0x04,
    669	.drvi = 0x18,
    670};
    671
    672static const struct tegra_dpaux_soc tegra210_dpaux_soc = {
    673	.cmh = 0x02,
    674	.drvz = 0x04,
    675	.drvi = 0x30,
    676};
    677
    678static const struct tegra_dpaux_soc tegra194_dpaux_soc = {
    679	.cmh = 0x02,
    680	.drvz = 0x04,
    681	.drvi = 0x2c,
    682};
    683
    684static const struct of_device_id tegra_dpaux_of_match[] = {
    685	{ .compatible = "nvidia,tegra194-dpaux", .data = &tegra194_dpaux_soc },
    686	{ .compatible = "nvidia,tegra186-dpaux", .data = &tegra210_dpaux_soc },
    687	{ .compatible = "nvidia,tegra210-dpaux", .data = &tegra210_dpaux_soc },
    688	{ .compatible = "nvidia,tegra124-dpaux", .data = &tegra124_dpaux_soc },
    689	{ },
    690};
    691MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
    692
    693struct platform_driver tegra_dpaux_driver = {
    694	.driver = {
    695		.name = "tegra-dpaux",
    696		.of_match_table = tegra_dpaux_of_match,
    697		.pm = &tegra_dpaux_pm_ops,
    698	},
    699	.probe = tegra_dpaux_probe,
    700	.remove = tegra_dpaux_remove,
    701};
    702
    703struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np)
    704{
    705	struct tegra_dpaux *dpaux;
    706
    707	mutex_lock(&dpaux_lock);
    708
    709	list_for_each_entry(dpaux, &dpaux_list, list)
    710		if (np == dpaux->dev->of_node) {
    711			mutex_unlock(&dpaux_lock);
    712			return &dpaux->aux;
    713		}
    714
    715	mutex_unlock(&dpaux_lock);
    716
    717	return NULL;
    718}
    719
    720int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output)
    721{
    722	struct tegra_dpaux *dpaux = to_dpaux(aux);
    723	unsigned long timeout;
    724	int err;
    725
    726	aux->drm_dev = output->connector.dev;
    727	err = drm_dp_aux_register(aux);
    728	if (err < 0)
    729		return err;
    730
    731	output->connector.polled = DRM_CONNECTOR_POLL_HPD;
    732	dpaux->output = output;
    733
    734	if (output->panel) {
    735		enum drm_connector_status status;
    736
    737		if (dpaux->vdd) {
    738			err = regulator_enable(dpaux->vdd);
    739			if (err < 0)
    740				return err;
    741		}
    742
    743		timeout = jiffies + msecs_to_jiffies(250);
    744
    745		while (time_before(jiffies, timeout)) {
    746			status = drm_dp_aux_detect(aux);
    747
    748			if (status == connector_status_connected)
    749				break;
    750
    751			usleep_range(1000, 2000);
    752		}
    753
    754		if (status != connector_status_connected)
    755			return -ETIMEDOUT;
    756	}
    757
    758	enable_irq(dpaux->irq);
    759	return 0;
    760}
    761
    762int drm_dp_aux_detach(struct drm_dp_aux *aux)
    763{
    764	struct tegra_dpaux *dpaux = to_dpaux(aux);
    765	unsigned long timeout;
    766	int err;
    767
    768	drm_dp_aux_unregister(aux);
    769	disable_irq(dpaux->irq);
    770
    771	if (dpaux->output->panel) {
    772		enum drm_connector_status status;
    773
    774		if (dpaux->vdd) {
    775			err = regulator_disable(dpaux->vdd);
    776			if (err < 0)
    777				return err;
    778		}
    779
    780		timeout = jiffies + msecs_to_jiffies(250);
    781
    782		while (time_before(jiffies, timeout)) {
    783			status = drm_dp_aux_detect(aux);
    784
    785			if (status == connector_status_disconnected)
    786				break;
    787
    788			usleep_range(1000, 2000);
    789		}
    790
    791		if (status != connector_status_disconnected)
    792			return -ETIMEDOUT;
    793
    794		dpaux->output = NULL;
    795	}
    796
    797	return 0;
    798}
    799
    800enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux)
    801{
    802	struct tegra_dpaux *dpaux = to_dpaux(aux);
    803	u32 value;
    804
    805	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
    806
    807	if (value & DPAUX_DP_AUXSTAT_HPD_STATUS)
    808		return connector_status_connected;
    809
    810	return connector_status_disconnected;
    811}
    812
    813int drm_dp_aux_enable(struct drm_dp_aux *aux)
    814{
    815	struct tegra_dpaux *dpaux = to_dpaux(aux);
    816
    817	return tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_AUX);
    818}
    819
    820int drm_dp_aux_disable(struct drm_dp_aux *aux)
    821{
    822	struct tegra_dpaux *dpaux = to_dpaux(aux);
    823
    824	tegra_dpaux_pad_power_down(dpaux);
    825
    826	return 0;
    827}