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