blob: 7c0beedc083082fa510e3146f3e2dcc512d74f5d [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>
18
Vincent Chencaeb5112021-07-08 09:08:21 +080019#define UBRDG_RESET SIFIVE_GENERIC_GPIO_NR(0, 7)
20#define ULPI_RESET SIFIVE_GENERIC_GPIO_NR(0, 9)
21#define UHUB_RESET SIFIVE_GENERIC_GPIO_NR(0, 11)
Green Wan2e5da522021-05-27 06:52:13 -070022#define GEM_PHY_RESET SIFIVE_GENERIC_GPIO_NR(0, 12)
23
24#define MODE_SELECT_REG 0x1000
Thomas Skibof50fad62021-11-24 14:32:09 -080025#define MODE_SELECT_SPI 0x6
Green Wan2e5da522021-05-27 06:52:13 -070026#define MODE_SELECT_SD 0xb
27#define MODE_SELECT_MASK GENMASK(3, 0)
28
Vincent Chen5a6def92021-07-08 09:08:20 +080029static inline int spl_reset_device_by_gpio(const char *label, int pin, int low_width)
Green Wan2e5da522021-05-27 06:52:13 -070030{
31 int ret;
32
Vincent Chen5a6def92021-07-08 09:08:20 +080033 ret = gpio_request(pin, label);
Green Wan2e5da522021-05-27 06:52:13 -070034 if (ret) {
Vincent Chen5a6def92021-07-08 09:08:20 +080035 debug("%s gpio request failed: %d\n", label, ret);
36 return ret;
37 }
38
39 ret = gpio_direction_output(pin, 1);
40 if (ret) {
41 debug("%s gpio direction set failed: %d\n", label, ret);
Green Wan2e5da522021-05-27 06:52:13 -070042 return ret;
43 }
44
Vincent Chen5a6def92021-07-08 09:08:20 +080045 udelay(1);
46
47 gpio_set_value(pin, 0);
48 udelay(low_width);
49 gpio_set_value(pin, 1);
50
51 return ret;
52}
53
54static inline int spl_gemgxl_init(void)
55{
56 int ret;
Green Wan2e5da522021-05-27 06:52:13 -070057 /*
58 * GEMGXL init VSC8541 PHY reset sequence;
59 * leave pull-down active for 2ms
60 */
61 udelay(2000);
Vincent Chen5a6def92021-07-08 09:08:20 +080062 ret = spl_reset_device_by_gpio("gem_phy_reset", GEM_PHY_RESET, 1);
63 mdelay(15);
64
65 return ret;
66}
67
Vincent Chencaeb5112021-07-08 09:08:21 +080068static inline int spl_usb_pcie_bridge_init(void)
69{
70 return spl_reset_device_by_gpio("usb_pcie_bridge_reset", UBRDG_RESET, 3000);
71}
72
73static inline int spl_usb_hub_init(void)
74{
75 return spl_reset_device_by_gpio("usb_hub_reset", UHUB_RESET, 100);
76}
77
78static inline int spl_ulpi_init(void)
79{
80 return spl_reset_device_by_gpio("ulpi_reset", ULPI_RESET, 1);
81}
82
Vincent Chen5a6def92021-07-08 09:08:20 +080083int spl_board_init_f(void)
84{
85 int ret;
86
87 ret = spl_soc_init();
Green Wan2e5da522021-05-27 06:52:13 -070088 if (ret) {
Vincent Chen5a6def92021-07-08 09:08:20 +080089 debug("HiFive Unmatched FU740 SPL init failed: %d\n", ret);
90 goto end;
Green Wan2e5da522021-05-27 06:52:13 -070091 }
92
Vincent Chen5a6def92021-07-08 09:08:20 +080093 ret = spl_gemgxl_init();
Green Wan2e5da522021-05-27 06:52:13 -070094 if (ret) {
Vincent Chen5a6def92021-07-08 09:08:20 +080095 debug("Gigabit ethernet PHY (VSC8541) init failed: %d\n", ret);
96 goto end;
Green Wan2e5da522021-05-27 06:52:13 -070097 }
98
Vincent Chencaeb5112021-07-08 09:08:21 +080099 ret = spl_usb_pcie_bridge_init();
100 if (ret) {
101 debug("USB Bridge (ASM1042A) init failed: %d\n", ret);
102 goto end;
103 }
104
105 ret = spl_usb_hub_init();
106 if (ret) {
107 debug("USB Hub (ASM1074) init failed: %d\n", ret);
108 goto end;
109 }
110
111 ret = spl_ulpi_init();
112 if (ret) {
113 debug("USB 2.0 PHY (USB3320C) init failed: %d\n", ret);
114 goto end;
115 }
116
Vincent Chen5a6def92021-07-08 09:08:20 +0800117end:
118 return ret;
Green Wan2e5da522021-05-27 06:52:13 -0700119}
120
121u32 spl_boot_device(void)
122{
123 u32 mode_select = readl((void *)MODE_SELECT_REG);
124 u32 boot_device = mode_select & MODE_SELECT_MASK;
125
126 switch (boot_device) {
Thomas Skibof50fad62021-11-24 14:32:09 -0800127 case MODE_SELECT_SPI:
128 return BOOT_DEVICE_SPI;
Green Wan2e5da522021-05-27 06:52:13 -0700129 case MODE_SELECT_SD:
130 return BOOT_DEVICE_MMC1;
131 default:
132 debug("Unsupported boot device 0x%x but trying MMC1\n",
133 boot_device);
134 return BOOT_DEVICE_MMC1;
135 }
136}
137
138#ifdef CONFIG_SPL_LOAD_FIT
139int board_fit_config_name_match(const char *name)
140{
Zong Li288ad1f2021-07-20 14:26:08 +0800141 /* boot using first FIT config */
142 return 0;
Green Wan2e5da522021-05-27 06:52:13 -0700143}
144#endif