xref: /openbmc/u-boot/drivers/pci/pcie_aspeed.c (revision fd0bc623)
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_ctl;
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_ctl);
111 	if (ret) {
112 		printf("%s(): Failed to get reset signal\n", __func__);
113 		return ret;
114 	}
115 
116 	reset_assert(&reset_ctl);
117 	mdelay(100);
118 	reset_deassert(&reset_ctl);
119 
120 	ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(aspeed_ahbc),
121 										  &ahbc_dev);
122 	if (ret) {
123 		debug("ahbc device not defined\n");
124 		return ret;
125 	}
126 
127 	h2x_of_handle = fdtdec_lookup_phandle(fdt, dev_of_offset(dev), "cfg-handle");
128 	if (h2x_of_handle > 0) {
129 		pcie->h2x_pt = (void *)fdtdec_get_addr(fdt, h2x_of_handle, "reg");
130 		debug("h2x cfg addr %x \n", (u32)pcie->h2x_pt);
131 	} else {
132 		debug("h2x device not defined\n");
133 		return h2x_of_handle;
134 	}
135 
136 	aspeed_ahbc_remap_enable(devfdt_get_addr_ptr(ahbc_dev));
137 
138 	//plda enable
139 	writel(PCIE_UNLOCK, pcie->ctrl_base + ASPEED_PCIE_LOCK);
140 	writel(ROOT_COMPLEX_ID(0x3), pcie->ctrl_base + ASPEED_PCIE_GLOBAL);
141 
142 	pcie->first_busno = dev->seq;
143 	mdelay(100);
144 
145 	/* Don't register host if link is down */
146 	if (readl(pcie->ctrl_base + ASPEED_PCIE_LINK) & PCIE_LINK_STS) {
147 #if 0
148 		printf("PCIE-%d: Link up - ", dev->seq);
149 		if(readl(pcie->ctrl_base + ASPEED_PCIE_LINK_STS) & PCIE_LINK_5G)
150 			printf("5G \n");
151 		if(readl(pcie->ctrl_base + ASPEED_PCIE_LINK_STS) & PCIE_LINK_2_5G)
152 			printf("2.5G \n");
153 #endif
154 		pcie->link_sts = 1;
155 	} else {
156 		printf("PCIE-%d: Link down\n", dev->seq);
157 		pcie->link_sts = 0;
158 	}
159 	aspeed_h2x_rc_enable(pcie->h2x_pt);
160 	if(pcie->link_sts)
161 		aspeed_pcie_workaround(pcie->h2x_pt);
162 
163 	return 0;
164 }
165 
166 static int pcie_aspeed_ofdata_to_platdata(struct udevice *dev)
167 {
168 	struct pcie_aspeed *pcie = dev_get_priv(dev);
169 
170 	/* Get the controller base address */
171 	pcie->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
172 
173 	/* Get the config space base address and size */
174 	pcie->cfg_base = (void *)devfdt_get_addr_size_index(dev, 1,
175 							 &pcie->cfg_size);
176 
177 	return 0;
178 }
179 
180 static const struct dm_pci_ops pcie_aspeed_ops = {
181 	.read_config	= pcie_aspeed_read_config,
182 	.write_config	= pcie_aspeed_write_config,
183 };
184 
185 static const struct udevice_id pcie_aspeed_ids[] = {
186 	{ .compatible = "aspeed,ast2600-pcie" },
187 	{ }
188 };
189 
190 U_BOOT_DRIVER(pcie_aspeed) = {
191 	.name			= "pcie_aspeed",
192 	.id				= UCLASS_PCI,
193 	.of_match		= pcie_aspeed_ids,
194 	.ops			= &pcie_aspeed_ops,
195 	.ofdata_to_platdata	= pcie_aspeed_ofdata_to_platdata,
196 	.probe			= pcie_aspeed_probe,
197 	.priv_auto_alloc_size	= sizeof(struct pcie_aspeed),
198 };
199