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 /* 78 * Aspeed STRONGLY NOT recommend to use eSPI early init. 79 * 80 * This eSPI early init sequence merely set OOB_FREE. It 81 * is NOT able to actually handle OOB requests from PCH. 82 * 83 * During the power on stage, PCH keep waiting OOB_FREE 84 * to continue its booting. In general, OOB_FREE is set 85 * when BMC firmware is ready. That is, the eSPI kernel 86 * driver is mounted and ready to serve eSPI. However, 87 * it means that PCH must wait until BMC kernel ready. 88 * 89 * For customers that request PCH booting as soon as 90 * possible. You may use this early init to set OOB_FREE 91 * to prevent PCH from blocking by OOB_FREE before BMC 92 * kernel ready. 93 * 94 * If you are not sure what you are doing, DO NOT use it. 95 */ 96 reg = readl(ESPI_BASE + 0x000); 97 reg |= 0xef; 98 writel(reg, ESPI_BASE + 0x000); 99 100 writel(0x0, ESPI_BASE + 0x110); 101 writel(0x0, ESPI_BASE + 0x114); 102 103 reg = readl(ESPI_BASE + 0x00c); 104 reg |= 0x80000000; 105 writel(reg, ESPI_BASE + 0x00c); 106 107 writel(0xffffffff, ESPI_BASE + 0x094); 108 writel(0x1, ESPI_BASE + 0x100); 109 writel(0x1, ESPI_BASE + 0x120); 110 111 reg = readl(ESPI_BASE + 0x080); 112 reg |= 0x50; 113 writel(reg, ESPI_BASE + 0x080); 114 115 reg = readl(ESPI_BASE + 0x000); 116 reg |= 0x10; 117 writel(reg, ESPI_BASE + 0x000); 118 } 119 120 int board_early_init_f(void) 121 { 122 #if 0 123 port80h_snoop_init(); 124 sgpio_init(); 125 #endif 126 espi_init(); 127 return 0; 128 } 129