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