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