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