blob: 7868111d8446e4b1838cc15d904f74348b2fcd39 [file] [log] [blame]
Chia-Wei Wang1c7ed532024-09-10 17:39:16 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) Aspeed Technology Inc.
4 */
5#include <asm/io.h>
6#include <asm/arch/sli.h>
7#include <asm/arch/scu.h>
8#include <linux/bitfield.h>
9#include <linux/bitops.h>
10
11#define SLI_POLL_TIMEOUT_US 100
12
13static void sli_clear_interrupt_status(uint32_t base)
14{
15 writel(-1, (void *)base + SLI_INTR_STATUS);
16}
17
18static int sli_wait(uint32_t base, uint32_t mask)
19{
20 uint32_t value;
21
22 sli_clear_interrupt_status(base);
23
24 do {
25 value = readl((void *)base + SLI_INTR_STATUS);
26 if (value & SLI_INTR_RX_ERRORS)
27 return -1;
28 } while ((value & mask) != mask);
29
30 return 0;
31}
32
33static int sli_wait_suspend(uint32_t base)
34{
35 return sli_wait(base, SLI_INTR_TX_SUSPEND | SLI_INTR_RX_SUSPEND);
36}
37
38/*
39 * CPU die --- downstream pads ---> I/O die
40 * CPU die <--- upstream pads ----- I/O die
41 *
42 * US/DS PAD[3:0] : SLIM[3:0]
43 * US/DS PAD[5:4] : SLIH[1:0]
44 * US/DS PAD[7:6] : SLIV[1:0]
45 */
46int sli_init(void)
47{
48 uint32_t value;
49
50 /* The following training sequence is designed for AST2700A0 */
51 value = FIELD_GET(SCU1_REVISION_HWID, readl(SCU1_REVISION));
52 if (value)
53 return 0;
54
55 /* Return if SLI had been calibrated */
56 value = readl((void *)SLIH_IOD_BASE + SLI_CTRL_III);
57 value = FIELD_GET(SLI_CLK_SEL, value);
58 if (value) {
59 debug("SLI has been initialized\n");
60 return 0;
61 }
62
63 /* 25MHz PAD delay for AST2700A0 */
64 value = SLI_RX_PHY_LAH_SEL_NEG | SLI_TRANS_EN | SLI_CLEAR_BUS;
65 writel(value, (void *)SLIH_IOD_BASE + SLI_CTRL_I);
66 writel(value, (void *)SLIM_IOD_BASE + SLI_CTRL_I);
67 writel(value | SLIV_RAW_MODE, (void *)SLIV_IOD_BASE + SLI_CTRL_I);
68 sli_wait_suspend(SLIH_IOD_BASE);
69 sli_wait_suspend(SLIH_CPU_BASE);
70
71 return 0;
72}