xref: /openbmc/u-boot/drivers/pci/pcie_aspeed.c (revision fb79a3bf)
1 // SPDX-License-Identifier: GPL-2.0+
2 #include <common.h>
3 #include <dm.h>
4 #include <reset.h>
5 #include <fdtdec.h>
6 #include <pci.h>
7 #include <asm/io.h>
8 #include <asm/arch/h2x_ast2600.h>
9 #include <asm/arch/ahbc_aspeed.h>
10 
11 DECLARE_GLOBAL_DATA_PTR;
12 
13 /* PCI Host Controller registers */
14 
15 #define ASPEED_PCIE_CLASS_CODE		0x04
16 #define ASPEED_PCIE_GLOBAL			0x30
17 #define ASPEED_PCIE_CFG_DIN			0x50
18 #define ASPEED_PCIE_CFG3			0x58
19 #define ASPEED_PCIE_LOCK			0x7C
20 #define ASPEED_PCIE_LINK			0xC0
21 #define ASPEED_PCIE_INT				0xC4
22 
23 /* 	AST_PCIE_CFG2			0x04		*/
24 #define PCIE_CFG_CLASS_CODE(x)	(x << 8)
25 #define PCIE_CFG_REV_ID(x)		(x)
26 
27 /* 	AST_PCIE_GLOBAL			0x30 	*/
28 #define ROOT_COMPLEX_ID(x)		(x << 4)
29 
30 /* 	AST_PCIE_LOCK			0x7C	*/
31 #define PCIE_UNLOCK				0xa8
32 
33 /*	AST_PCIE_LINK			0xC0	*/
34 #define PCIE_LINK_STS			BIT(5)
35 
36 struct pcie_aspeed {
37 	void *ctrl_base;
38 	void *h2x_pt;
39 	void *cfg_base;
40 	fdt_size_t cfg_size;
41 	int link_sts;
42 	int first_busno;
43 };
44 
45 static int pcie_aspeed_read_config(struct udevice *bus, pci_dev_t bdf,
46 				     uint offset, ulong *valuep,
47 				     enum pci_size_t size)
48 {
49 	struct pcie_aspeed *pcie = dev_get_priv(bus);
50 
51 	debug("PCIE CFG read:  (b,d,f)=(%2d,%2d,%2d) \n",
52 	      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
53 
54 	/* Only allow one other device besides the local one on the local bus */
55 	if (PCI_BUS(bdf) == 1 && PCI_DEV(bdf) != 0) {
56 			debug("- out of range\n");
57 			/*
58 			 * If local dev is 0, the first other dev can
59 			 * only be 1
60 			 */
61 			*valuep = pci_get_ff(size);
62 			return 0;
63 	}
64 
65 	if (PCI_BUS(bdf) == 1 && (!pcie->link_sts)) {
66 		*valuep = pci_get_ff(size);
67 		return 0;
68 	}
69 
70 	aspeed_pcie_cfg_read(pcie->h2x_pt, bdf, offset, valuep);
71 
72 	debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, *valuep);
73 	*valuep = pci_conv_32_to_size(*valuep, offset, size);
74 
75 	return 0;
76 }
77 
78 static int pcie_aspeed_write_config(struct udevice *bus, pci_dev_t bdf,
79 				      uint offset, ulong value,
80 				      enum pci_size_t size)
81 {
82 	struct pcie_aspeed *pcie = dev_get_priv(bus);
83 
84 	debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
85 	      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
86 	debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
87 
88 	aspeed_pcie_cfg_write(pcie->h2x_pt, bdf, offset, value, size);
89 
90 	return 0;
91 }
92 
93 static int pcie_aspeed_probe(struct udevice *dev)
94 {
95 	struct reset_ctl reset_ctl0, reset_ctl1;
96 	struct pcie_aspeed *pcie = dev_get_priv(dev);
97 	struct udevice *ctlr = pci_get_controller(dev);
98 	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
99 	struct udevice *ahbc_dev, *h2x_dev;
100 	int ret = 0;
101 
102 	ret = reset_get_by_index(dev, 0, &reset_ctl0);
103 	if (ret) {
104 		printf("%s(): Failed to get reset signal\n", __func__);
105 		return ret;
106 	}
107 
108 	ret = reset_get_by_index(dev, 1, &reset_ctl1);
109 	if (ret) {
110 		printf("%s(): Failed to get reset signal\n", __func__);
111 		return ret;
112 	}
113 
114 	reset_assert(&reset_ctl0);
115 	reset_assert(&reset_ctl1);
116 	mdelay(100);
117 	reset_deassert(&reset_ctl0);
118 
119 	ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(aspeed_ahbc),
120 										  &ahbc_dev);
121 	if (ret) {
122 		debug("ahbc device not defined\n");
123 		return ret;
124 	}
125 
126 	ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(aspeed_h2x),
127 										  &h2x_dev);
128 	if (ret) {
129 		debug("h2x device not defined\n");
130 		return ret;
131 	}
132 
133 	pcie->h2x_pt = devfdt_get_addr_ptr(h2x_dev);
134 
135 	aspeed_ahbc_remap_enable(devfdt_get_addr_ptr(ahbc_dev));
136 
137 	//plda enable
138 	writel(PCIE_UNLOCK, pcie->ctrl_base + ASPEED_PCIE_LOCK);
139 //	writel(PCIE_CFG_CLASS_CODE(0x60000) | PCIE_CFG_REV_ID(4), pcie->ctrl_base + ASPEED_PCIE_CLASS_CODE);
140 	writel(ROOT_COMPLEX_ID(0x3), pcie->ctrl_base + ASPEED_PCIE_GLOBAL);
141 #if 0
142 	//fpga
143 	writel(0x500460ff, pcie->ctrl_base + 0x2c);
144 #endif
145 
146 	pcie->first_busno = dev->seq;
147 	mdelay(100);
148 
149 	/* Don't register host if link is down */
150 	if (readl(pcie->ctrl_base + ASPEED_PCIE_LINK) & PCIE_LINK_STS) {
151 		printf("PCIE-%d: Link up\n", dev->seq);
152 		pcie->link_sts = 1;
153 	} else {
154 		printf("PCIE-%d: Link down\n", dev->seq);
155 		pcie->link_sts = 0;
156 	}
157 
158 	/* System memory space */
159 	pci_set_region(hose->regions + 0,
160 			   0, 0,
161 			   gd->ram_size,
162 			   PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
163 
164 	/* PCI memory space */
165 	pci_set_region(hose->regions + 1, 0x60000000,
166 			   0x60000000, 0x10000000, PCI_REGION_IO);
167 
168 	/* PCI I/O space */
169 	pci_set_region(hose->regions + 2, 0x70000000,
170 			   0x70000000, 0x10000000, PCI_REGION_MEM);
171 
172 	hose->region_count = 3;
173 
174 	return 0;
175 }
176 
177 static int pcie_aspeed_ofdata_to_platdata(struct udevice *dev)
178 {
179 	struct pcie_aspeed *pcie = dev_get_priv(dev);
180 
181 	/* Get the controller base address */
182 	pcie->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
183 
184 	/* Get the config space base address and size */
185 	pcie->cfg_base = (void *)devfdt_get_addr_size_index(dev, 1,
186 							 &pcie->cfg_size);
187 
188 	return 0;
189 }
190 
191 static const struct dm_pci_ops pcie_aspeed_ops = {
192 	.read_config	= pcie_aspeed_read_config,
193 	.write_config	= pcie_aspeed_write_config,
194 };
195 
196 static const struct udevice_id pcie_aspeed_ids[] = {
197 	{ .compatible = "aspeed,ast2600-pcie" },
198 	{ }
199 };
200 
201 U_BOOT_DRIVER(pcie_aspeed) = {
202 	.name			= "pcie_aspeed",
203 	.id				= UCLASS_PCI,
204 	.of_match		= pcie_aspeed_ids,
205 	.ops			= &pcie_aspeed_ops,
206 	.ofdata_to_platdata	= pcie_aspeed_ofdata_to_platdata,
207 	.probe			= pcie_aspeed_probe,
208 	.priv_auto_alloc_size	= sizeof(struct pcie_aspeed),
209 };
210