1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #include <linux/bitops.h>
4 #include <linux/errno.h>
5 #include <linux/io.h>
6 #include <linux/sizes.h>
7 #include <linux/types.h>
8 #include <dm.h>
9 
10 /* System Bus Controller registers */
11 #define UNIPHIER_SBC_BASE	0x100	/* base address of bank0 space */
12 #define    UNIPHIER_SBC_BASE_BE		BIT(0)	/* bank_enable */
13 #define UNIPHIER_SBC_CTRL0	0x200	/* timing parameter 0 of bank0 */
14 #define UNIPHIER_SBC_CTRL1	0x204	/* timing parameter 1 of bank0 */
15 #define UNIPHIER_SBC_CTRL2	0x208	/* timing parameter 2 of bank0 */
16 #define UNIPHIER_SBC_CTRL3	0x20c	/* timing parameter 3 of bank0 */
17 #define UNIPHIER_SBC_CTRL4	0x300	/* timing parameter 4 of bank0 */
18 
19 #define UNIPHIER_SBC_STRIDE	0x10	/* register stride to next bank */
20 
21 #if 1
22 /* slower but LED works */
23 #define SBCTRL0_VALUE	0x55450000
24 #define SBCTRL1_VALUE	0x07168d00
25 #define SBCTRL2_VALUE	0x34000009
26 #define SBCTRL4_VALUE	0x02110110
27 
28 #else
29 /* faster but LED does not work */
30 #define SBCTRL0_VALUE	0x55450000
31 #define SBCTRL1_VALUE	0x06057700
32 /* NOR flash needs more wait counts than SRAM */
33 #define SBCTRL2_VALUE	0x34000009
34 #define SBCTRL4_VALUE	0x02110210
35 #endif
36 
uniphier_system_bus_set_reg(void __iomem * membase)37 void uniphier_system_bus_set_reg(void __iomem *membase)
38 {
39 	void __iomem *bank0_base = membase;
40 	void __iomem *bank1_base = membase + UNIPHIER_SBC_STRIDE;
41 
42 	/*
43 	 * Only CS1 is connected to support card.
44 	 * BKSZ[1:0] should be set to "01".
45 	 */
46 	writel(SBCTRL0_VALUE, bank1_base + UNIPHIER_SBC_CTRL0);
47 	writel(SBCTRL1_VALUE, bank1_base + UNIPHIER_SBC_CTRL1);
48 	writel(SBCTRL2_VALUE, bank1_base + UNIPHIER_SBC_CTRL2);
49 	writel(SBCTRL4_VALUE, bank1_base + UNIPHIER_SBC_CTRL4);
50 
51 	if (readl(bank1_base + UNIPHIER_SBC_BASE) & UNIPHIER_SBC_BASE_BE) {
52 		/*
53 		 * Boot Swap On: boot from external NOR/SRAM
54 		 * 0x42000000-0x43ffffff is a mirror of 0x40000000-0x41ffffff.
55 		 *
56 		 * 0x40000000-0x41efffff, 0x42000000-0x43efffff: memory bank
57 		 * 0x41f00000-0x41ffffff, 0x43f00000-0x43ffffff: peripherals
58 		 */
59 		writel(0x0000bc01, bank0_base + UNIPHIER_SBC_BASE);
60 	} else {
61 		/*
62 		 * Boot Swap Off: boot from mask ROM
63 		 * 0x40000000-0x41ffffff: mask ROM
64 		 * 0x42000000-0x43efffff: memory bank (31MB)
65 		 * 0x43f00000-0x43ffffff: peripherals (1MB)
66 		 */
67 		writel(0x0000be01, bank0_base + UNIPHIER_SBC_BASE); /* dummy */
68 		writel(0x0200be01, bank0_base + UNIPHIER_SBC_BASE);
69 	}
70 }
71 
uniphier_system_bus_probe(struct udevice * dev)72 static int uniphier_system_bus_probe(struct udevice *dev)
73 {
74 	fdt_addr_t base;
75 	void __iomem *membase;
76 
77 	base = dev_read_addr(dev);
78 	if (base == FDT_ADDR_T_NONE)
79 		return -EINVAL;
80 
81 	membase = devm_ioremap(dev, base, SZ_1K);
82 	if (!membase)
83 		return -ENOMEM;
84 
85 	uniphier_system_bus_set_reg(membase);
86 
87 	return 0;
88 }
89 
90 static const struct udevice_id uniphier_system_bus_match[] = {
91 	{ .compatible = "socionext,uniphier-system-bus" },
92 	{ /* sentinel */ }
93 };
94 
95 U_BOOT_DRIVER(uniphier_system_bus_driver) = {
96 	.name	= "uniphier-system-bus",
97 	.id	= UCLASS_SIMPLE_BUS,
98 	.of_match = uniphier_system_bus_match,
99 	.probe = uniphier_system_bus_probe,
100 };
101