xref: /openbmc/u-boot/drivers/pci/pcie_aspeed.c (revision cb41ae03)
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 /* 	AST_PCIE_CFG2			0x04		*/
27 #define PCIE_CFG_CLASS_CODE(x)	(x << 8)
28 #define PCIE_CFG_REV_ID(x)		(x)
29 
30 /* 	AST_PCIE_GLOBAL			0x30 	*/
31 #define ROOT_COMPLEX_ID(x)		(x << 4)
32 
33 /* 	AST_PCIE_LOCK			0x7C	*/
34 #define PCIE_UNLOCK				0xa8
35 
36 /*	AST_PCIE_LINK			0xC0	*/
37 #define PCIE_LINK_STS			BIT(5)
38 
39 struct pcie_aspeed {
40 	void *ctrl_base;
41 	void *h2x_pt;
42 	void *cfg_base;
43 	fdt_size_t cfg_size;
44 
45 	int first_busno;
46 
47 	/* IO and MEM PCI regions */
48 	struct pci_region io;
49 	struct pci_region mem;
50 };
51 
52 static int pcie_addr_valid(pci_dev_t d, int first_busno)
53 {
54 #if 0
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 #endif
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 	aspeed_pcie_cfg_read(pcie->h2x_pt, bdf, offset, valuep);
79 
80 	debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, *valuep);
81 	*valuep = pci_conv_32_to_size(*valuep, offset, size);
82 
83 	return 0;
84 }
85 
86 static int pcie_aspeed_write_config(struct udevice *bus, pci_dev_t bdf,
87 				      uint offset, ulong value,
88 				      enum pci_size_t size)
89 {
90 	struct pcie_aspeed *pcie = dev_get_priv(bus);
91 
92 	debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
93 	      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
94 	debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
95 
96 	if (!pcie_addr_valid(bdf, pcie->first_busno)) {
97 		debug("- out of range\n");
98 		return 0;
99 	}
100 
101 	aspeed_pcie_cfg_write(pcie->h2x_pt, bdf, offset, value, size);
102 
103 	return 0;
104 }
105 
106 static int pcie_aspeed_probe(struct udevice *dev)
107 {
108 	struct pcie_aspeed *pcie = dev_get_priv(dev);
109 	struct udevice *ctlr = pci_get_controller(dev);
110 	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
111 	struct udevice *ahbc_dev, *h2x_dev;
112 	int ret = 0;
113 
114 	ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(aspeed_ahbc),
115 										  &ahbc_dev);
116 	if (ret) {
117 		debug("ahbc device not defined\n");
118 		return ret;
119 	}
120 
121 	ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(aspeed_h2x),
122 										  &h2x_dev);
123 	if (ret) {
124 		debug("h2x device not defined\n");
125 		return ret;
126 	}
127 
128 	pcie->h2x_pt = devfdt_get_addr_ptr(h2x_dev);
129 
130 	aspeed_ahbc_remap_enable(devfdt_get_addr_ptr(ahbc_dev));
131 
132 	//plda enable
133 	writel(PCIE_UNLOCK, pcie->ctrl_base + ASPEED_PCIE_LOCK);
134 	writel(PCIE_CFG_CLASS_CODE(0x60000) | PCIE_CFG_REV_ID(4), pcie->ctrl_base + ASPEED_PCIE_CLASS_CODE);
135 	writel(ROOT_COMPLEX_ID(0x3), pcie->ctrl_base + ASPEED_PCIE_GLOBAL);
136 #if 0
137 	//fpga
138 	writel(0x500460ff, pcie->ctrl_base + 0x2c);
139 #endif
140 
141 	pcie->first_busno = dev->seq;
142 
143 	/* Don't register host if link is down */
144 	if (readl(pcie->ctrl_base + ASPEED_PCIE_LINK) & PCIE_LINK_STS) {
145 		printf("PCIE-%d: Link up\n", dev->seq);
146 	} else {
147 		printf("PCIE-%d: Link down\n", dev->seq);
148 	}
149 
150 	/* Store the IO and MEM windows settings for future use by the ATU */
151 	pcie->io.phys_start = hose->regions[0].phys_start; /* IO base */
152 	pcie->io.bus_start  = hose->regions[0].bus_start;  /* IO_bus_addr */
153 	pcie->io.size	    = hose->regions[0].size;	   /* IO size */
154 
155 	pcie->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
156 	pcie->mem.bus_start  = hose->regions[1].bus_start;  /* MEM_bus_addr */
157 	pcie->mem.size	     = hose->regions[1].size;	    /* MEM size */
158 
159 	return 0;
160 }
161 
162 static int pcie_aspeed_ofdata_to_platdata(struct udevice *dev)
163 {
164 	struct pcie_aspeed *pcie = dev_get_priv(dev);
165 
166 	/* Get the controller base address */
167 	pcie->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
168 
169 	/* Get the config space base address and size */
170 	pcie->cfg_base = (void *)devfdt_get_addr_size_index(dev, 1,
171 							 &pcie->cfg_size);
172 
173 	return 0;
174 }
175 
176 static const struct dm_pci_ops pcie_aspeed_ops = {
177 	.read_config	= pcie_aspeed_read_config,
178 	.write_config	= pcie_aspeed_write_config,
179 };
180 
181 static const struct udevice_id pcie_aspeed_ids[] = {
182 	{ .compatible = "aspeed,ast2600-pcie" },
183 	{ }
184 };
185 
186 U_BOOT_DRIVER(pcie_aspeed) = {
187 	.name			= "pcie_aspeed",
188 	.id				= UCLASS_PCI,
189 	.of_match		= pcie_aspeed_ids,
190 	.ops			= &pcie_aspeed_ops,
191 	.ofdata_to_platdata	= pcie_aspeed_ofdata_to_platdata,
192 	.probe			= pcie_aspeed_probe,
193 	.priv_auto_alloc_size	= sizeof(struct pcie_aspeed),
194 };
195