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