xref: /openbmc/u-boot/drivers/misc/aspeed_dp.c (revision 4298c59cf183374fac535e5de8364642096944d2)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) ASPEED Technology Inc.
4  */
5 
6 #include <linux/bitfield.h>
7 #include <common.h>
8 #include <clk.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <reset.h>
12 #include <fdtdec.h>
13 #include <asm/io.h>
14 #include "dp_mcu_firmware.h"
15 
16 #define MCU_CTRL                        0x180100e0
17 #define  MCU_CTRL_AHBS_IMEM_EN          BIT(0)
18 #define  MCU_CTRL_AHBS_SW_RST           BIT(4)
19 #define  MCU_CTRL_AHBM_SW_RST           BIT(8)
20 #define  MCU_CTRL_CORE_SW_RST           BIT(12)
21 #define  MCU_CTRL_DMEM_SHUT_DOWN        BIT(16)
22 #define  MCU_CTRL_DMEM_SLEEP            BIT(17)
23 #define  MCU_CTRL_DMEM_CLK_OFF          BIT(18)
24 #define  MCU_CTRL_IMEM_SHUT_DOWN        BIT(20)
25 #define  MCU_CTRL_IMEM_SLEEP            BIT(21)
26 #define  MCU_CTRL_IMEM_CLK_OFF          BIT(22)
27 #define  MCU_CTRL_IMEM_SEL              BIT(24)
28 #define  MCU_CTRL_CONFIG                BIT(28)
29 
30 #define MCU_INTR_CTRL                   0x180100e8
31 #define  MCU_INTR_CTRL_CLR              GENMASK(7, 0)
32 #define  MCU_INTR_CTRL_MASK             GENMASK(15, 8)
33 #define  MCU_INTR_CTRL_EN               GENMASK(23, 16)
34 
35 #define MCU_IMEM_START                  0x18020000
36 
37 struct aspeed_dp_priv {
38 	void *ctrl_base;
39 };
40 
41 static int aspeed_dp_probe(struct udevice *dev)
42 {
43 	struct aspeed_dp_priv *dp = dev_get_priv(dev);
44 	struct reset_ctl dp_reset_ctl, dpmcu_reset_ctrl;
45 	int i, ret = 0, len;
46 	const u32 *cell;
47 	u32 tmp, mcu_ctrl;
48 
49 	/* Get the controller base address */
50 	dp->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
51 
52 	debug("%s(dev=%p) \n", __func__, dev);
53 
54 	ret = reset_get_by_index(dev, 0, &dp_reset_ctl);
55 	if (ret) {
56 		printf("%s(): Failed to get dp reset signal\n", __func__);
57 		return ret;
58 	}
59 
60 	ret = reset_get_by_index(dev, 1, &dpmcu_reset_ctrl);
61 	if (ret) {
62 		printf("%s(): Failed to get dp mcu reset signal\n", __func__);
63 		return ret;
64 	}
65 
66 	/* reset for DPTX and DPMCU if MCU isn't running */
67 	if ((readl(0x1e6e2100) & BIT(13)) == 0) {
68 		reset_assert(&dp_reset_ctl);
69 		reset_assert(&dpmcu_reset_ctrl);
70 		reset_deassert(&dp_reset_ctl);
71 		reset_deassert(&dpmcu_reset_ctrl);
72 	}
73 
74 	/* select HOST or BMC as display control master
75 	enable or disable sending EDID to Host	*/
76 	writel(readl(dp->ctrl_base + 0xB8) & ~(BIT(24) | BIT(28)), dp->ctrl_base + 0xB8);
77 
78 	/* DPMCU */
79 	/* clear display format and enable region */
80 	writel(0, 0x18000de0);
81 
82 	/* load DPMCU firmware to internal instruction memory */
83 	mcu_ctrl = MCU_CTRL_CONFIG | MCU_CTRL_IMEM_CLK_OFF | MCU_CTRL_IMEM_SHUT_DOWN |
84 	      MCU_CTRL_DMEM_CLK_OFF | MCU_CTRL_DMEM_SHUT_DOWN | MCU_CTRL_AHBS_SW_RST;
85 	writel(mcu_ctrl, MCU_CTRL);
86 
87 	mcu_ctrl &= ~(MCU_CTRL_IMEM_SHUT_DOWN | MCU_CTRL_DMEM_SHUT_DOWN);
88 	writel(mcu_ctrl, MCU_CTRL);
89 
90 	mcu_ctrl &= ~(MCU_CTRL_IMEM_CLK_OFF | MCU_CTRL_DMEM_CLK_OFF);
91 	writel(mcu_ctrl, MCU_CTRL);
92 
93 	mcu_ctrl |= MCU_CTRL_AHBS_IMEM_EN;
94 	writel(mcu_ctrl, MCU_CTRL);
95 
96 	for (i = 0; i < ARRAY_SIZE(firmware_ast2600_dp); i++)
97 		writel(firmware_ast2600_dp[i], MCU_IMEM_START + (i * 4));
98 
99 	// update configs to dmem for re-driver
100 	writel(0x0000dead, 0x18000e00);	// mark re-driver cfg not ready
101 	cell = dev_read_prop(dev, "eq-table", &len);
102 	if (cell) {
103 		for (i = 0; i < len / sizeof(u32); ++i)
104 			writel(fdt32_to_cpu(cell[i]), 0x18000e04 + i * 4);
105 	} else {
106 		debug("%s(): Failed to get eq-table for re-driver\n", __func__);
107 		goto ERR_DTS;
108 	}
109 
110 	tmp = dev_read_s32_default(dev, "i2c-base-addr", -1);
111 	if (tmp == -1) {
112 		debug("%s(): Failed to get i2c port's base address\n", __func__);
113 		goto ERR_DTS;
114 	}
115 	writel(tmp, 0x18000e28);
116 
117 	tmp = dev_read_s32_default(dev, "i2c-buf-addr", -1);
118 	if (tmp == -1) {
119 		debug("%s(): Failed to get i2c port's buf address\n", __func__);
120 		goto ERR_DTS;
121 	}
122 	writel(tmp, 0x18000e2c);
123 
124 	tmp = dev_read_s32_default(dev, "dev-addr", -1);
125 	if (tmp == -1)
126 		tmp = 0x70;
127 	writel(tmp, 0x18000e30);
128 	writel(0x0000cafe, 0x18000e00);	// mark re-driver cfg ready
129 
130 ERR_DTS:
131 	/* release DPMCU internal reset */
132 	mcu_ctrl &= ~MCU_CTRL_AHBS_IMEM_EN;
133 	writel(mcu_ctrl, MCU_CTRL);
134 	mcu_ctrl |= MCU_CTRL_CORE_SW_RST | MCU_CTRL_AHBM_SW_RST;
135 	writel(mcu_ctrl, MCU_CTRL);
136 	//disable dp interrupt
137 	writel(FIELD_PREP(MCU_INTR_CTRL_EN, 0xff), MCU_INTR_CTRL);
138 	//set vga ASTDP with DPMCU FW handling scratch
139 	writel(readl(0x1e6e2100) | (0x7 << 9), 0x1e6e2100);
140 
141 	return 0;
142 }
143 
144 static int dp_aspeed_ofdata_to_platdata(struct udevice *dev)
145 {
146 	struct aspeed_dp_priv *dp = dev_get_priv(dev);
147 
148 	/* Get the controller base address */
149 	dp->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
150 
151 	return 0;
152 }
153 
154 static const struct udevice_id aspeed_dp_ids[] = {
155 	{ .compatible = "aspeed,ast2600-displayport" },
156 	{ }
157 };
158 
159 U_BOOT_DRIVER(aspeed_dp) = {
160 	.name		= "aspeed_dp",
161 	.id			= UCLASS_MISC,
162 	.of_match	= aspeed_dp_ids,
163 	.probe		= aspeed_dp_probe,
164 	.ofdata_to_platdata   = dp_aspeed_ofdata_to_platdata,
165 	.priv_auto_alloc_size = sizeof(struct aspeed_dp_priv),
166 };
167