]>
Commit | Line | Data |
---|---|---|
828d9af5 BM |
1 | /* |
2 | * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
6df7ffea | 8 | #include <mmc.h> |
e4ad6031 BM |
9 | #include <netdev.h> |
10 | #include <phy.h> | |
828d9af5 | 11 | #include <asm/io.h> |
05b98ec3 | 12 | #include <asm/irq.h> |
828d9af5 BM |
13 | #include <asm/pci.h> |
14 | #include <asm/post.h> | |
15 | #include <asm/processor.h> | |
b162257d BM |
16 | #include <asm/arch/device.h> |
17 | #include <asm/arch/msg_port.h> | |
18 | #include <asm/arch/quark.h> | |
19 | ||
6df7ffea BM |
20 | static struct pci_device_id mmc_supported[] = { |
21 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO }, | |
22 | }; | |
23 | ||
728b393f BM |
24 | /* |
25 | * TODO: | |
26 | * | |
27 | * This whole routine should be removed until we fully convert the ICH SPI | |
28 | * driver to DM and make use of DT to pass the bios control register offset | |
29 | */ | |
30 | static void unprotect_spi_flash(void) | |
31 | { | |
32 | u32 bc; | |
33 | ||
aa09505b | 34 | qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, &bc); |
728b393f | 35 | bc |= 0x1; /* unprotect the flash */ |
aa09505b | 36 | qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, bc); |
728b393f BM |
37 | } |
38 | ||
b162257d BM |
39 | static void quark_setup_bars(void) |
40 | { | |
41 | /* GPIO - D31:F0:R44h */ | |
aa09505b BM |
42 | qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA, |
43 | CONFIG_GPIO_BASE | IO_BAR_EN); | |
b162257d BM |
44 | |
45 | /* ACPI PM1 Block - D31:F0:R48h */ | |
aa09505b BM |
46 | qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK, |
47 | CONFIG_ACPI_PM1_BASE | IO_BAR_EN); | |
b162257d BM |
48 | |
49 | /* GPE0 - D31:F0:R4Ch */ | |
aa09505b BM |
50 | qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK, |
51 | CONFIG_ACPI_GPE0_BASE | IO_BAR_EN); | |
b162257d BM |
52 | |
53 | /* WDT - D31:F0:R84h */ | |
aa09505b BM |
54 | qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA, |
55 | CONFIG_WDT_BASE | IO_BAR_EN); | |
b162257d BM |
56 | |
57 | /* RCBA - D31:F0:RF0h */ | |
aa09505b BM |
58 | qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, |
59 | CONFIG_RCBA_BASE | MEM_BAR_EN); | |
b162257d BM |
60 | |
61 | /* ACPI P Block - Msg Port 04:R70h */ | |
62 | msg_port_write(MSG_PORT_RMU, PBLK_BA, | |
63 | CONFIG_ACPI_PBLK_BASE | IO_BAR_EN); | |
64 | ||
65 | /* SPI DMA - Msg Port 04:R7Ah */ | |
66 | msg_port_write(MSG_PORT_RMU, SPI_DMA_BA, | |
67 | CONFIG_SPI_DMA_BASE | IO_BAR_EN); | |
68 | ||
69 | /* PCIe ECAM */ | |
70 | msg_port_write(MSG_PORT_MEM_ARBITER, AEC_CTRL, | |
71 | CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN); | |
72 | msg_port_write(MSG_PORT_HOST_BRIDGE, HEC_REG, | |
73 | CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN); | |
74 | } | |
828d9af5 | 75 | |
316fd392 BM |
76 | static void quark_pcie_early_init(void) |
77 | { | |
78 | u32 pcie_cfg; | |
79 | ||
80 | /* | |
81 | * Step1: Assert PCIe signal PERST# | |
82 | * | |
83 | * The CPU interface to the PERST# signal is platform dependent. | |
84 | * Call the board-specific codes to perform this task. | |
85 | */ | |
86 | board_assert_perst(); | |
87 | ||
88 | /* Step2: PHY common lane reset */ | |
89 | pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); | |
90 | pcie_cfg |= PCIE_PHY_LANE_RST; | |
91 | msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); | |
92 | /* wait 1 ms for PHY common lane reset */ | |
93 | mdelay(1); | |
94 | ||
95 | /* Step3: PHY sideband interface reset and controller main reset */ | |
96 | pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); | |
97 | pcie_cfg |= (PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST); | |
98 | msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); | |
99 | /* wait 80ms for PLL to lock */ | |
100 | mdelay(80); | |
101 | ||
102 | /* Step4: Controller sideband interface reset */ | |
103 | pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); | |
104 | pcie_cfg |= PCIE_CTLR_SB_RST; | |
105 | msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); | |
106 | /* wait 20ms for controller sideband interface reset */ | |
107 | mdelay(20); | |
108 | ||
109 | /* Step5: De-assert PERST# */ | |
110 | board_deassert_perst(); | |
111 | ||
112 | /* Step6: Controller primary interface reset */ | |
113 | pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); | |
114 | pcie_cfg |= PCIE_CTLR_PRI_RST; | |
115 | msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); | |
116 | ||
117 | /* Mixer Load Lane 0 */ | |
118 | pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0); | |
119 | pcie_cfg &= ~((1 << 6) | (1 << 7)); | |
120 | msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0, pcie_cfg); | |
121 | ||
122 | /* Mixer Load Lane 1 */ | |
123 | pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1); | |
124 | pcie_cfg &= ~((1 << 6) | (1 << 7)); | |
125 | msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg); | |
126 | } | |
127 | ||
f82a7840 BM |
128 | static void quark_enable_legacy_seg(void) |
129 | { | |
130 | u32 hmisc2; | |
131 | ||
132 | hmisc2 = msg_port_read(MSG_PORT_HOST_BRIDGE, HMISC2); | |
133 | hmisc2 |= (HMISC2_SEGE | HMISC2_SEGF | HMISC2_SEGAB); | |
134 | msg_port_write(MSG_PORT_HOST_BRIDGE, HMISC2, hmisc2); | |
135 | } | |
136 | ||
828d9af5 BM |
137 | int arch_cpu_init(void) |
138 | { | |
139 | struct pci_controller *hose; | |
140 | int ret; | |
141 | ||
142 | post_code(POST_CPU_INIT); | |
143 | #ifdef CONFIG_SYS_X86_TSC_TIMER | |
144 | timer_set_base(rdtsc()); | |
145 | #endif | |
146 | ||
147 | ret = x86_cpu_init_f(); | |
148 | if (ret) | |
149 | return ret; | |
150 | ||
151 | ret = pci_early_init_hose(&hose); | |
152 | if (ret) | |
153 | return ret; | |
154 | ||
b162257d BM |
155 | /* |
156 | * Quark SoC has some non-standard BARs (excluding PCI standard BARs) | |
157 | * which need be initialized with suggested values | |
158 | */ | |
159 | quark_setup_bars(); | |
160 | ||
316fd392 BM |
161 | /* |
162 | * Initialize PCIe controller | |
163 | * | |
164 | * Quark SoC holds the PCIe controller in reset following a power on. | |
165 | * U-Boot needs to release the PCIe controller from reset. The PCIe | |
166 | * controller (D23:F0/F1) will not be visible in PCI configuration | |
167 | * space and any access to its PCI configuration registers will cause | |
168 | * system hang while it is held in reset. | |
169 | */ | |
170 | quark_pcie_early_init(); | |
171 | ||
f82a7840 BM |
172 | /* Turn on legacy segments (A/B/E/F) decode to system RAM */ |
173 | quark_enable_legacy_seg(); | |
174 | ||
728b393f BM |
175 | unprotect_spi_flash(); |
176 | ||
828d9af5 BM |
177 | return 0; |
178 | } | |
179 | ||
180 | int print_cpuinfo(void) | |
181 | { | |
182 | post_code(POST_CPU_INFO); | |
183 | return default_print_cpuinfo(); | |
184 | } | |
185 | ||
186 | void reset_cpu(ulong addr) | |
187 | { | |
188 | /* cold reset */ | |
ebebf059 | 189 | x86_full_reset(); |
828d9af5 | 190 | } |
6df7ffea BM |
191 | |
192 | int cpu_mmc_init(bd_t *bis) | |
193 | { | |
194 | return pci_mmc_init("Quark SDHCI", mmc_supported, | |
195 | ARRAY_SIZE(mmc_supported)); | |
196 | } | |
e4ad6031 BM |
197 | |
198 | int cpu_eth_init(bd_t *bis) | |
199 | { | |
200 | u32 base; | |
201 | int ret0, ret1; | |
202 | ||
aa09505b | 203 | qrk_pci_read_config_dword(QUARK_EMAC0, PCI_BASE_ADDRESS_0, &base); |
e4ad6031 BM |
204 | ret0 = designware_initialize(base, PHY_INTERFACE_MODE_RMII); |
205 | ||
aa09505b | 206 | qrk_pci_read_config_dword(QUARK_EMAC1, PCI_BASE_ADDRESS_0, &base); |
e4ad6031 BM |
207 | ret1 = designware_initialize(base, PHY_INTERFACE_MODE_RMII); |
208 | ||
209 | if (ret0 < 0 && ret1 < 0) | |
210 | return -1; | |
211 | else | |
212 | return 0; | |
213 | } | |
05b98ec3 BM |
214 | |
215 | void cpu_irq_init(void) | |
216 | { | |
217 | struct quark_rcba *rcba; | |
218 | u32 base; | |
219 | ||
aa09505b | 220 | qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base); |
05b98ec3 BM |
221 | base &= ~MEM_BAR_EN; |
222 | rcba = (struct quark_rcba *)base; | |
223 | ||
224 | /* | |
225 | * Route Quark PCI device interrupt pin to PIRQ | |
226 | * | |
227 | * Route device#23's INTA/B/C/D to PIRQA/B/C/D | |
228 | * Route device#20,21's INTA/B/C/D to PIRQE/F/G/H | |
229 | */ | |
230 | writew(PIRQC, &rcba->rmu_ir); | |
231 | writew(PIRQA | (PIRQB << 4) | (PIRQC << 8) | (PIRQD << 12), | |
232 | &rcba->d23_ir); | |
233 | writew(PIRQD, &rcba->core_ir); | |
234 | writew(PIRQE | (PIRQF << 4) | (PIRQG << 8) | (PIRQH << 12), | |
235 | &rcba->d20d21_ir); | |
236 | } | |
237 | ||
238 | int arch_misc_init(void) | |
239 | { | |
7e4be120 | 240 | return pirq_init(); |
05b98ec3 | 241 | } |