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