blob: e69bed9d99d3054b0e6866ecbc7ffed6a501e3b9 [file] [log] [blame]
Green Wan2e5da522021-05-27 06:52:13 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2020-2021 SiFive, Inc
4 *
5 * Authors:
6 * Pragnesh Patel <pragnesh.patel@sifive.com>
7 */
8
9#include <init.h>
10#include <spl.h>
11#include <misc.h>
12#include <log.h>
13#include <linux/delay.h>
14#include <linux/io.h>
15#include <asm/gpio.h>
16#include <asm/arch/gpio.h>
17#include <asm/arch/spl.h>
Vincent Chen6a842772024-01-16 14:35:57 +080018#include <linux/io.h>
19#include <asm/arch/eeprom.h>
20
21struct pwm_sifive_regs {
22 unsigned int cfg; /* PWM configuration register */
23 unsigned int pad0; /* Reserved */
24 unsigned int cnt; /* PWM count register */
25 unsigned int pad1; /* Reserved */
26 unsigned int pwms; /* Scaled PWM count register */
27 unsigned int pad2; /* Reserved */
28 unsigned int pad3; /* Reserved */
29 unsigned int pad4; /* Reserved */
30 unsigned int cmp0; /* PWM 0 compare register */
31 unsigned int cmp1; /* PWM 1 compare register */
32 unsigned int cmp2; /* PWM 2 compare register */
33 unsigned int cmp3; /* PWM 3 compare register */
34};
35
36#define PWM0_BASE 0x10020000
37#define PWM1_BASE 0x10021000
38#define PWM_CFG_INIT 0x1000
39#define PWM_CMP_ENABLE_VAL 0x0
40#define PWM_CMP_DISABLE_VAL 0xffff
Green Wan2e5da522021-05-27 06:52:13 -070041
Vincent Chencaeb5112021-07-08 09:08:21 +080042#define UBRDG_RESET SIFIVE_GENERIC_GPIO_NR(0, 7)
43#define ULPI_RESET SIFIVE_GENERIC_GPIO_NR(0, 9)
44#define UHUB_RESET SIFIVE_GENERIC_GPIO_NR(0, 11)
Green Wan2e5da522021-05-27 06:52:13 -070045#define GEM_PHY_RESET SIFIVE_GENERIC_GPIO_NR(0, 12)
46
47#define MODE_SELECT_REG 0x1000
Thomas Skibof50fad62021-11-24 14:32:09 -080048#define MODE_SELECT_SPI 0x6
Green Wan2e5da522021-05-27 06:52:13 -070049#define MODE_SELECT_SD 0xb
50#define MODE_SELECT_MASK GENMASK(3, 0)
51
Vincent Chen6a842772024-01-16 14:35:57 +080052void spl_pwm_device_init(void)
53{
54 struct pwm_sifive_regs *pwm0, *pwm1;
55
56 pwm0 = (struct pwm_sifive_regs *)PWM0_BASE;
57 pwm1 = (struct pwm_sifive_regs *)PWM1_BASE;
58 writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp0);
59
60 /* Set the 3-color PWM LEDs to yellow in SPL */
61 writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp1);
62 writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp2);
63 writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp3);
64 writel(PWM_CFG_INIT, (void *)&pwm0->cfg);
65
66 /* Turn on all the fans, (J21), (J23) and (J24), on the unmatched board */
67 /* The SoC fan(J21) on the rev3 board cannot be controlled by PWM_COMP0,
68 * so here sets the initial value of PWM_COMP0 as DISABLE */
69 if (get_pcb_revision_from_eeprom() == PCB_REVISION_REV3)
70 writel(PWM_CMP_DISABLE_VAL, (void *)&pwm1->cmp1);
71 else
72 writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp1);
73
74 writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp2);
75 writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp3);
76 writel(PWM_CFG_INIT, (void *)&pwm1->cfg);
77}
78
Vincent Chen5a6def92021-07-08 09:08:20 +080079static inline int spl_reset_device_by_gpio(const char *label, int pin, int low_width)
Green Wan2e5da522021-05-27 06:52:13 -070080{
81 int ret;
82
Vincent Chen5a6def92021-07-08 09:08:20 +080083 ret = gpio_request(pin, label);
Green Wan2e5da522021-05-27 06:52:13 -070084 if (ret) {
Vincent Chen5a6def92021-07-08 09:08:20 +080085 debug("%s gpio request failed: %d\n", label, ret);
86 return ret;
87 }
88
89 ret = gpio_direction_output(pin, 1);
90 if (ret) {
91 debug("%s gpio direction set failed: %d\n", label, ret);
Green Wan2e5da522021-05-27 06:52:13 -070092 return ret;
93 }
94
Vincent Chen5a6def92021-07-08 09:08:20 +080095 udelay(1);
96
97 gpio_set_value(pin, 0);
98 udelay(low_width);
99 gpio_set_value(pin, 1);
100
101 return ret;
102}
103
104static inline int spl_gemgxl_init(void)
105{
106 int ret;
Green Wan2e5da522021-05-27 06:52:13 -0700107 /*
108 * GEMGXL init VSC8541 PHY reset sequence;
109 * leave pull-down active for 2ms
110 */
111 udelay(2000);
Vincent Chen5a6def92021-07-08 09:08:20 +0800112 ret = spl_reset_device_by_gpio("gem_phy_reset", GEM_PHY_RESET, 1);
113 mdelay(15);
114
115 return ret;
116}
117
Vincent Chencaeb5112021-07-08 09:08:21 +0800118static inline int spl_usb_pcie_bridge_init(void)
119{
120 return spl_reset_device_by_gpio("usb_pcie_bridge_reset", UBRDG_RESET, 3000);
121}
122
123static inline int spl_usb_hub_init(void)
124{
125 return spl_reset_device_by_gpio("usb_hub_reset", UHUB_RESET, 100);
126}
127
128static inline int spl_ulpi_init(void)
129{
130 return spl_reset_device_by_gpio("ulpi_reset", ULPI_RESET, 1);
131}
132
Vincent Chen5a6def92021-07-08 09:08:20 +0800133int spl_board_init_f(void)
134{
135 int ret;
136
137 ret = spl_soc_init();
Green Wan2e5da522021-05-27 06:52:13 -0700138 if (ret) {
Vincent Chen5a6def92021-07-08 09:08:20 +0800139 debug("HiFive Unmatched FU740 SPL init failed: %d\n", ret);
140 goto end;
Green Wan2e5da522021-05-27 06:52:13 -0700141 }
142
Vincent Chen6a842772024-01-16 14:35:57 +0800143 spl_pwm_device_init();
144
Vincent Chen5a6def92021-07-08 09:08:20 +0800145 ret = spl_gemgxl_init();
Green Wan2e5da522021-05-27 06:52:13 -0700146 if (ret) {
Vincent Chen5a6def92021-07-08 09:08:20 +0800147 debug("Gigabit ethernet PHY (VSC8541) init failed: %d\n", ret);
148 goto end;
Green Wan2e5da522021-05-27 06:52:13 -0700149 }
150
Vincent Chencaeb5112021-07-08 09:08:21 +0800151 ret = spl_usb_pcie_bridge_init();
152 if (ret) {
153 debug("USB Bridge (ASM1042A) init failed: %d\n", ret);
154 goto end;
155 }
156
157 ret = spl_usb_hub_init();
158 if (ret) {
159 debug("USB Hub (ASM1074) init failed: %d\n", ret);
160 goto end;
161 }
162
163 ret = spl_ulpi_init();
164 if (ret) {
165 debug("USB 2.0 PHY (USB3320C) init failed: %d\n", ret);
166 goto end;
167 }
168
Vincent Chen5a6def92021-07-08 09:08:20 +0800169end:
170 return ret;
Green Wan2e5da522021-05-27 06:52:13 -0700171}
172
173u32 spl_boot_device(void)
174{
175 u32 mode_select = readl((void *)MODE_SELECT_REG);
176 u32 boot_device = mode_select & MODE_SELECT_MASK;
177
178 switch (boot_device) {
Thomas Skibof50fad62021-11-24 14:32:09 -0800179 case MODE_SELECT_SPI:
180 return BOOT_DEVICE_SPI;
Green Wan2e5da522021-05-27 06:52:13 -0700181 case MODE_SELECT_SD:
182 return BOOT_DEVICE_MMC1;
183 default:
184 debug("Unsupported boot device 0x%x but trying MMC1\n",
185 boot_device);
186 return BOOT_DEVICE_MMC1;
187 }
188}
189
190#ifdef CONFIG_SPL_LOAD_FIT
191int board_fit_config_name_match(const char *name)
192{
Zong Li288ad1f2021-07-20 14:26:08 +0800193 /* boot using first FIT config */
194 return 0;
Green Wan2e5da522021-05-27 06:52:13 -0700195}
196#endif