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 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 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 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