1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) ASPEED Technology Inc. 4 */ 5 #include <common.h> 6 #include <asm/io.h> 7 8 #define SCU_BASE 0x1e6e2000 9 #define ESPI_BASE 0x1e6ee000 10 #define LPC_BASE 0x1e789000 11 #define LPC_HICR5 (LPC_BASE + 0x80) 12 #define LPC_HICR6 (LPC_BASE + 0x84) 13 #define LPC_SNPWADR (LPC_BASE + 0x90) 14 #define LPC_HICRB (LPC_BASE + 0x100) 15 #define GPIO_BASE 0x1e780000 16 17 /* HICR5 Bits */ 18 #define HICR5_EN_SIOGIO (1 << 31) /* Enable SIOGIO */ 19 #define HICR5_EN80HGIO (1 << 30) /* Enable 80hGIO */ 20 #define HICR5_SEL80HGIO (0x1f << 24) /* Select 80hGIO */ 21 #define SET_SEL80HGIO(x) ((x & 0x1f) << 24) /* Select 80hGIO Offset */ 22 #define HICR5_UNKVAL_MASK 0x1FFF0000 /* Bits with unknown values on reset */ 23 #define HICR5_ENINT_SNP0W (1 << 1) /* Enable Snooping address 0 */ 24 #define HICR5_EN_SNP0W (1 << 0) /* Enable Snooping address 0 */ 25 26 /* HRCR6 Bits */ 27 #define HICR6_STR_SNP0W (1 << 0) /* Interrupt Status Snoop address 0 */ 28 #define HICR6_STR_SNP1W (1 << 1) /* Interrupt Status Snoop address 1 */ 29 30 /* HICRB Bits */ 31 #define HICRB_EN80HSGIO (1 << 13) /* Enable 80hSGIO */ 32 33 static void __maybe_unused port80h_snoop_init(void) 34 { 35 u32 value; 36 /* enable port80h snoop and sgpio */ 37 /* set lpc snoop #0 to port 0x80 */ 38 value = readl(LPC_SNPWADR) & 0xffff0000; 39 writel(value | 0x80, LPC_SNPWADR); 40 41 /* clear interrupt status */ 42 value = readl(LPC_HICR6); 43 value |= HICR6_STR_SNP0W | HICR6_STR_SNP1W; 44 writel(value, LPC_HICR6); 45 46 /* enable lpc snoop #0 and SIOGIO */ 47 value = readl(LPC_HICR5) & ~(HICR5_UNKVAL_MASK); 48 value |= HICR5_EN_SIOGIO | HICR5_EN_SNP0W; 49 writel(value, LPC_HICR5); 50 51 /* enable port80h snoop on SGPIO */ 52 value = readl(LPC_HICRB) | HICRB_EN80HSGIO; 53 writel(value, LPC_HICRB); 54 } 55 56 static void __maybe_unused sgpio_init(void) 57 { 58 #define SGPIO_CLK_DIV(N) ((N) << 16) 59 #define SGPIO_BYTES(N) ((N) << 6) 60 #define SGPIO_ENABLE 1 61 #define GPIO554 0x554 62 #define SCU_414 0x414 /* Multi-function Pin Control #5 */ 63 #define SCU_414_SGPM_MASK GENMASK(27, 24) 64 65 u32 value; 66 /* set the sgpio clock to pclk/(2*(5+1)) or ~2 MHz */ 67 value = SGPIO_CLK_DIV(256) | SGPIO_BYTES(10) | SGPIO_ENABLE; 68 writel(value, GPIO_BASE + GPIO554); 69 writel(readl(SCU_BASE | SCU_414) | SCU_414_SGPM_MASK, 70 SCU_BASE | SCU_414); 71 } 72 73 static void __maybe_unused espi_init(void) 74 { 75 u32 reg; 76 77 /* skip eSPI init if LPC mode is selected */ 78 reg = readl(SCU_BASE + 0x510); 79 if (reg & BIT(6)) 80 return; 81 82 /* 83 * Aspeed STRONGLY NOT recommend to use eSPI early init. 84 * 85 * This eSPI early init sequence merely set OOB_FREE. It 86 * is NOT able to actually handle OOB requests from PCH. 87 * 88 * During the power on stage, PCH keep waiting OOB_FREE 89 * to continue its booting. In general, OOB_FREE is set 90 * when BMC firmware is ready. That is, the eSPI kernel 91 * driver is mounted and ready to serve eSPI. However, 92 * it means that PCH must wait until BMC kernel ready. 93 * 94 * For customers that request PCH booting as soon as 95 * possible. You may use this early init to set OOB_FREE 96 * to prevent PCH from blocking by OOB_FREE before BMC 97 * kernel ready. 98 * 99 * If you are not sure what you are doing, DO NOT use it. 100 */ 101 reg = readl(ESPI_BASE + 0x000); 102 reg |= 0xef; 103 writel(reg, ESPI_BASE + 0x000); 104 105 writel(0x0, ESPI_BASE + 0x110); 106 writel(0x0, ESPI_BASE + 0x114); 107 108 reg = readl(ESPI_BASE + 0x00c); 109 reg |= 0x80000000; 110 writel(reg, ESPI_BASE + 0x00c); 111 112 writel(0xffffffff, ESPI_BASE + 0x094); 113 writel(0x1, ESPI_BASE + 0x100); 114 writel(0x1, ESPI_BASE + 0x120); 115 116 reg = readl(ESPI_BASE + 0x080); 117 reg |= 0x50; 118 writel(reg, ESPI_BASE + 0x080); 119 120 reg = readl(ESPI_BASE + 0x000); 121 reg |= 0x10; 122 writel(reg, ESPI_BASE + 0x000); 123 } 124 125 int board_early_init_f(void) 126 { 127 #if 0 128 port80h_snoop_init(); 129 sgpio_init(); 130 #endif 131 espi_init(); 132 return 0; 133 } 134