1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Texas Instruments, Inc
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <log.h>
9 #include <pci.h>
10 #include <generic-phy.h>
11 #include <power-domain.h>
12 #include <regmap.h>
13 #include <syscon.h>
14 #include <asm/global_data.h>
15 #include <asm/io.h>
16 #include <asm-generic/gpio.h>
17 #include <dm/device_compat.h>
18 #include <linux/bitops.h>
19 #include <linux/delay.h>
20 #include <linux/err.h>
21 
22 #include "pcie_dw_common.h"
23 
24 DECLARE_GLOBAL_DATA_PTR;
25 
26 #define PCIE_VENDORID_MASK	GENMASK(15, 0)
27 #define PCIE_DEVICEID_SHIFT	16
28 
29 #define PCIE_LINK_CAPABILITY		0x7c
30 #define PCIE_LINK_CTL_2			0xa0
31 #define TARGET_LINK_SPEED_MASK		0xf
32 #define LINK_SPEED_GEN_1		0x1
33 #define LINK_SPEED_GEN_2		0x2
34 #define LINK_SPEED_GEN_3		0x3
35 
36 #define PCIE_MISC_CONTROL_1_OFF		0x8bc
37 #define PCIE_DBI_RO_WR_EN		BIT(0)
38 
39 #define PLR_OFFSET			0x700
40 #define PCIE_PORT_DEBUG0		(PLR_OFFSET + 0x28)
41 #define PORT_LOGIC_LTSSM_STATE_MASK	0x1f
42 #define PORT_LOGIC_LTSSM_STATE_L0	0x11
43 
44 #define PCIE_LINK_UP_TIMEOUT_MS		100
45 
46 /* Offsets from App base */
47 #define PCIE_CMD_STATUS			0x04
48 #define LTSSM_EN_VAL			BIT(0)
49 
50 
51 #define AM654_PCIE_DEV_TYPE_MASK	0x3
52 #define EP				0x0
53 #define LEG_EP				0x1
54 #define RC				0x2
55 
56 /**
57  * struct pcie_dw_ti - TI DW PCIe controller state
58  *
59  * @pci: The common PCIe DW structure
60  * @app_base: The base address of application register space
61  */
62 struct pcie_dw_ti {
63 	/* Must be first member of the struct */
64 	struct pcie_dw dw;
65 	void *app_base;
66 };
67 
68 enum dw_pcie_device_mode {
69 	DW_PCIE_UNKNOWN_TYPE,
70 	DW_PCIE_EP_TYPE,
71 	DW_PCIE_LEG_EP_TYPE,
72 	DW_PCIE_RC_TYPE,
73 };
74 
75 /**
76  * pcie_dw_configure() - Configure link capabilities and speed
77  *
78  * @regs_base: A pointer to the PCIe controller registers
79  * @cap_speed: The capabilities and speed to configure
80  *
81  * Configure the link capabilities and speed in the PCIe root complex.
82  */
pcie_dw_configure(struct pcie_dw_ti * pci,u32 cap_speed)83 static void pcie_dw_configure(struct pcie_dw_ti *pci, u32 cap_speed)
84 {
85 	u32 val;
86 
87 	dw_pcie_dbi_write_enable(&pci->dw, true);
88 
89 	val = readl(pci->dw.dbi_base + PCIE_LINK_CAPABILITY);
90 	val &= ~TARGET_LINK_SPEED_MASK;
91 	val |= cap_speed;
92 	writel(val, pci->dw.dbi_base + PCIE_LINK_CAPABILITY);
93 
94 	val = readl(pci->dw.dbi_base + PCIE_LINK_CTL_2);
95 	val &= ~TARGET_LINK_SPEED_MASK;
96 	val |= cap_speed;
97 	writel(val, pci->dw.dbi_base + PCIE_LINK_CTL_2);
98 
99 	dw_pcie_dbi_write_enable(&pci->dw, false);
100 }
101 
102 /**
103  * is_link_up() - Return the link state
104  *
105  * @regs_base: A pointer to the PCIe DBICS registers
106  *
107  * Return: 1 (true) for active line and 0 (false) for no link
108  */
is_link_up(struct pcie_dw_ti * pci)109 static int is_link_up(struct pcie_dw_ti *pci)
110 {
111 	u32 val;
112 
113 	val = readl(pci->dw.dbi_base + PCIE_PORT_DEBUG0);
114 	val &= PORT_LOGIC_LTSSM_STATE_MASK;
115 
116 	return (val == PORT_LOGIC_LTSSM_STATE_L0);
117 }
118 
119 /**
120  * wait_link_up() - Wait for the link to come up
121  *
122  * @regs_base: A pointer to the PCIe controller registers
123  *
124  * Return: 1 (true) for active line and 0 (false) for no link (timeout)
125  */
wait_link_up(struct pcie_dw_ti * pci)126 static int wait_link_up(struct pcie_dw_ti *pci)
127 {
128 	unsigned long timeout;
129 
130 	timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS;
131 	while (!is_link_up(pci)) {
132 		if (get_timer(0) > timeout)
133 			return 0;
134 	};
135 
136 	return 1;
137 }
138 
pcie_dw_ti_pcie_link_up(struct pcie_dw_ti * pci,u32 cap_speed)139 static int pcie_dw_ti_pcie_link_up(struct pcie_dw_ti *pci, u32 cap_speed)
140 {
141 	u32 val;
142 
143 	if (is_link_up(pci)) {
144 		printf("PCI Link already up before configuration!\n");
145 		return 1;
146 	}
147 
148 	/* DW pre link configurations */
149 	pcie_dw_configure(pci, cap_speed);
150 
151 	/* Initiate link training */
152 	val = readl(pci->app_base + PCIE_CMD_STATUS);
153 	val |= LTSSM_EN_VAL;
154 	writel(val, pci->app_base + PCIE_CMD_STATUS);
155 
156 	/* Check that link was established */
157 	if (!wait_link_up(pci))
158 		return 0;
159 
160 	/*
161 	 * Link can be established in Gen 1. still need to wait
162 	 * till MAC nagaotiation is completed
163 	 */
164 	udelay(100);
165 
166 	return 1;
167 }
168 
pcie_am654_set_mode(struct pcie_dw_ti * pci,enum dw_pcie_device_mode mode)169 static int pcie_am654_set_mode(struct pcie_dw_ti *pci,
170 			       enum dw_pcie_device_mode mode)
171 {
172 	struct regmap *syscon;
173 	u32 val;
174 	u32 mask;
175 	int ret;
176 
177 	syscon = syscon_regmap_lookup_by_phandle(pci->dw.dev,
178 						 "ti,syscon-pcie-mode");
179 	if (IS_ERR(syscon))
180 		return 0;
181 
182 	mask = AM654_PCIE_DEV_TYPE_MASK;
183 
184 	switch (mode) {
185 	case DW_PCIE_RC_TYPE:
186 		val = RC;
187 		break;
188 	case DW_PCIE_EP_TYPE:
189 		val = EP;
190 		break;
191 	default:
192 		dev_err(pci->dw.dev, "INVALID device type %d\n", mode);
193 		return -EINVAL;
194 	}
195 
196 	ret = regmap_update_bits(syscon, 0, mask, val);
197 	if (ret) {
198 		dev_err(pci->dw.dev, "failed to set pcie mode\n");
199 		return ret;
200 	}
201 
202 	return 0;
203 }
204 
pcie_dw_init_id(struct pcie_dw_ti * pci)205 static int pcie_dw_init_id(struct pcie_dw_ti *pci)
206 {
207 	struct regmap *devctrl_regs;
208 	unsigned int id;
209 	int ret;
210 
211 	devctrl_regs = syscon_regmap_lookup_by_phandle(pci->dw.dev,
212 						       "ti,syscon-pcie-id");
213 	if (IS_ERR(devctrl_regs))
214 		return PTR_ERR(devctrl_regs);
215 
216 	ret = regmap_read(devctrl_regs, 0, &id);
217 	if (ret)
218 		return ret;
219 
220 	dw_pcie_dbi_write_enable(&pci->dw, true);
221 	writew(id & PCIE_VENDORID_MASK, pci->dw.dbi_base + PCI_VENDOR_ID);
222 	writew(id >> PCIE_DEVICEID_SHIFT, pci->dw.dbi_base + PCI_DEVICE_ID);
223 	dw_pcie_dbi_write_enable(&pci->dw, false);
224 
225 	return 0;
226 }
227 
228 /**
229  * pcie_dw_ti_probe() - Probe the PCIe bus for active link
230  *
231  * @dev: A pointer to the device being operated on
232  *
233  * Probe for an active link on the PCIe bus and configure the controller
234  * to enable this port.
235  *
236  * Return: 0 on success, else -ENODEV
237  */
pcie_dw_ti_probe(struct udevice * dev)238 static int pcie_dw_ti_probe(struct udevice *dev)
239 {
240 	struct pcie_dw_ti *pci = dev_get_priv(dev);
241 	struct udevice *ctlr = pci_get_controller(dev);
242 	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
243 	struct power_domain pci_pwrdmn;
244 	struct phy phy0, phy1;
245 	int ret;
246 
247 	ret = power_domain_get_by_index(dev, &pci_pwrdmn, 0);
248 	if (ret) {
249 		dev_err(dev, "failed to get power domain\n");
250 		return ret;
251 	}
252 
253 	ret = power_domain_on(&pci_pwrdmn);
254 	if (ret) {
255 		dev_err(dev, "Power domain on failed\n");
256 		return ret;
257 	}
258 
259 	ret = generic_phy_get_by_name(dev,  "pcie-phy0", &phy0);
260 	if (ret) {
261 		dev_err(dev, "Unable to get phy0");
262 		return ret;
263 	}
264 	generic_phy_reset(&phy0);
265 	generic_phy_init(&phy0);
266 	generic_phy_power_on(&phy0);
267 
268 	ret = generic_phy_get_by_name(dev,  "pcie-phy1", &phy1);
269 	if (ret) {
270 		dev_err(dev, "Unable to get phy1");
271 		return ret;
272 	}
273 	generic_phy_reset(&phy1);
274 	generic_phy_init(&phy1);
275 	generic_phy_power_on(&phy1);
276 
277 	pci->dw.first_busno = dev_seq(dev);
278 	pci->dw.dev = dev;
279 
280 	pcie_dw_setup_host(&pci->dw);
281 	pcie_dw_init_id(pci);
282 
283 	if (device_is_compatible(dev, "ti,am654-pcie-rc"))
284 		pcie_am654_set_mode(pci, DW_PCIE_RC_TYPE);
285 
286 	if (!pcie_dw_ti_pcie_link_up(pci, LINK_SPEED_GEN_2)) {
287 		printf("PCIE-%d: Link down\n", dev_seq(dev));
288 		return -ENODEV;
289 	}
290 
291 	printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev_seq(dev),
292 	       pcie_dw_get_link_speed(&pci->dw),
293 	       pcie_dw_get_link_width(&pci->dw),
294 	       hose->first_busno);
295 
296 	pcie_dw_prog_outbound_atu_unroll(&pci->dw, PCIE_ATU_REGION_INDEX0,
297 					 PCIE_ATU_TYPE_MEM,
298 					 pci->dw.mem.phys_start,
299 					 pci->dw.mem.bus_start, pci->dw.mem.size);
300 
301 	return 0;
302 }
303 
304 /**
305  * pcie_dw_ti_of_to_plat() - Translate from DT to device state
306  *
307  * @dev: A pointer to the device being operated on
308  *
309  * Translate relevant data from the device tree pertaining to device @dev into
310  * state that the driver will later make use of. This state is stored in the
311  * device's private data structure.
312  *
313  * Return: 0 on success, else -EINVAL
314  */
pcie_dw_ti_of_to_plat(struct udevice * dev)315 static int pcie_dw_ti_of_to_plat(struct udevice *dev)
316 {
317 	struct pcie_dw_ti *pcie = dev_get_priv(dev);
318 
319 	/* Get the controller base address */
320 	pcie->dw.dbi_base = (void *)dev_read_addr_name(dev, "dbics");
321 	if ((fdt_addr_t)pcie->dw.dbi_base == FDT_ADDR_T_NONE)
322 		return -EINVAL;
323 
324 	/* Get the config space base address and size */
325 	pcie->dw.cfg_base = (void *)dev_read_addr_size_name(dev, "config",
326 							 &pcie->dw.cfg_size);
327 	if ((fdt_addr_t)pcie->dw.cfg_base == FDT_ADDR_T_NONE)
328 		return -EINVAL;
329 
330 	/* Get the iATU base address and size */
331 	pcie->dw.atu_base = (void *)dev_read_addr_name(dev, "atu");
332 	if ((fdt_addr_t)pcie->dw.atu_base == FDT_ADDR_T_NONE)
333 		return -EINVAL;
334 
335 	/* Get the app base address and size */
336 	pcie->app_base = (void *)dev_read_addr_name(dev, "app");
337 	if ((fdt_addr_t)pcie->app_base == FDT_ADDR_T_NONE)
338 		return -EINVAL;
339 
340 	return 0;
341 }
342 
343 static const struct dm_pci_ops pcie_dw_ti_ops = {
344 	.read_config	= pcie_dw_read_config,
345 	.write_config	= pcie_dw_write_config,
346 };
347 
348 static const struct udevice_id pcie_dw_ti_ids[] = {
349 	{ .compatible = "ti,am654-pcie-rc" },
350 	{ }
351 };
352 
353 U_BOOT_DRIVER(pcie_dw_ti) = {
354 	.name			= "pcie_dw_ti",
355 	.id			= UCLASS_PCI,
356 	.of_match		= pcie_dw_ti_ids,
357 	.ops			= &pcie_dw_ti_ops,
358 	.of_to_plat	= pcie_dw_ti_of_to_plat,
359 	.probe			= pcie_dw_ti_probe,
360 	.priv_auto	= sizeof(struct pcie_dw_ti),
361 };
362