xref: /openbmc/u-boot/drivers/misc/aspeed_dp.c (revision d99caab4)
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 
_redriver_cfg(struct udevice * dev)41 static void _redriver_cfg(struct udevice *dev)
42 {
43 	const u32 *cell;
44 	int i, len;
45 	u32 tmp;
46 
47 	// update configs to dmem for re-driver
48 	writel(0x0000dead, 0x18000e00);	// mark re-driver cfg not ready
49 	cell = dev_read_prop(dev, "eq-table", &len);
50 	if (cell) {
51 		for (i = 0; i < len / sizeof(u32); ++i)
52 			writel(fdt32_to_cpu(cell[i]), 0x18000e04 + i * 4);
53 	} else {
54 		debug("%s(): Failed to get eq-table for re-driver\n", __func__);
55 		return;
56 	}
57 
58 	tmp = dev_read_s32_default(dev, "i2c-base-addr", -1);
59 	if (tmp == -1) {
60 		debug("%s(): Failed to get i2c port's base address\n", __func__);
61 		return;
62 	}
63 	writel(tmp, 0x18000e28);
64 
65 	tmp = dev_read_s32_default(dev, "i2c-buf-addr", -1);
66 	if (tmp == -1) {
67 		debug("%s(): Failed to get i2c port's buf address\n", __func__);
68 		return;
69 	}
70 	writel(tmp, 0x18000e2c);
71 
72 	tmp = dev_read_s32_default(dev, "dev-addr", -1);
73 	if (tmp == -1)
74 		tmp = 0x70;
75 	writel(tmp, 0x18000e30);
76 	writel(0x0000cafe, 0x18000e00);	// mark re-driver cfg ready
77 }
78 
aspeed_dp_probe(struct udevice * dev)79 static int aspeed_dp_probe(struct udevice *dev)
80 {
81 	struct aspeed_dp_priv *dp = dev_get_priv(dev);
82 	struct reset_ctl dp_reset_ctl, dpmcu_reset_ctrl;
83 	int i, ret = 0;
84 	u32 mcu_ctrl;
85 	bool is_mcu_stop = ((readl(0x1e6e2100) & BIT(13)) == 0);
86 
87 	/* Get the controller base address */
88 	dp->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
89 
90 	debug("%s(dev=%p) \n", __func__, dev);
91 
92 	ret = reset_get_by_index(dev, 0, &dp_reset_ctl);
93 	if (ret) {
94 		printf("%s(): Failed to get dp reset signal\n", __func__);
95 		return ret;
96 	}
97 
98 	ret = reset_get_by_index(dev, 1, &dpmcu_reset_ctrl);
99 	if (ret) {
100 		printf("%s(): Failed to get dp mcu reset signal\n", __func__);
101 		return ret;
102 	}
103 
104 	/* reset for DPTX and DPMCU if MCU isn't running */
105 	if (is_mcu_stop) {
106 		reset_assert(&dp_reset_ctl);
107 		reset_assert(&dpmcu_reset_ctrl);
108 		reset_deassert(&dp_reset_ctl);
109 		reset_deassert(&dpmcu_reset_ctrl);
110 	}
111 
112 	/* select HOST or BMC as display control master
113 	enable or disable sending EDID to Host	*/
114 	writel(readl(dp->ctrl_base + 0xB8) & ~(BIT(24) | BIT(28)), dp->ctrl_base + 0xB8);
115 
116 	/* DPMCU */
117 	/* clear display format and enable region */
118 	writel(0, 0x18000de0);
119 
120 	_redriver_cfg(dev);
121 
122 	/* load DPMCU firmware to internal instruction memory */
123 	if (is_mcu_stop) {
124 		mcu_ctrl = MCU_CTRL_CONFIG | MCU_CTRL_IMEM_CLK_OFF | MCU_CTRL_IMEM_SHUT_DOWN |
125 		      MCU_CTRL_DMEM_CLK_OFF | MCU_CTRL_DMEM_SHUT_DOWN | MCU_CTRL_AHBS_SW_RST;
126 		writel(mcu_ctrl, MCU_CTRL);
127 
128 		mcu_ctrl &= ~(MCU_CTRL_IMEM_SHUT_DOWN | MCU_CTRL_DMEM_SHUT_DOWN);
129 		writel(mcu_ctrl, MCU_CTRL);
130 
131 		mcu_ctrl &= ~(MCU_CTRL_IMEM_CLK_OFF | MCU_CTRL_DMEM_CLK_OFF);
132 		writel(mcu_ctrl, MCU_CTRL);
133 
134 		mcu_ctrl |= MCU_CTRL_AHBS_IMEM_EN;
135 		writel(mcu_ctrl, MCU_CTRL);
136 
137 		for (i = 0; i < ARRAY_SIZE(firmware_ast2600_dp); i++)
138 			writel(firmware_ast2600_dp[i], MCU_IMEM_START + (i * 4));
139 
140 		/* release DPMCU internal reset */
141 		mcu_ctrl &= ~MCU_CTRL_AHBS_IMEM_EN;
142 		writel(mcu_ctrl, MCU_CTRL);
143 		mcu_ctrl |= MCU_CTRL_CORE_SW_RST | MCU_CTRL_AHBM_SW_RST;
144 		writel(mcu_ctrl, MCU_CTRL);
145 		//disable dp interrupt
146 		writel(FIELD_PREP(MCU_INTR_CTRL_EN, 0xff), MCU_INTR_CTRL);
147 	}
148 
149 	//set vga ASTDP with DPMCU FW handling scratch
150 	writel(readl(0x1e6e2100) | (0x7 << 9), 0x1e6e2100);
151 
152 	return 0;
153 }
154 
dp_aspeed_ofdata_to_platdata(struct udevice * dev)155 static int dp_aspeed_ofdata_to_platdata(struct udevice *dev)
156 {
157 	struct aspeed_dp_priv *dp = dev_get_priv(dev);
158 
159 	/* Get the controller base address */
160 	dp->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
161 
162 	return 0;
163 }
164 
165 static const struct udevice_id aspeed_dp_ids[] = {
166 	{ .compatible = "aspeed,ast2600-displayport" },
167 	{ }
168 };
169 
170 U_BOOT_DRIVER(aspeed_dp) = {
171 	.name		= "aspeed_dp",
172 	.id			= UCLASS_MISC,
173 	.of_match	= aspeed_dp_ids,
174 	.probe		= aspeed_dp_probe,
175 	.ofdata_to_platdata   = dp_aspeed_ofdata_to_platdata,
176 	.priv_auto_alloc_size = sizeof(struct aspeed_dp_priv),
177 };
178