1b20c38a9SStefan Roese /*
2b20c38a9SStefan Roese * Copyright (C) 2015-2016 Stefan Roese <sr@denx.de>
3b20c38a9SStefan Roese *
4b20c38a9SStefan Roese * SPDX-License-Identifier: GPL-2.0+
5b20c38a9SStefan Roese */
6b20c38a9SStefan Roese
7b20c38a9SStefan Roese #include <common.h>
8169a8550SStefan Roese #include <i2c.h>
9169a8550SStefan Roese #include <pci.h>
10ced0d849SStefan Roese #include <asm/gpio.h>
11b20c38a9SStefan Roese #include <asm/io.h>
12b20c38a9SStefan Roese #include <asm/arch/cpu.h>
13b20c38a9SStefan Roese #include <asm/arch/soc.h>
14169a8550SStefan Roese #include <linux/crc8.h>
15aea02abeSStefan Roese #include <linux/mbus.h>
16b20c38a9SStefan Roese #ifdef CONFIG_NET
17b20c38a9SStefan Roese #include <netdev.h>
18b20c38a9SStefan Roese #endif
19aea02abeSStefan Roese #include "theadorable.h"
20b20c38a9SStefan Roese
21b20c38a9SStefan Roese #include "../drivers/ddr/marvell/axp/ddr3_hw_training.h"
22b20c38a9SStefan Roese #include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h"
23b20c38a9SStefan Roese
24b20c38a9SStefan Roese DECLARE_GLOBAL_DATA_PTR;
25b20c38a9SStefan Roese
26ced0d849SStefan Roese #define MV_USB_PHY_BASE (MVEBU_AXP_USB_BASE + 0x800)
27ced0d849SStefan Roese #define PHY_CHANNEL_RX_CTRL0_REG(port, chan) \
28ced0d849SStefan Roese (MV_USB_PHY_BASE + ((port) << 12) + ((chan) << 6) + 0x8)
29ced0d849SStefan Roese
30b20c38a9SStefan Roese #define THEADORABLE_GPP_OUT_ENA_LOW 0x00336780
31b20c38a9SStefan Roese #define THEADORABLE_GPP_OUT_ENA_MID 0x00003cf0
32b20c38a9SStefan Roese #define THEADORABLE_GPP_OUT_ENA_HIGH (~(0x0))
33b20c38a9SStefan Roese
34b20c38a9SStefan Roese #define THEADORABLE_GPP_OUT_VAL_LOW 0x2c0c983f
35b20c38a9SStefan Roese #define THEADORABLE_GPP_OUT_VAL_MID 0x0007000c
36b20c38a9SStefan Roese #define THEADORABLE_GPP_OUT_VAL_HIGH 0x00000000
37b20c38a9SStefan Roese
38ced0d849SStefan Roese #define GPIO_USB0_PWR_ON 18
39ced0d849SStefan Roese #define GPIO_USB1_PWR_ON 19
40ced0d849SStefan Roese
41169a8550SStefan Roese #define PEX_SWITCH_NOT_FOUNT_LIMIT 3
42169a8550SStefan Roese
43169a8550SStefan Roese #define STM_I2C_BUS 1
44169a8550SStefan Roese #define STM_I2C_ADDR 0x27
45169a8550SStefan Roese #define REBOOT_DELAY 1000 /* reboot-delay in ms */
46169a8550SStefan Roese
47b20c38a9SStefan Roese /* DDR3 static configuration */
48b20c38a9SStefan Roese static MV_DRAM_MC_INIT ddr3_theadorable[MV_MAX_DDR3_STATIC_SIZE] = {
49b20c38a9SStefan Roese {0x00001400, 0x7301ca28}, /* DDR SDRAM Configuration Register */
50b20c38a9SStefan Roese {0x00001404, 0x30000800}, /* Dunit Control Low Register */
51b20c38a9SStefan Roese {0x00001408, 0x44149887}, /* DDR SDRAM Timing (Low) Register */
52b20c38a9SStefan Roese {0x0000140C, 0x38d93fc7}, /* DDR SDRAM Timing (High) Register */
53b20c38a9SStefan Roese {0x00001410, 0x1b100001}, /* DDR SDRAM Address Control Register */
54b20c38a9SStefan Roese {0x00001424, 0x0000f3ff}, /* Dunit Control High Register */
55b20c38a9SStefan Roese {0x00001428, 0x000f8830}, /* ODT Timing (Low) Register */
56b20c38a9SStefan Roese {0x0000142C, 0x014c50f4}, /* DDR3 Timing Register */
57b20c38a9SStefan Roese {0x0000147C, 0x0000c671}, /* ODT Timing (High) Register */
58b20c38a9SStefan Roese
59b20c38a9SStefan Roese {0x00001494, 0x00010000}, /* DDR SDRAM ODT Control (Low) Reg */
60b20c38a9SStefan Roese {0x0000149C, 0x00000001}, /* DDR Dunit ODT Control Register */
61b20c38a9SStefan Roese {0x000014A0, 0x00000001}, /* DRAM FIFO Control Register */
62b20c38a9SStefan Roese {0x000014A8, 0x00000101}, /* AXI Control Register */
63b20c38a9SStefan Roese
64b20c38a9SStefan Roese /*
65b20c38a9SStefan Roese * DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the
66b20c38a9SStefan Roese * training sequence
67b20c38a9SStefan Roese */
68b20c38a9SStefan Roese {0x000200e8, 0x3fff0e01},
69b20c38a9SStefan Roese {0x00020184, 0x3fffffe0}, /* Close fast path Window to - 2G */
70b20c38a9SStefan Roese
71b20c38a9SStefan Roese {0x0001504, 0x7fffffe1}, /* CS0 Size */
72b20c38a9SStefan Roese {0x000150C, 0x00000000}, /* CS1 Size */
73b20c38a9SStefan Roese {0x0001514, 0x00000000}, /* CS2 Size */
74b20c38a9SStefan Roese {0x000151C, 0x00000000}, /* CS3 Size */
75b20c38a9SStefan Roese
76b20c38a9SStefan Roese {0x00020220, 0x00000007}, /* Reserved */
77b20c38a9SStefan Roese
78b20c38a9SStefan Roese {0x00001538, 0x00000009}, /* Read Data Sample Delays Register */
79b20c38a9SStefan Roese {0x0000153C, 0x00000009}, /* Read Data Ready Delay Register */
80b20c38a9SStefan Roese
81b20c38a9SStefan Roese {0x000015D0, 0x00000650}, /* MR0 */
82b20c38a9SStefan Roese {0x000015D4, 0x00000044}, /* MR1 */
83b20c38a9SStefan Roese {0x000015D8, 0x00000010}, /* MR2 */
84b20c38a9SStefan Roese {0x000015DC, 0x00000000}, /* MR3 */
85b20c38a9SStefan Roese {0x000015E0, 0x00000001},
86b20c38a9SStefan Roese {0x000015E4, 0x00203c18}, /* ZQDS Configuration Register */
87b20c38a9SStefan Roese {0x000015EC, 0xf800a225}, /* DDR PHY */
88b20c38a9SStefan Roese
89b20c38a9SStefan Roese /* Recommended Settings from Marvell for 4 x 16 bit devices: */
90b20c38a9SStefan Roese {0x000014C0, 0x192424c9}, /* DRAM addr and Ctrl Driving Strenght*/
91b20c38a9SStefan Roese {0x000014C4, 0x0aaa24c9}, /* DRAM Data and DQS Driving Strenght */
92b20c38a9SStefan Roese
93b20c38a9SStefan Roese {0x0, 0x0}
94b20c38a9SStefan Roese };
95b20c38a9SStefan Roese
96b20c38a9SStefan Roese static MV_DRAM_MODES board_ddr_modes[MV_DDR3_MODES_NUMBER] = {
97b20c38a9SStefan Roese {"theadorable_1333-667", 0x3, 0x5, 0x0, A0, ddr3_theadorable, NULL},
98b20c38a9SStefan Roese };
99b20c38a9SStefan Roese
100b20c38a9SStefan Roese extern MV_SERDES_CHANGE_M_PHY serdes_change_m_phy[];
101b20c38a9SStefan Roese
102b20c38a9SStefan Roese /*
103b20c38a9SStefan Roese * Lane0 - PCIE0.0 X1 (to WIFI Module)
104b20c38a9SStefan Roese * Lane5 - SATA0
105b20c38a9SStefan Roese * Lane6 - SATA1
106b20c38a9SStefan Roese * Lane7 - SGMII0 (to Ethernet Phy)
107b20c38a9SStefan Roese * Lane8-11 - PCIE2.0 X4 (to PEX Switch)
108b20c38a9SStefan Roese * all other lanes are disabled
109b20c38a9SStefan Roese */
110b20c38a9SStefan Roese MV_BIN_SERDES_CFG theadorable_serdes_cfg[] = {
111b20c38a9SStefan Roese { MV_PEX_ROOT_COMPLEX, 0x22200001, 0x00001111,
112b20c38a9SStefan Roese { PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4,
113b20c38a9SStefan Roese PEX_BUS_DISABLED },
114b20c38a9SStefan Roese 0x0060, serdes_change_m_phy
115b20c38a9SStefan Roese },
116b20c38a9SStefan Roese };
117b20c38a9SStefan Roese
1189627ce2dSStefan Roese /*
1199627ce2dSStefan Roese * Define a board-specific detection pulse-width array for the SerDes PCIe
1209627ce2dSStefan Roese * interfaces. If not defined in the board code, the default of currently 2
1219627ce2dSStefan Roese * is used. Values from 0...3 are possible (2 bits).
1229627ce2dSStefan Roese */
1239627ce2dSStefan Roese u8 serdes_pex_pulse_width[4] = { 0, 2, 2, 2 };
1249627ce2dSStefan Roese
ddr3_get_static_ddr_mode(void)125b20c38a9SStefan Roese MV_DRAM_MODES *ddr3_get_static_ddr_mode(void)
126b20c38a9SStefan Roese {
127b20c38a9SStefan Roese /* Only one mode supported for this board */
128b20c38a9SStefan Roese return &board_ddr_modes[0];
129b20c38a9SStefan Roese }
130b20c38a9SStefan Roese
board_serdes_cfg_get(u8 pex_mode)131b20c38a9SStefan Roese MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
132b20c38a9SStefan Roese {
133b20c38a9SStefan Roese return &theadorable_serdes_cfg[0];
134b20c38a9SStefan Roese }
135b20c38a9SStefan Roese
board_sat_r_get(u8 dev_num,u8 reg)1369ed00b07SStefan Roese u8 board_sat_r_get(u8 dev_num, u8 reg)
1379ed00b07SStefan Roese {
1389ed00b07SStefan Roese /* Bit 0 enables PCI 2.0 link capabilities instead of PCI 1.x */
1399ed00b07SStefan Roese return 0x01;
1409ed00b07SStefan Roese }
1419ed00b07SStefan Roese
board_early_init_f(void)142b20c38a9SStefan Roese int board_early_init_f(void)
143b20c38a9SStefan Roese {
144b20c38a9SStefan Roese /* Configure MPP */
145b20c38a9SStefan Roese writel(0x00000000, MVEBU_MPP_BASE + 0x00);
146b20c38a9SStefan Roese writel(0x03300000, MVEBU_MPP_BASE + 0x04);
147b20c38a9SStefan Roese writel(0x00000033, MVEBU_MPP_BASE + 0x08);
148b20c38a9SStefan Roese writel(0x00000000, MVEBU_MPP_BASE + 0x0c);
149b20c38a9SStefan Roese writel(0x11110000, MVEBU_MPP_BASE + 0x10);
150b20c38a9SStefan Roese writel(0x00221100, MVEBU_MPP_BASE + 0x14);
151b20c38a9SStefan Roese writel(0x00000000, MVEBU_MPP_BASE + 0x18);
152b20c38a9SStefan Roese writel(0x00000000, MVEBU_MPP_BASE + 0x1c);
153b20c38a9SStefan Roese writel(0x00000000, MVEBU_MPP_BASE + 0x20);
154b20c38a9SStefan Roese
155b20c38a9SStefan Roese /* Configure GPIO */
156b20c38a9SStefan Roese writel(THEADORABLE_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
157b20c38a9SStefan Roese writel(THEADORABLE_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
158b20c38a9SStefan Roese writel(THEADORABLE_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
159b20c38a9SStefan Roese writel(THEADORABLE_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
160b20c38a9SStefan Roese writel(THEADORABLE_GPP_OUT_VAL_HIGH, MVEBU_GPIO2_BASE + 0x00);
161b20c38a9SStefan Roese writel(THEADORABLE_GPP_OUT_ENA_HIGH, MVEBU_GPIO2_BASE + 0x04);
162b20c38a9SStefan Roese
163b20c38a9SStefan Roese return 0;
164b20c38a9SStefan Roese }
165b20c38a9SStefan Roese
board_init(void)166b20c38a9SStefan Roese int board_init(void)
167b20c38a9SStefan Roese {
168ced0d849SStefan Roese int ret;
169ced0d849SStefan Roese
170b20c38a9SStefan Roese /* adress of boot parameters */
171b20c38a9SStefan Roese gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
172b20c38a9SStefan Roese
173aea02abeSStefan Roese /*
174aea02abeSStefan Roese * Map SPI devices via MBUS so that they can be accessed via
175aea02abeSStefan Roese * the SPI direct access mode
176aea02abeSStefan Roese */
177aea02abeSStefan Roese mbus_dt_setup_win(&mbus_state, SPI_BUS0_DEV1_BASE, SPI_BUS0_DEV1_SIZE,
178aea02abeSStefan Roese CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI0_CS1);
179aea02abeSStefan Roese mbus_dt_setup_win(&mbus_state, SPI_BUS1_DEV2_BASE, SPI_BUS0_DEV1_SIZE,
180aea02abeSStefan Roese CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI1_CS2);
181aea02abeSStefan Roese
182ced0d849SStefan Roese /*
183ced0d849SStefan Roese * Set RX Channel Control 0 Register:
184ced0d849SStefan Roese * Tests have shown, that setting the LPF_COEF from 0 (1/8)
185ced0d849SStefan Roese * to 3 (1/1) results in a more stable USB connection.
186ced0d849SStefan Roese */
187ced0d849SStefan Roese setbits_le32(PHY_CHANNEL_RX_CTRL0_REG(0, 1), 0xc);
188ced0d849SStefan Roese setbits_le32(PHY_CHANNEL_RX_CTRL0_REG(0, 2), 0xc);
189ced0d849SStefan Roese setbits_le32(PHY_CHANNEL_RX_CTRL0_REG(0, 3), 0xc);
190ced0d849SStefan Roese
191ced0d849SStefan Roese /* Toggle USB power */
192ced0d849SStefan Roese ret = gpio_request(GPIO_USB0_PWR_ON, "USB0_PWR_ON");
193ced0d849SStefan Roese if (ret < 0)
194ced0d849SStefan Roese return ret;
195ced0d849SStefan Roese gpio_direction_output(GPIO_USB0_PWR_ON, 0);
196ced0d849SStefan Roese ret = gpio_request(GPIO_USB1_PWR_ON, "USB1_PWR_ON");
197ced0d849SStefan Roese if (ret < 0)
198ced0d849SStefan Roese return ret;
199ced0d849SStefan Roese gpio_direction_output(GPIO_USB1_PWR_ON, 0);
200ced0d849SStefan Roese mdelay(1);
201ced0d849SStefan Roese gpio_set_value(GPIO_USB0_PWR_ON, 1);
202ced0d849SStefan Roese gpio_set_value(GPIO_USB1_PWR_ON, 1);
203ced0d849SStefan Roese
204b20c38a9SStefan Roese return 0;
205b20c38a9SStefan Roese }
206b20c38a9SStefan Roese
checkboard(void)207b20c38a9SStefan Roese int checkboard(void)
208b20c38a9SStefan Roese {
209aea02abeSStefan Roese board_fpga_add();
210aea02abeSStefan Roese
211b20c38a9SStefan Roese return 0;
212b20c38a9SStefan Roese }
213b20c38a9SStefan Roese
214b20c38a9SStefan Roese #ifdef CONFIG_NET
board_eth_init(bd_t * bis)215b20c38a9SStefan Roese int board_eth_init(bd_t *bis)
216b20c38a9SStefan Roese {
217b20c38a9SStefan Roese cpu_eth_init(bis); /* Built in controller(s) come first */
218b20c38a9SStefan Roese return pci_eth_init(bis);
219b20c38a9SStefan Roese }
220b20c38a9SStefan Roese #endif
221b20c38a9SStefan Roese
board_video_init(void)222b20c38a9SStefan Roese int board_video_init(void)
223b20c38a9SStefan Roese {
224b20c38a9SStefan Roese struct mvebu_lcd_info lcd_info;
225b20c38a9SStefan Roese
226b20c38a9SStefan Roese /* Reserved memory area via CONFIG_SYS_MEM_TOP_HIDE */
227b20c38a9SStefan Roese lcd_info.fb_base = gd->ram_size;
228b20c38a9SStefan Roese lcd_info.x_res = 240;
229b20c38a9SStefan Roese lcd_info.x_fp = 1;
230b20c38a9SStefan Roese lcd_info.x_bp = 45;
231b20c38a9SStefan Roese lcd_info.y_res = 320;
232b20c38a9SStefan Roese lcd_info.y_fp = 1;
233b20c38a9SStefan Roese lcd_info.y_bp = 3;
234b20c38a9SStefan Roese
235b20c38a9SStefan Roese return mvebu_lcd_register_init(&lcd_info);
236b20c38a9SStefan Roese }
237169a8550SStefan Roese
238169a8550SStefan Roese #ifdef CONFIG_BOARD_LATE_INIT
board_late_init(void)239169a8550SStefan Roese int board_late_init(void)
240169a8550SStefan Roese {
241169a8550SStefan Roese pci_dev_t bdf;
242169a8550SStefan Roese ulong bootcount;
243169a8550SStefan Roese
244169a8550SStefan Roese /*
245169a8550SStefan Roese * Check if the PEX switch is detected (somtimes its not available
246169a8550SStefan Roese * on the PCIe bus). In this case, try to recover by issuing a
247169a8550SStefan Roese * soft-reset or even a power-cycle, depending on the bootcounter
248169a8550SStefan Roese * value.
249169a8550SStefan Roese */
250169a8550SStefan Roese bdf = pci_find_device(PCI_VENDOR_ID_PLX, 0x8619, 0);
251169a8550SStefan Roese if (bdf == -1) {
252169a8550SStefan Roese u8 i2c_buf[8];
253169a8550SStefan Roese int ret;
254169a8550SStefan Roese
255169a8550SStefan Roese /* PEX switch not found! */
256169a8550SStefan Roese bootcount = bootcount_load();
257169a8550SStefan Roese printf("Failed to find PLX PEX-switch (bootcount=%ld)\n",
258169a8550SStefan Roese bootcount);
259169a8550SStefan Roese if (bootcount > PEX_SWITCH_NOT_FOUNT_LIMIT) {
260169a8550SStefan Roese printf("Issuing power-switch via uC!\n");
261169a8550SStefan Roese
262169a8550SStefan Roese printf("Issuing power-switch via uC!\n");
263169a8550SStefan Roese i2c_set_bus_num(STM_I2C_BUS);
264169a8550SStefan Roese i2c_buf[0] = STM_I2C_ADDR << 1;
265169a8550SStefan Roese i2c_buf[1] = 0xc5; /* cmd */
266169a8550SStefan Roese i2c_buf[2] = 0x01; /* enable */
267169a8550SStefan Roese /* Delay before reboot */
268169a8550SStefan Roese i2c_buf[3] = REBOOT_DELAY & 0x00ff;
269169a8550SStefan Roese i2c_buf[4] = (REBOOT_DELAY & 0xff00) >> 8;
270169a8550SStefan Roese /* Delay before shutdown */
271169a8550SStefan Roese i2c_buf[5] = 0x00;
272169a8550SStefan Roese i2c_buf[6] = 0x00;
273169a8550SStefan Roese i2c_buf[7] = crc8(0x72, &i2c_buf[0], 7);
274169a8550SStefan Roese
275169a8550SStefan Roese ret = i2c_write(STM_I2C_ADDR, 0, 0, &i2c_buf[1], 7);
276169a8550SStefan Roese if (ret) {
277169a8550SStefan Roese printf("I2C write error (ret=%d)\n", ret);
278169a8550SStefan Roese printf("Issuing soft-reset...\n");
279169a8550SStefan Roese /* default handling: SOFT reset */
280169a8550SStefan Roese do_reset(NULL, 0, 0, NULL);
281169a8550SStefan Roese }
282169a8550SStefan Roese
283169a8550SStefan Roese /* Wait for power-cycle to occur... */
284169a8550SStefan Roese printf("Waiting for power-cycle via uC...\n");
285169a8550SStefan Roese while (1)
286169a8550SStefan Roese ;
287169a8550SStefan Roese } else {
288169a8550SStefan Roese printf("Issuing soft-reset...\n");
289169a8550SStefan Roese /* default handling: SOFT reset */
290169a8550SStefan Roese do_reset(NULL, 0, 0, NULL);
291169a8550SStefan Roese }
292169a8550SStefan Roese }
293169a8550SStefan Roese
294169a8550SStefan Roese return 0;
295169a8550SStefan Roese }
296169a8550SStefan Roese #endif
297*55e0306cSStefan Roese
298*55e0306cSStefan Roese #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_PCI)
do_pcie_test(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])299*55e0306cSStefan Roese int do_pcie_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
300*55e0306cSStefan Roese {
301*55e0306cSStefan Roese pci_dev_t bdf;
302*55e0306cSStefan Roese u16 ven_id, dev_id;
303*55e0306cSStefan Roese
304*55e0306cSStefan Roese if (argc != 3)
305*55e0306cSStefan Roese return cmd_usage(cmdtp);
306*55e0306cSStefan Roese
307*55e0306cSStefan Roese ven_id = simple_strtoul(argv[1], NULL, 16);
308*55e0306cSStefan Roese dev_id = simple_strtoul(argv[2], NULL, 16);
309*55e0306cSStefan Roese
310*55e0306cSStefan Roese printf("Checking for PCIe device: VendorID 0x%04x, DeviceId 0x%04x\n",
311*55e0306cSStefan Roese ven_id, dev_id);
312*55e0306cSStefan Roese
313*55e0306cSStefan Roese /*
314*55e0306cSStefan Roese * Check if the PCIe device is detected (somtimes its not available
315*55e0306cSStefan Roese * on the PCIe bus)
316*55e0306cSStefan Roese */
317*55e0306cSStefan Roese bdf = pci_find_device(ven_id, dev_id, 0);
318*55e0306cSStefan Roese if (bdf == -1) {
319*55e0306cSStefan Roese /* PCIe device not found! */
320*55e0306cSStefan Roese printf("Failed to find PCIe device\n");
321*55e0306cSStefan Roese } else {
322*55e0306cSStefan Roese /* PCIe device found! */
323*55e0306cSStefan Roese printf("PCIe device found, resetting board...\n");
324*55e0306cSStefan Roese
325*55e0306cSStefan Roese /* default handling: SOFT reset */
326*55e0306cSStefan Roese do_reset(NULL, 0, 0, NULL);
327*55e0306cSStefan Roese }
328*55e0306cSStefan Roese
329*55e0306cSStefan Roese return 0;
330*55e0306cSStefan Roese }
331*55e0306cSStefan Roese
332*55e0306cSStefan Roese U_BOOT_CMD(
333*55e0306cSStefan Roese pcie, 3, 0, do_pcie_test,
334*55e0306cSStefan Roese "Test for presence of a PCIe device",
335*55e0306cSStefan Roese "<VendorID> <DeviceID>"
336*55e0306cSStefan Roese );
337*55e0306cSStefan Roese #endif
338