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