16e0832faSShawn Lin // SPDX-License-Identifier: GPL-2.0
26e0832faSShawn Lin /*
36e0832faSShawn Lin * Synopsys DesignWare PCIe host controller driver
46e0832faSShawn Lin *
56e0832faSShawn Lin * Copyright (C) 2013 Samsung Electronics Co., Ltd.
67ecd4a81SAlexander A. Klimov * https://www.samsung.com
76e0832faSShawn Lin *
86e0832faSShawn Lin * Author: Jingoo Han <jg1.han@samsung.com>
96e0832faSShawn Lin */
106e0832faSShawn Lin
11edf408b9SSerge Semin #include <linux/align.h>
1289473aa9SSerge Semin #include <linux/bitops.h>
13ef69f852SSerge Semin #include <linux/clk.h>
146e0832faSShawn Lin #include <linux/delay.h>
15939fbcd5SSerge Semin #include <linux/dma/edma.h>
16ef69f852SSerge Semin #include <linux/gpio/consumer.h>
17ef8c5887SSerge Semin #include <linux/ioport.h>
186e0832faSShawn Lin #include <linux/of.h>
19c925cfafSRob Herring #include <linux/platform_device.h>
2089473aa9SSerge Semin #include <linux/sizes.h>
216e0832faSShawn Lin #include <linux/types.h>
226e0832faSShawn Lin
23ed22aaaeSDilip Kota #include "../../pci.h"
246e0832faSShawn Lin #include "pcie-designware.h"
256e0832faSShawn Lin
26ef69f852SSerge Semin static const char * const dw_pcie_app_clks[DW_PCIE_NUM_APP_CLKS] = {
27ef69f852SSerge Semin [DW_PCIE_DBI_CLK] = "dbi",
28ef69f852SSerge Semin [DW_PCIE_MSTR_CLK] = "mstr",
29ef69f852SSerge Semin [DW_PCIE_SLV_CLK] = "slv",
30ef69f852SSerge Semin };
31ef69f852SSerge Semin
32ef69f852SSerge Semin static const char * const dw_pcie_core_clks[DW_PCIE_NUM_CORE_CLKS] = {
33ef69f852SSerge Semin [DW_PCIE_PIPE_CLK] = "pipe",
34ef69f852SSerge Semin [DW_PCIE_CORE_CLK] = "core",
35ef69f852SSerge Semin [DW_PCIE_AUX_CLK] = "aux",
36ef69f852SSerge Semin [DW_PCIE_REF_CLK] = "ref",
37ef69f852SSerge Semin };
38ef69f852SSerge Semin
39ef69f852SSerge Semin static const char * const dw_pcie_app_rsts[DW_PCIE_NUM_APP_RSTS] = {
40ef69f852SSerge Semin [DW_PCIE_DBI_RST] = "dbi",
41ef69f852SSerge Semin [DW_PCIE_MSTR_RST] = "mstr",
42ef69f852SSerge Semin [DW_PCIE_SLV_RST] = "slv",
43ef69f852SSerge Semin };
44ef69f852SSerge Semin
45ef69f852SSerge Semin static const char * const dw_pcie_core_rsts[DW_PCIE_NUM_CORE_RSTS] = {
46ef69f852SSerge Semin [DW_PCIE_NON_STICKY_RST] = "non-sticky",
47ef69f852SSerge Semin [DW_PCIE_STICKY_RST] = "sticky",
48ef69f852SSerge Semin [DW_PCIE_CORE_RST] = "core",
49ef69f852SSerge Semin [DW_PCIE_PIPE_RST] = "pipe",
50ef69f852SSerge Semin [DW_PCIE_PHY_RST] = "phy",
51ef69f852SSerge Semin [DW_PCIE_HOT_RST] = "hot",
52ef69f852SSerge Semin [DW_PCIE_PWR_RST] = "pwr",
53ef69f852SSerge Semin };
54ef69f852SSerge Semin
dw_pcie_get_clocks(struct dw_pcie * pci)55ef69f852SSerge Semin static int dw_pcie_get_clocks(struct dw_pcie *pci)
56ef69f852SSerge Semin {
57ef69f852SSerge Semin int i, ret;
58ef69f852SSerge Semin
59ef69f852SSerge Semin for (i = 0; i < DW_PCIE_NUM_APP_CLKS; i++)
60ef69f852SSerge Semin pci->app_clks[i].id = dw_pcie_app_clks[i];
61ef69f852SSerge Semin
62ef69f852SSerge Semin for (i = 0; i < DW_PCIE_NUM_CORE_CLKS; i++)
63ef69f852SSerge Semin pci->core_clks[i].id = dw_pcie_core_clks[i];
64ef69f852SSerge Semin
65ef69f852SSerge Semin ret = devm_clk_bulk_get_optional(pci->dev, DW_PCIE_NUM_APP_CLKS,
66ef69f852SSerge Semin pci->app_clks);
67ef69f852SSerge Semin if (ret)
68ef69f852SSerge Semin return ret;
69ef69f852SSerge Semin
70ef69f852SSerge Semin return devm_clk_bulk_get_optional(pci->dev, DW_PCIE_NUM_CORE_CLKS,
71ef69f852SSerge Semin pci->core_clks);
72ef69f852SSerge Semin }
73ef69f852SSerge Semin
dw_pcie_get_resets(struct dw_pcie * pci)74ef69f852SSerge Semin static int dw_pcie_get_resets(struct dw_pcie *pci)
75ef69f852SSerge Semin {
76ef69f852SSerge Semin int i, ret;
77ef69f852SSerge Semin
78ef69f852SSerge Semin for (i = 0; i < DW_PCIE_NUM_APP_RSTS; i++)
79ef69f852SSerge Semin pci->app_rsts[i].id = dw_pcie_app_rsts[i];
80ef69f852SSerge Semin
81ef69f852SSerge Semin for (i = 0; i < DW_PCIE_NUM_CORE_RSTS; i++)
82ef69f852SSerge Semin pci->core_rsts[i].id = dw_pcie_core_rsts[i];
83ef69f852SSerge Semin
84ef69f852SSerge Semin ret = devm_reset_control_bulk_get_optional_shared(pci->dev,
85ef69f852SSerge Semin DW_PCIE_NUM_APP_RSTS,
86ef69f852SSerge Semin pci->app_rsts);
87ef69f852SSerge Semin if (ret)
88ef69f852SSerge Semin return ret;
89ef69f852SSerge Semin
90ef69f852SSerge Semin ret = devm_reset_control_bulk_get_optional_exclusive(pci->dev,
91ef69f852SSerge Semin DW_PCIE_NUM_CORE_RSTS,
92ef69f852SSerge Semin pci->core_rsts);
93ef69f852SSerge Semin if (ret)
94ef69f852SSerge Semin return ret;
95ef69f852SSerge Semin
96ef69f852SSerge Semin pci->pe_rst = devm_gpiod_get_optional(pci->dev, "reset", GPIOD_OUT_HIGH);
97ef69f852SSerge Semin if (IS_ERR(pci->pe_rst))
98ef69f852SSerge Semin return PTR_ERR(pci->pe_rst);
99ef69f852SSerge Semin
100ef69f852SSerge Semin return 0;
101ef69f852SSerge Semin }
102ef69f852SSerge Semin
dw_pcie_get_resources(struct dw_pcie * pci)103ef8c5887SSerge Semin int dw_pcie_get_resources(struct dw_pcie *pci)
104ef8c5887SSerge Semin {
105ef8c5887SSerge Semin struct platform_device *pdev = to_platform_device(pci->dev);
106ef8c5887SSerge Semin struct device_node *np = dev_of_node(pci->dev);
107ef8c5887SSerge Semin struct resource *res;
108ef69f852SSerge Semin int ret;
109ef8c5887SSerge Semin
110ef8c5887SSerge Semin if (!pci->dbi_base) {
111ef8c5887SSerge Semin res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
112ef8c5887SSerge Semin pci->dbi_base = devm_pci_remap_cfg_resource(pci->dev, res);
113ef8c5887SSerge Semin if (IS_ERR(pci->dbi_base))
114ef8c5887SSerge Semin return PTR_ERR(pci->dbi_base);
115ef8c5887SSerge Semin }
116ef8c5887SSerge Semin
117ef8c5887SSerge Semin /* DBI2 is mainly useful for the endpoint controller */
118ef8c5887SSerge Semin if (!pci->dbi_base2) {
119ef8c5887SSerge Semin res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2");
120ef8c5887SSerge Semin if (res) {
121ef8c5887SSerge Semin pci->dbi_base2 = devm_pci_remap_cfg_resource(pci->dev, res);
122ef8c5887SSerge Semin if (IS_ERR(pci->dbi_base2))
123ef8c5887SSerge Semin return PTR_ERR(pci->dbi_base2);
124ef8c5887SSerge Semin } else {
125ef8c5887SSerge Semin pci->dbi_base2 = pci->dbi_base + SZ_4K;
126ef8c5887SSerge Semin }
127ef8c5887SSerge Semin }
128ef8c5887SSerge Semin
129ef8c5887SSerge Semin /* For non-unrolled iATU/eDMA platforms this range will be ignored */
130ef8c5887SSerge Semin if (!pci->atu_base) {
131ef8c5887SSerge Semin res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu");
132ef8c5887SSerge Semin if (res) {
133ef8c5887SSerge Semin pci->atu_size = resource_size(res);
134ef8c5887SSerge Semin pci->atu_base = devm_ioremap_resource(pci->dev, res);
135ef8c5887SSerge Semin if (IS_ERR(pci->atu_base))
136ef8c5887SSerge Semin return PTR_ERR(pci->atu_base);
137ef8c5887SSerge Semin } else {
138ef8c5887SSerge Semin pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
139ef8c5887SSerge Semin }
140ef8c5887SSerge Semin }
141ef8c5887SSerge Semin
142ef8c5887SSerge Semin /* Set a default value suitable for at most 8 in and 8 out windows */
143ef8c5887SSerge Semin if (!pci->atu_size)
144ef8c5887SSerge Semin pci->atu_size = SZ_4K;
145ef8c5887SSerge Semin
146939fbcd5SSerge Semin /* eDMA region can be mapped to a custom base address */
147939fbcd5SSerge Semin if (!pci->edma.reg_base) {
148939fbcd5SSerge Semin res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
149939fbcd5SSerge Semin if (res) {
150939fbcd5SSerge Semin pci->edma.reg_base = devm_ioremap_resource(pci->dev, res);
151939fbcd5SSerge Semin if (IS_ERR(pci->edma.reg_base))
152939fbcd5SSerge Semin return PTR_ERR(pci->edma.reg_base);
153939fbcd5SSerge Semin } else if (pci->atu_size >= 2 * DEFAULT_DBI_DMA_OFFSET) {
154939fbcd5SSerge Semin pci->edma.reg_base = pci->atu_base + DEFAULT_DBI_DMA_OFFSET;
155939fbcd5SSerge Semin }
156939fbcd5SSerge Semin }
157939fbcd5SSerge Semin
158ef69f852SSerge Semin /* LLDD is supposed to manually switch the clocks and resets state */
159ef69f852SSerge Semin if (dw_pcie_cap_is(pci, REQ_RES)) {
160ef69f852SSerge Semin ret = dw_pcie_get_clocks(pci);
161ef69f852SSerge Semin if (ret)
162ef69f852SSerge Semin return ret;
163ef69f852SSerge Semin
164ef69f852SSerge Semin ret = dw_pcie_get_resets(pci);
165ef69f852SSerge Semin if (ret)
166ef69f852SSerge Semin return ret;
167ef69f852SSerge Semin }
168ef69f852SSerge Semin
169ef8c5887SSerge Semin if (pci->link_gen < 1)
170ef8c5887SSerge Semin pci->link_gen = of_pci_get_max_link_speed(np);
171ef8c5887SSerge Semin
172ef8c5887SSerge Semin of_property_read_u32(np, "num-lanes", &pci->num_lanes);
173ef8c5887SSerge Semin
174ef8c5887SSerge Semin if (of_property_read_bool(np, "snps,enable-cdm-check"))
175ef8c5887SSerge Semin dw_pcie_cap_set(pci, CDM_CHECK);
176ef8c5887SSerge Semin
177ef8c5887SSerge Semin return 0;
178ef8c5887SSerge Semin }
179ef8c5887SSerge Semin
dw_pcie_version_detect(struct dw_pcie * pci)18013e9d390SSerge Semin void dw_pcie_version_detect(struct dw_pcie *pci)
18113e9d390SSerge Semin {
18213e9d390SSerge Semin u32 ver;
18313e9d390SSerge Semin
18413e9d390SSerge Semin /* The content of the CSR is zero on DWC PCIe older than v4.70a */
18513e9d390SSerge Semin ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_NUMBER);
18613e9d390SSerge Semin if (!ver)
18713e9d390SSerge Semin return;
18813e9d390SSerge Semin
18913e9d390SSerge Semin if (pci->version && pci->version != ver)
19013e9d390SSerge Semin dev_warn(pci->dev, "Versions don't match (%08x != %08x)\n",
19113e9d390SSerge Semin pci->version, ver);
19213e9d390SSerge Semin else
19313e9d390SSerge Semin pci->version = ver;
19413e9d390SSerge Semin
19513e9d390SSerge Semin ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_TYPE);
19613e9d390SSerge Semin
19713e9d390SSerge Semin if (pci->type && pci->type != ver)
19813e9d390SSerge Semin dev_warn(pci->dev, "Types don't match (%08x != %08x)\n",
19913e9d390SSerge Semin pci->type, ver);
20013e9d390SSerge Semin else
20113e9d390SSerge Semin pci->type = ver;
20213e9d390SSerge Semin }
20313e9d390SSerge Semin
2047a6854f6SVidya Sagar /*
2057a6854f6SVidya Sagar * These interfaces resemble the pci_find_*capability() interfaces, but these
2067a6854f6SVidya Sagar * are for configuring host controllers, which are bridges *to* PCI devices but
2077a6854f6SVidya Sagar * are not PCI devices themselves.
2087a6854f6SVidya Sagar */
__dw_pcie_find_next_cap(struct dw_pcie * pci,u8 cap_ptr,u8 cap)2097a6854f6SVidya Sagar static u8 __dw_pcie_find_next_cap(struct dw_pcie *pci, u8 cap_ptr,
2107a6854f6SVidya Sagar u8 cap)
2117a6854f6SVidya Sagar {
2127a6854f6SVidya Sagar u8 cap_id, next_cap_ptr;
2137a6854f6SVidya Sagar u16 reg;
2147a6854f6SVidya Sagar
2157a6854f6SVidya Sagar if (!cap_ptr)
2167a6854f6SVidya Sagar return 0;
2177a6854f6SVidya Sagar
2187a6854f6SVidya Sagar reg = dw_pcie_readw_dbi(pci, cap_ptr);
2197a6854f6SVidya Sagar cap_id = (reg & 0x00ff);
2207a6854f6SVidya Sagar
2217a6854f6SVidya Sagar if (cap_id > PCI_CAP_ID_MAX)
2227a6854f6SVidya Sagar return 0;
2237a6854f6SVidya Sagar
2247a6854f6SVidya Sagar if (cap_id == cap)
2257a6854f6SVidya Sagar return cap_ptr;
2267a6854f6SVidya Sagar
2277a6854f6SVidya Sagar next_cap_ptr = (reg & 0xff00) >> 8;
2287a6854f6SVidya Sagar return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
2297a6854f6SVidya Sagar }
2307a6854f6SVidya Sagar
dw_pcie_find_capability(struct dw_pcie * pci,u8 cap)2317a6854f6SVidya Sagar u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap)
2327a6854f6SVidya Sagar {
2337a6854f6SVidya Sagar u8 next_cap_ptr;
2347a6854f6SVidya Sagar u16 reg;
2357a6854f6SVidya Sagar
2367a6854f6SVidya Sagar reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST);
2377a6854f6SVidya Sagar next_cap_ptr = (reg & 0x00ff);
2387a6854f6SVidya Sagar
2397a6854f6SVidya Sagar return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
2407a6854f6SVidya Sagar }
2417a6854f6SVidya Sagar EXPORT_SYMBOL_GPL(dw_pcie_find_capability);
2427a6854f6SVidya Sagar
dw_pcie_find_next_ext_capability(struct dw_pcie * pci,u16 start,u8 cap)2435b0841faSVidya Sagar static u16 dw_pcie_find_next_ext_capability(struct dw_pcie *pci, u16 start,
2445b0841faSVidya Sagar u8 cap)
2455b0841faSVidya Sagar {
2465b0841faSVidya Sagar u32 header;
2475b0841faSVidya Sagar int ttl;
2485b0841faSVidya Sagar int pos = PCI_CFG_SPACE_SIZE;
2495b0841faSVidya Sagar
2505b0841faSVidya Sagar /* minimum 8 bytes per capability */
2515b0841faSVidya Sagar ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
2525b0841faSVidya Sagar
2535b0841faSVidya Sagar if (start)
2545b0841faSVidya Sagar pos = start;
2555b0841faSVidya Sagar
2565b0841faSVidya Sagar header = dw_pcie_readl_dbi(pci, pos);
2575b0841faSVidya Sagar /*
2585b0841faSVidya Sagar * If we have no capabilities, this is indicated by cap ID,
2595b0841faSVidya Sagar * cap version and next pointer all being 0.
2605b0841faSVidya Sagar */
2615b0841faSVidya Sagar if (header == 0)
2625b0841faSVidya Sagar return 0;
2635b0841faSVidya Sagar
2645b0841faSVidya Sagar while (ttl-- > 0) {
2655b0841faSVidya Sagar if (PCI_EXT_CAP_ID(header) == cap && pos != start)
2665b0841faSVidya Sagar return pos;
2675b0841faSVidya Sagar
2685b0841faSVidya Sagar pos = PCI_EXT_CAP_NEXT(header);
2695b0841faSVidya Sagar if (pos < PCI_CFG_SPACE_SIZE)
2705b0841faSVidya Sagar break;
2715b0841faSVidya Sagar
2725b0841faSVidya Sagar header = dw_pcie_readl_dbi(pci, pos);
2735b0841faSVidya Sagar }
2745b0841faSVidya Sagar
2755b0841faSVidya Sagar return 0;
2765b0841faSVidya Sagar }
2775b0841faSVidya Sagar
dw_pcie_find_ext_capability(struct dw_pcie * pci,u8 cap)2785b0841faSVidya Sagar u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap)
2795b0841faSVidya Sagar {
2805b0841faSVidya Sagar return dw_pcie_find_next_ext_capability(pci, 0, cap);
2815b0841faSVidya Sagar }
2825b0841faSVidya Sagar EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability);
2835b0841faSVidya Sagar
dw_pcie_read(void __iomem * addr,int size,u32 * val)2846e0832faSShawn Lin int dw_pcie_read(void __iomem *addr, int size, u32 *val)
2856e0832faSShawn Lin {
2864f8bbd2fSAndrey Smirnov if (!IS_ALIGNED((uintptr_t)addr, size)) {
2876e0832faSShawn Lin *val = 0;
2886e0832faSShawn Lin return PCIBIOS_BAD_REGISTER_NUMBER;
2896e0832faSShawn Lin }
2906e0832faSShawn Lin
2916e0832faSShawn Lin if (size == 4) {
2926e0832faSShawn Lin *val = readl(addr);
2936e0832faSShawn Lin } else if (size == 2) {
2946e0832faSShawn Lin *val = readw(addr);
2956e0832faSShawn Lin } else if (size == 1) {
2966e0832faSShawn Lin *val = readb(addr);
2976e0832faSShawn Lin } else {
2986e0832faSShawn Lin *val = 0;
2996e0832faSShawn Lin return PCIBIOS_BAD_REGISTER_NUMBER;
3006e0832faSShawn Lin }
3016e0832faSShawn Lin
3026e0832faSShawn Lin return PCIBIOS_SUCCESSFUL;
3036e0832faSShawn Lin }
304ca98329dSVidya Sagar EXPORT_SYMBOL_GPL(dw_pcie_read);
3056e0832faSShawn Lin
dw_pcie_write(void __iomem * addr,int size,u32 val)3066e0832faSShawn Lin int dw_pcie_write(void __iomem *addr, int size, u32 val)
3076e0832faSShawn Lin {
3084f8bbd2fSAndrey Smirnov if (!IS_ALIGNED((uintptr_t)addr, size))
3096e0832faSShawn Lin return PCIBIOS_BAD_REGISTER_NUMBER;
3106e0832faSShawn Lin
3116e0832faSShawn Lin if (size == 4)
3126e0832faSShawn Lin writel(val, addr);
3136e0832faSShawn Lin else if (size == 2)
3146e0832faSShawn Lin writew(val, addr);
3156e0832faSShawn Lin else if (size == 1)
3166e0832faSShawn Lin writeb(val, addr);
3176e0832faSShawn Lin else
3186e0832faSShawn Lin return PCIBIOS_BAD_REGISTER_NUMBER;
3196e0832faSShawn Lin
3206e0832faSShawn Lin return PCIBIOS_SUCCESSFUL;
3216e0832faSShawn Lin }
322ca98329dSVidya Sagar EXPORT_SYMBOL_GPL(dw_pcie_write);
3236e0832faSShawn Lin
dw_pcie_read_dbi(struct dw_pcie * pci,u32 reg,size_t size)3247bc082d7SVidya Sagar u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size)
3256e0832faSShawn Lin {
3266e0832faSShawn Lin int ret;
3276e0832faSShawn Lin u32 val;
3286e0832faSShawn Lin
329a2f882d8SJisheng Zhang if (pci->ops && pci->ops->read_dbi)
3307bc082d7SVidya Sagar return pci->ops->read_dbi(pci, pci->dbi_base, reg, size);
3316e0832faSShawn Lin
3327bc082d7SVidya Sagar ret = dw_pcie_read(pci->dbi_base + reg, size, &val);
3336e0832faSShawn Lin if (ret)
3346e0832faSShawn Lin dev_err(pci->dev, "Read DBI address failed\n");
3356e0832faSShawn Lin
3366e0832faSShawn Lin return val;
3376e0832faSShawn Lin }
338ca98329dSVidya Sagar EXPORT_SYMBOL_GPL(dw_pcie_read_dbi);
3396e0832faSShawn Lin
dw_pcie_write_dbi(struct dw_pcie * pci,u32 reg,size_t size,u32 val)3407bc082d7SVidya Sagar void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
3416e0832faSShawn Lin {
3426e0832faSShawn Lin int ret;
3436e0832faSShawn Lin
344a2f882d8SJisheng Zhang if (pci->ops && pci->ops->write_dbi) {
3457bc082d7SVidya Sagar pci->ops->write_dbi(pci, pci->dbi_base, reg, size, val);
3466e0832faSShawn Lin return;
3476e0832faSShawn Lin }
3486e0832faSShawn Lin
3497bc082d7SVidya Sagar ret = dw_pcie_write(pci->dbi_base + reg, size, val);
3506e0832faSShawn Lin if (ret)
3516e0832faSShawn Lin dev_err(pci->dev, "Write DBI address failed\n");
3526e0832faSShawn Lin }
353ca98329dSVidya Sagar EXPORT_SYMBOL_GPL(dw_pcie_write_dbi);
3546e0832faSShawn Lin
dw_pcie_write_dbi2(struct dw_pcie * pci,u32 reg,size_t size,u32 val)3557bc082d7SVidya Sagar void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
356ddf567e3SKishon Vijay Abraham I {
357ddf567e3SKishon Vijay Abraham I int ret;
358ddf567e3SKishon Vijay Abraham I
359a2f882d8SJisheng Zhang if (pci->ops && pci->ops->write_dbi2) {
3607bc082d7SVidya Sagar pci->ops->write_dbi2(pci, pci->dbi_base2, reg, size, val);
361ddf567e3SKishon Vijay Abraham I return;
362ddf567e3SKishon Vijay Abraham I }
363ddf567e3SKishon Vijay Abraham I
3647bc082d7SVidya Sagar ret = dw_pcie_write(pci->dbi_base2 + reg, size, val);
365ddf567e3SKishon Vijay Abraham I if (ret)
366ddf567e3SKishon Vijay Abraham I dev_err(pci->dev, "write DBI address failed\n");
367ddf567e3SKishon Vijay Abraham I }
368ddf567e3SKishon Vijay Abraham I
dw_pcie_select_atu(struct dw_pcie * pci,u32 dir,u32 index)3695a163f59SSerge Semin static inline void __iomem *dw_pcie_select_atu(struct dw_pcie *pci, u32 dir,
3705a163f59SSerge Semin u32 index)
3717bc082d7SVidya Sagar {
3727f9e982dSSerge Semin if (dw_pcie_cap_is(pci, IATU_UNROLL))
3735a163f59SSerge Semin return pci->atu_base + PCIE_ATU_UNROLL_BASE(dir, index);
3745a163f59SSerge Semin
3755a163f59SSerge Semin dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, dir | index);
3765a163f59SSerge Semin return pci->atu_base;
3775a163f59SSerge Semin }
3785a163f59SSerge Semin
dw_pcie_readl_atu(struct dw_pcie * pci,u32 dir,u32 index,u32 reg)3795a163f59SSerge Semin static u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 dir, u32 index, u32 reg)
3805a163f59SSerge Semin {
3815a163f59SSerge Semin void __iomem *base;
3827bc082d7SVidya Sagar int ret;
3837bc082d7SVidya Sagar u32 val;
3847bc082d7SVidya Sagar
3855a163f59SSerge Semin base = dw_pcie_select_atu(pci, dir, index);
3867bc082d7SVidya Sagar
3875a163f59SSerge Semin if (pci->ops && pci->ops->read_dbi)
3885a163f59SSerge Semin return pci->ops->read_dbi(pci, base, reg, 4);
3895a163f59SSerge Semin
3905a163f59SSerge Semin ret = dw_pcie_read(base + reg, 4, &val);
3917bc082d7SVidya Sagar if (ret)
3927bc082d7SVidya Sagar dev_err(pci->dev, "Read ATU address failed\n");
3937bc082d7SVidya Sagar
3947bc082d7SVidya Sagar return val;
3957bc082d7SVidya Sagar }
3967bc082d7SVidya Sagar
dw_pcie_writel_atu(struct dw_pcie * pci,u32 dir,u32 index,u32 reg,u32 val)3975a163f59SSerge Semin static void dw_pcie_writel_atu(struct dw_pcie *pci, u32 dir, u32 index,
3985a163f59SSerge Semin u32 reg, u32 val)
3997bc082d7SVidya Sagar {
4005a163f59SSerge Semin void __iomem *base;
4017bc082d7SVidya Sagar int ret;
4027bc082d7SVidya Sagar
4035a163f59SSerge Semin base = dw_pcie_select_atu(pci, dir, index);
4045a163f59SSerge Semin
405a2f882d8SJisheng Zhang if (pci->ops && pci->ops->write_dbi) {
4065a163f59SSerge Semin pci->ops->write_dbi(pci, base, reg, 4, val);
4077bc082d7SVidya Sagar return;
4087bc082d7SVidya Sagar }
4097bc082d7SVidya Sagar
4105a163f59SSerge Semin ret = dw_pcie_write(base + reg, 4, val);
4117bc082d7SVidya Sagar if (ret)
4127bc082d7SVidya Sagar dev_err(pci->dev, "Write ATU address failed\n");
4137bc082d7SVidya Sagar }
4147bc082d7SVidya Sagar
dw_pcie_readl_atu_ob(struct dw_pcie * pci,u32 index,u32 reg)4155a163f59SSerge Semin static inline u32 dw_pcie_readl_atu_ob(struct dw_pcie *pci, u32 index, u32 reg)
4166e0832faSShawn Lin {
4175a163f59SSerge Semin return dw_pcie_readl_atu(pci, PCIE_ATU_REGION_DIR_OB, index, reg);
4186e0832faSShawn Lin }
4196e0832faSShawn Lin
dw_pcie_writel_atu_ob(struct dw_pcie * pci,u32 index,u32 reg,u32 val)4205a163f59SSerge Semin static inline void dw_pcie_writel_atu_ob(struct dw_pcie *pci, u32 index, u32 reg,
4216e0832faSShawn Lin u32 val)
4226e0832faSShawn Lin {
4235a163f59SSerge Semin dw_pcie_writel_atu(pci, PCIE_ATU_REGION_DIR_OB, index, reg, val);
4246e0832faSShawn Lin }
4256e0832faSShawn Lin
dw_pcie_enable_ecrc(u32 val)4266104033bSVidya Sagar static inline u32 dw_pcie_enable_ecrc(u32 val)
4276104033bSVidya Sagar {
4286104033bSVidya Sagar /*
4296104033bSVidya Sagar * DesignWare core version 4.90A has a design issue where the 'TD'
4306104033bSVidya Sagar * bit in the Control register-1 of the ATU outbound region acts
4316104033bSVidya Sagar * like an override for the ECRC setting, i.e., the presence of TLP
4326104033bSVidya Sagar * Digest (ECRC) in the outgoing TLPs is solely determined by this
4336104033bSVidya Sagar * bit. This is contrary to the PCIe spec which says that the
4346104033bSVidya Sagar * enablement of the ECRC is solely determined by the AER
4356104033bSVidya Sagar * registers.
4366104033bSVidya Sagar *
4376104033bSVidya Sagar * Because of this, even when the ECRC is enabled through AER
4386104033bSVidya Sagar * registers, the transactions going through ATU won't have TLP
4396104033bSVidya Sagar * Digest as there is no way the PCI core AER code could program
4406104033bSVidya Sagar * the TD bit which is specific to the DesignWare core.
4416104033bSVidya Sagar *
4426104033bSVidya Sagar * The best way to handle this scenario is to program the TD bit
4436104033bSVidya Sagar * always. It affects only the traffic from root port to downstream
4446104033bSVidya Sagar * devices.
4456104033bSVidya Sagar *
4466104033bSVidya Sagar * At this point,
4476104033bSVidya Sagar * When ECRC is enabled in AER registers, everything works normally
4486104033bSVidya Sagar * When ECRC is NOT enabled in AER registers, then,
4496104033bSVidya Sagar * on Root Port:- TLP Digest (DWord size) gets appended to each packet
4506104033bSVidya Sagar * even through it is not required. Since downstream
4516104033bSVidya Sagar * TLPs are mostly for configuration accesses and BAR
4526104033bSVidya Sagar * accesses, they are not in critical path and won't
4536104033bSVidya Sagar * have much negative effect on the performance.
4546104033bSVidya Sagar * on End Point:- TLP Digest is received for some/all the packets coming
4556104033bSVidya Sagar * from the root port. TLP Digest is ignored because,
4566104033bSVidya Sagar * as per the PCIe Spec r5.0 v1.0 section 2.2.3
4576104033bSVidya Sagar * "TLP Digest Rules", when an endpoint receives TLP
4586104033bSVidya Sagar * Digest when its ECRC check functionality is disabled
4596104033bSVidya Sagar * in AER registers, received TLP Digest is just ignored.
4606104033bSVidya Sagar * Since there is no issue or error reported either side, best way to
4616104033bSVidya Sagar * handle the scenario is to program TD bit by default.
4626104033bSVidya Sagar */
4636104033bSVidya Sagar
4646104033bSVidya Sagar return val | PCIE_ATU_TD;
4656104033bSVidya Sagar }
4666104033bSVidya Sagar
__dw_pcie_prog_outbound_atu(struct dw_pcie * pci,u8 func_no,int index,int type,u64 cpu_addr,u64 pci_addr,u64 size)467edf408b9SSerge Semin static int __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no,
46824ede430SXiaowei Bao int index, int type, u64 cpu_addr,
46974081de4SVidya Sagar u64 pci_addr, u64 size)
4706e0832faSShawn Lin {
4716e0832faSShawn Lin u32 retries, val;
472777e7c3aSSerge Semin u64 limit_addr;
4736e0832faSShawn Lin
474a2f882d8SJisheng Zhang if (pci->ops && pci->ops->cpu_addr_fixup)
4756e0832faSShawn Lin cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
4766e0832faSShawn Lin
477777e7c3aSSerge Semin limit_addr = cpu_addr + size - 1;
478777e7c3aSSerge Semin
479edf408b9SSerge Semin if ((limit_addr & ~pci->region_limit) != (cpu_addr & ~pci->region_limit) ||
480edf408b9SSerge Semin !IS_ALIGNED(cpu_addr, pci->region_align) ||
481edf408b9SSerge Semin !IS_ALIGNED(pci_addr, pci->region_align) || !size) {
482edf408b9SSerge Semin return -EINVAL;
483edf408b9SSerge Semin }
484edf408b9SSerge Semin
4855a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LOWER_BASE,
4866e0832faSShawn Lin lower_32_bits(cpu_addr));
4875a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_BASE,
4886e0832faSShawn Lin upper_32_bits(cpu_addr));
4895a163f59SSerge Semin
4905a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LIMIT,
491777e7c3aSSerge Semin lower_32_bits(limit_addr));
4920b0a780dSSerge Semin if (dw_pcie_ver_is_ge(pci, 460A))
4935a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_LIMIT,
494777e7c3aSSerge Semin upper_32_bits(limit_addr));
4955a163f59SSerge Semin
4965a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LOWER_TARGET,
4976e0832faSShawn Lin lower_32_bits(pci_addr));
4985a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_TARGET,
4996e0832faSShawn Lin upper_32_bits(pci_addr));
5005a163f59SSerge Semin
5016104033bSVidya Sagar val = type | PCIE_ATU_FUNC_NUM(func_no);
502777e7c3aSSerge Semin if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) &&
5030b0a780dSSerge Semin dw_pcie_ver_is_ge(pci, 460A))
504777e7c3aSSerge Semin val |= PCIE_ATU_INCREASE_REGION_SIZE;
5050b0a780dSSerge Semin if (dw_pcie_ver_is(pci, 490A))
5066104033bSVidya Sagar val = dw_pcie_enable_ecrc(val);
5075a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_REGION_CTRL1, val);
5085a163f59SSerge Semin
5095a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_REGION_CTRL2, PCIE_ATU_ENABLE);
5106e0832faSShawn Lin
5116e0832faSShawn Lin /*
5126e0832faSShawn Lin * Make sure ATU enable takes effect before any subsequent config
5136e0832faSShawn Lin * and I/O accesses.
5146e0832faSShawn Lin */
5156e0832faSShawn Lin for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
5165a163f59SSerge Semin val = dw_pcie_readl_atu_ob(pci, index, PCIE_ATU_REGION_CTRL2);
5176e0832faSShawn Lin if (val & PCIE_ATU_ENABLE)
518edf408b9SSerge Semin return 0;
5196e0832faSShawn Lin
5209024143eSJisheng Zhang mdelay(LINK_WAIT_IATU);
5216e0832faSShawn Lin }
5225a163f59SSerge Semin
5236e0832faSShawn Lin dev_err(pci->dev, "Outbound iATU is not being enabled\n");
524edf408b9SSerge Semin
525edf408b9SSerge Semin return -ETIMEDOUT;
5266e0832faSShawn Lin }
5276e0832faSShawn Lin
dw_pcie_prog_outbound_atu(struct dw_pcie * pci,int index,int type,u64 cpu_addr,u64 pci_addr,u64 size)528edf408b9SSerge Semin int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
52974081de4SVidya Sagar u64 cpu_addr, u64 pci_addr, u64 size)
53024ede430SXiaowei Bao {
531edf408b9SSerge Semin return __dw_pcie_prog_outbound_atu(pci, 0, index, type,
53224ede430SXiaowei Bao cpu_addr, pci_addr, size);
53324ede430SXiaowei Bao }
53424ede430SXiaowei Bao
dw_pcie_prog_ep_outbound_atu(struct dw_pcie * pci,u8 func_no,int index,int type,u64 cpu_addr,u64 pci_addr,u64 size)535edf408b9SSerge Semin int dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index,
53624ede430SXiaowei Bao int type, u64 cpu_addr, u64 pci_addr,
5373856e1c5SShradha Todi u64 size)
53824ede430SXiaowei Bao {
539edf408b9SSerge Semin return __dw_pcie_prog_outbound_atu(pci, func_no, index, type,
54024ede430SXiaowei Bao cpu_addr, pci_addr, size);
54124ede430SXiaowei Bao }
54224ede430SXiaowei Bao
dw_pcie_readl_atu_ib(struct dw_pcie * pci,u32 index,u32 reg)5435a163f59SSerge Semin static inline u32 dw_pcie_readl_atu_ib(struct dw_pcie *pci, u32 index, u32 reg)
5446e0832faSShawn Lin {
5455a163f59SSerge Semin return dw_pcie_readl_atu(pci, PCIE_ATU_REGION_DIR_IB, index, reg);
5466e0832faSShawn Lin }
5476e0832faSShawn Lin
dw_pcie_writel_atu_ib(struct dw_pcie * pci,u32 index,u32 reg,u32 val)5485a163f59SSerge Semin static inline void dw_pcie_writel_atu_ib(struct dw_pcie *pci, u32 index, u32 reg,
5496e0832faSShawn Lin u32 val)
5506e0832faSShawn Lin {
5515a163f59SSerge Semin dw_pcie_writel_atu(pci, PCIE_ATU_REGION_DIR_IB, index, reg, val);
5526e0832faSShawn Lin }
5536e0832faSShawn Lin
dw_pcie_prog_inbound_atu(struct dw_pcie * pci,int index,int type,u64 cpu_addr,u64 pci_addr,u64 size)5548522e17dSSerge Semin int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
5558522e17dSSerge Semin u64 cpu_addr, u64 pci_addr, u64 size)
5568522e17dSSerge Semin {
5578522e17dSSerge Semin u64 limit_addr = pci_addr + size - 1;
5588522e17dSSerge Semin u32 retries, val;
5598522e17dSSerge Semin
5608522e17dSSerge Semin if ((limit_addr & ~pci->region_limit) != (pci_addr & ~pci->region_limit) ||
5618522e17dSSerge Semin !IS_ALIGNED(cpu_addr, pci->region_align) ||
5628522e17dSSerge Semin !IS_ALIGNED(pci_addr, pci->region_align) || !size) {
5638522e17dSSerge Semin return -EINVAL;
5648522e17dSSerge Semin }
5658522e17dSSerge Semin
5668522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_BASE,
5678522e17dSSerge Semin lower_32_bits(pci_addr));
5688522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_BASE,
5698522e17dSSerge Semin upper_32_bits(pci_addr));
5708522e17dSSerge Semin
5718522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LIMIT,
5728522e17dSSerge Semin lower_32_bits(limit_addr));
5738522e17dSSerge Semin if (dw_pcie_ver_is_ge(pci, 460A))
5748522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_LIMIT,
5758522e17dSSerge Semin upper_32_bits(limit_addr));
5768522e17dSSerge Semin
5778522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
5788522e17dSSerge Semin lower_32_bits(cpu_addr));
5798522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
5808522e17dSSerge Semin upper_32_bits(cpu_addr));
5818522e17dSSerge Semin
5828522e17dSSerge Semin val = type;
5838522e17dSSerge Semin if (upper_32_bits(limit_addr) > upper_32_bits(pci_addr) &&
5848522e17dSSerge Semin dw_pcie_ver_is_ge(pci, 460A))
5858522e17dSSerge Semin val |= PCIE_ATU_INCREASE_REGION_SIZE;
5868522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL1, val);
5878522e17dSSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL2, PCIE_ATU_ENABLE);
5888522e17dSSerge Semin
5898522e17dSSerge Semin /*
5908522e17dSSerge Semin * Make sure ATU enable takes effect before any subsequent config
5918522e17dSSerge Semin * and I/O accesses.
5928522e17dSSerge Semin */
5938522e17dSSerge Semin for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
5948522e17dSSerge Semin val = dw_pcie_readl_atu_ib(pci, index, PCIE_ATU_REGION_CTRL2);
5958522e17dSSerge Semin if (val & PCIE_ATU_ENABLE)
5968522e17dSSerge Semin return 0;
5978522e17dSSerge Semin
5988522e17dSSerge Semin mdelay(LINK_WAIT_IATU);
5998522e17dSSerge Semin }
6008522e17dSSerge Semin
6018522e17dSSerge Semin dev_err(pci->dev, "Inbound iATU is not being enabled\n");
6028522e17dSSerge Semin
6038522e17dSSerge Semin return -ETIMEDOUT;
6048522e17dSSerge Semin }
6058522e17dSSerge Semin
dw_pcie_prog_ep_inbound_atu(struct dw_pcie * pci,u8 func_no,int index,int type,u64 cpu_addr,u8 bar)6068522e17dSSerge Semin int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
6074859db9bSSerge Semin int type, u64 cpu_addr, u8 bar)
6086e0832faSShawn Lin {
6096e0832faSShawn Lin u32 retries, val;
6106e0832faSShawn Lin
611edf408b9SSerge Semin if (!IS_ALIGNED(cpu_addr, pci->region_align))
612edf408b9SSerge Semin return -EINVAL;
613edf408b9SSerge Semin
6145a163f59SSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
6155a163f59SSerge Semin lower_32_bits(cpu_addr));
6165a163f59SSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
6175a163f59SSerge Semin upper_32_bits(cpu_addr));
6186e0832faSShawn Lin
6195a163f59SSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL1, type |
62024ede430SXiaowei Bao PCIE_ATU_FUNC_NUM(func_no));
6215a163f59SSerge Semin dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL2,
6225a163f59SSerge Semin PCIE_ATU_ENABLE | PCIE_ATU_FUNC_NUM_MATCH_EN |
62324ede430SXiaowei Bao PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
6246e0832faSShawn Lin
6256e0832faSShawn Lin /*
6266e0832faSShawn Lin * Make sure ATU enable takes effect before any subsequent config
6276e0832faSShawn Lin * and I/O accesses.
6286e0832faSShawn Lin */
6296e0832faSShawn Lin for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
6305a163f59SSerge Semin val = dw_pcie_readl_atu_ib(pci, index, PCIE_ATU_REGION_CTRL2);
6316e0832faSShawn Lin if (val & PCIE_ATU_ENABLE)
6326e0832faSShawn Lin return 0;
6336e0832faSShawn Lin
6349024143eSJisheng Zhang mdelay(LINK_WAIT_IATU);
6356e0832faSShawn Lin }
6365a163f59SSerge Semin
6376e0832faSShawn Lin dev_err(pci->dev, "Inbound iATU is not being enabled\n");
6386e0832faSShawn Lin
6395a163f59SSerge Semin return -ETIMEDOUT;
6406e0832faSShawn Lin }
6416e0832faSShawn Lin
dw_pcie_disable_atu(struct dw_pcie * pci,u32 dir,int index)64238fe2723SSerge Semin void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index)
6436e0832faSShawn Lin {
6445a163f59SSerge Semin dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0);
645d1cf738fSSerge Semin }
6466e0832faSShawn Lin
dw_pcie_wait_for_link(struct dw_pcie * pci)647da56a1bfSAjay Agarwal int dw_pcie_wait_for_link(struct dw_pcie *pci)
648da56a1bfSAjay Agarwal {
649c5097b98SJohan Hovold u32 offset, val;
6506e0832faSShawn Lin int retries;
6516e0832faSShawn Lin
6526e0832faSShawn Lin /* Check if the link is up or not */
6536e0832faSShawn Lin for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
65414c4ad12SSerge Semin if (dw_pcie_link_up(pci))
65514c4ad12SSerge Semin break;
65614c4ad12SSerge Semin
6576e0832faSShawn Lin usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
6586e0832faSShawn Lin }
6596e0832faSShawn Lin
66014c4ad12SSerge Semin if (retries >= LINK_WAIT_MAX_RETRIES) {
6618405d8f0SVidya Sagar dev_info(pci->dev, "Phy link never came up\n");
6626e0832faSShawn Lin return -ETIMEDOUT;
6636e0832faSShawn Lin }
66414c4ad12SSerge Semin
665c5097b98SJohan Hovold offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
666c5097b98SJohan Hovold val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
667c5097b98SJohan Hovold
668c5097b98SJohan Hovold dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
669c5097b98SJohan Hovold FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
670c5097b98SJohan Hovold FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
67114c4ad12SSerge Semin
67214c4ad12SSerge Semin return 0;
67314c4ad12SSerge Semin }
674feee519aSVidya Sagar EXPORT_SYMBOL_GPL(dw_pcie_wait_for_link);
6756e0832faSShawn Lin
dw_pcie_link_up(struct dw_pcie * pci)6766e0832faSShawn Lin int dw_pcie_link_up(struct dw_pcie *pci)
6776e0832faSShawn Lin {
6786e0832faSShawn Lin u32 val;
6796e0832faSShawn Lin
680a2f882d8SJisheng Zhang if (pci->ops && pci->ops->link_up)
6816e0832faSShawn Lin return pci->ops->link_up(pci);
6826e0832faSShawn Lin
6833869e9a3SSerge Semin val = dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1);
68460ef4b07SAndrey Smirnov return ((val & PCIE_PORT_DEBUG1_LINK_UP) &&
68560ef4b07SAndrey Smirnov (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
6866e0832faSShawn Lin }
6873a7fb867SLuca Ceresoli EXPORT_SYMBOL_GPL(dw_pcie_link_up);
6886e0832faSShawn Lin
dw_pcie_upconfig_setup(struct dw_pcie * pci)689ed22aaaeSDilip Kota void dw_pcie_upconfig_setup(struct dw_pcie *pci)
690ed22aaaeSDilip Kota {
691ed22aaaeSDilip Kota u32 val;
692ed22aaaeSDilip Kota
693ed22aaaeSDilip Kota val = dw_pcie_readl_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL);
694ed22aaaeSDilip Kota val |= PORT_MLTI_UPCFG_SUPPORT;
695ed22aaaeSDilip Kota dw_pcie_writel_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL, val);
696ed22aaaeSDilip Kota }
697ed22aaaeSDilip Kota EXPORT_SYMBOL_GPL(dw_pcie_upconfig_setup);
698ed22aaaeSDilip Kota
dw_pcie_link_set_max_speed(struct dw_pcie * pci,u32 link_gen)69939bc5006SRob Herring static void dw_pcie_link_set_max_speed(struct dw_pcie *pci, u32 link_gen)
700ed22aaaeSDilip Kota {
70139bc5006SRob Herring u32 cap, ctrl2, link_speed;
702ed22aaaeSDilip Kota u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
703ed22aaaeSDilip Kota
70439bc5006SRob Herring cap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
70539bc5006SRob Herring ctrl2 = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCTL2);
70639bc5006SRob Herring ctrl2 &= ~PCI_EXP_LNKCTL2_TLS;
707ed22aaaeSDilip Kota
708ed22aaaeSDilip Kota switch (pcie_link_speed[link_gen]) {
709ed22aaaeSDilip Kota case PCIE_SPEED_2_5GT:
71039bc5006SRob Herring link_speed = PCI_EXP_LNKCTL2_TLS_2_5GT;
711ed22aaaeSDilip Kota break;
712ed22aaaeSDilip Kota case PCIE_SPEED_5_0GT:
71339bc5006SRob Herring link_speed = PCI_EXP_LNKCTL2_TLS_5_0GT;
714ed22aaaeSDilip Kota break;
715ed22aaaeSDilip Kota case PCIE_SPEED_8_0GT:
71639bc5006SRob Herring link_speed = PCI_EXP_LNKCTL2_TLS_8_0GT;
717ed22aaaeSDilip Kota break;
718ed22aaaeSDilip Kota case PCIE_SPEED_16_0GT:
71939bc5006SRob Herring link_speed = PCI_EXP_LNKCTL2_TLS_16_0GT;
720ed22aaaeSDilip Kota break;
721ed22aaaeSDilip Kota default:
722ed22aaaeSDilip Kota /* Use hardware capability */
72339bc5006SRob Herring link_speed = FIELD_GET(PCI_EXP_LNKCAP_SLS, cap);
72439bc5006SRob Herring ctrl2 &= ~PCI_EXP_LNKCTL2_HASD;
725ed22aaaeSDilip Kota break;
726ed22aaaeSDilip Kota }
727ed22aaaeSDilip Kota
72839bc5006SRob Herring dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCTL2, ctrl2 | link_speed);
72939bc5006SRob Herring
73039bc5006SRob Herring cap &= ~((u32)PCI_EXP_LNKCAP_SLS);
73139bc5006SRob Herring dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, cap | link_speed);
73239bc5006SRob Herring
733ed22aaaeSDilip Kota }
734ed22aaaeSDilip Kota
dw_pcie_link_set_max_link_width(struct dw_pcie * pci,u32 num_lanes)735e8bde5ebSYoshihiro Shimoda static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes)
736e8bde5ebSYoshihiro Shimoda {
737*f3dda1cfSYoshihiro Shimoda u32 lnkcap, lwsc, plc;
738*f3dda1cfSYoshihiro Shimoda u8 cap;
739e8bde5ebSYoshihiro Shimoda
740e8bde5ebSYoshihiro Shimoda if (!num_lanes)
741e8bde5ebSYoshihiro Shimoda return;
742e8bde5ebSYoshihiro Shimoda
743e8bde5ebSYoshihiro Shimoda /* Set the number of lanes */
744e8bde5ebSYoshihiro Shimoda plc = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
745e8bde5ebSYoshihiro Shimoda plc &= ~PORT_LINK_FAST_LINK_MODE;
746e8bde5ebSYoshihiro Shimoda plc &= ~PORT_LINK_MODE_MASK;
747e8bde5ebSYoshihiro Shimoda
748e8bde5ebSYoshihiro Shimoda /* Set link width speed control register */
749e8bde5ebSYoshihiro Shimoda lwsc = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
750e8bde5ebSYoshihiro Shimoda lwsc &= ~PORT_LOGIC_LINK_WIDTH_MASK;
751e8bde5ebSYoshihiro Shimoda switch (num_lanes) {
752e8bde5ebSYoshihiro Shimoda case 1:
753e8bde5ebSYoshihiro Shimoda plc |= PORT_LINK_MODE_1_LANES;
754e8bde5ebSYoshihiro Shimoda lwsc |= PORT_LOGIC_LINK_WIDTH_1_LANES;
755e8bde5ebSYoshihiro Shimoda break;
756e8bde5ebSYoshihiro Shimoda case 2:
757e8bde5ebSYoshihiro Shimoda plc |= PORT_LINK_MODE_2_LANES;
758e8bde5ebSYoshihiro Shimoda lwsc |= PORT_LOGIC_LINK_WIDTH_2_LANES;
759e8bde5ebSYoshihiro Shimoda break;
760e8bde5ebSYoshihiro Shimoda case 4:
761e8bde5ebSYoshihiro Shimoda plc |= PORT_LINK_MODE_4_LANES;
762e8bde5ebSYoshihiro Shimoda lwsc |= PORT_LOGIC_LINK_WIDTH_4_LANES;
763e8bde5ebSYoshihiro Shimoda break;
764e8bde5ebSYoshihiro Shimoda case 8:
765e8bde5ebSYoshihiro Shimoda plc |= PORT_LINK_MODE_8_LANES;
766e8bde5ebSYoshihiro Shimoda lwsc |= PORT_LOGIC_LINK_WIDTH_8_LANES;
767e8bde5ebSYoshihiro Shimoda break;
768e8bde5ebSYoshihiro Shimoda default:
769e8bde5ebSYoshihiro Shimoda dev_err(pci->dev, "num-lanes %u: invalid value\n", num_lanes);
770e8bde5ebSYoshihiro Shimoda return;
771e8bde5ebSYoshihiro Shimoda }
772e8bde5ebSYoshihiro Shimoda dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, plc);
773e8bde5ebSYoshihiro Shimoda dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, lwsc);
774*f3dda1cfSYoshihiro Shimoda
775*f3dda1cfSYoshihiro Shimoda cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
776*f3dda1cfSYoshihiro Shimoda lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP);
777*f3dda1cfSYoshihiro Shimoda lnkcap &= ~PCI_EXP_LNKCAP_MLW;
778*f3dda1cfSYoshihiro Shimoda lnkcap |= FIELD_PREP(PCI_EXP_LNKCAP_MLW, num_lanes);
779*f3dda1cfSYoshihiro Shimoda dw_pcie_writel_dbi(pci, cap + PCI_EXP_LNKCAP, lnkcap);
780e8bde5ebSYoshihiro Shimoda }
781e8bde5ebSYoshihiro Shimoda
dw_pcie_iatu_detect(struct dw_pcie * pci)7829f67ecddSSerge Semin void dw_pcie_iatu_detect(struct dw_pcie *pci)
783281f1f99SRob Herring {
7845a163f59SSerge Semin int max_region, ob, ib;
78589473aa9SSerge Semin u32 val, min, dir;
78689473aa9SSerge Semin u64 max;
787281f1f99SRob Herring
7889f67ecddSSerge Semin val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
7899f67ecddSSerge Semin if (val == 0xFFFFFFFF) {
7909f67ecddSSerge Semin dw_pcie_cap_set(pci, IATU_UNROLL);
7919f67ecddSSerge Semin
7925a163f59SSerge Semin max_region = min((int)pci->atu_size / 512, 256);
7935a163f59SSerge Semin } else {
7949f67ecddSSerge Semin pci->atu_base = pci->dbi_base + PCIE_ATU_VIEWPORT_BASE;
7959f67ecddSSerge Semin pci->atu_size = PCIE_ATU_VIEWPORT_SIZE;
7969f67ecddSSerge Semin
797281f1f99SRob Herring dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, 0xFF);
798281f1f99SRob Herring max_region = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT) + 1;
7995a163f59SSerge Semin }
800281f1f99SRob Herring
8015a163f59SSerge Semin for (ob = 0; ob < max_region; ob++) {
8025a163f59SSerge Semin dw_pcie_writel_atu_ob(pci, ob, PCIE_ATU_LOWER_TARGET, 0x11110000);
8035a163f59SSerge Semin val = dw_pcie_readl_atu_ob(pci, ob, PCIE_ATU_LOWER_TARGET);
8045a163f59SSerge Semin if (val != 0x11110000)
805281f1f99SRob Herring break;
806281f1f99SRob Herring }
807281f1f99SRob Herring
8085a163f59SSerge Semin for (ib = 0; ib < max_region; ib++) {
8095a163f59SSerge Semin dw_pcie_writel_atu_ib(pci, ib, PCIE_ATU_LOWER_TARGET, 0x11110000);
8105a163f59SSerge Semin val = dw_pcie_readl_atu_ib(pci, ib, PCIE_ATU_LOWER_TARGET);
8115a163f59SSerge Semin if (val != 0x11110000)
812281f1f99SRob Herring break;
813281f1f99SRob Herring }
814281f1f99SRob Herring
81589473aa9SSerge Semin if (ob) {
81689473aa9SSerge Semin dir = PCIE_ATU_REGION_DIR_OB;
81789473aa9SSerge Semin } else if (ib) {
81889473aa9SSerge Semin dir = PCIE_ATU_REGION_DIR_IB;
81989473aa9SSerge Semin } else {
82089473aa9SSerge Semin dev_err(pci->dev, "No iATU regions found\n");
82189473aa9SSerge Semin return;
82289473aa9SSerge Semin }
82389473aa9SSerge Semin
82489473aa9SSerge Semin dw_pcie_writel_atu(pci, dir, 0, PCIE_ATU_LIMIT, 0x0);
82589473aa9SSerge Semin min = dw_pcie_readl_atu(pci, dir, 0, PCIE_ATU_LIMIT);
82689473aa9SSerge Semin
82789473aa9SSerge Semin if (dw_pcie_ver_is_ge(pci, 460A)) {
82889473aa9SSerge Semin dw_pcie_writel_atu(pci, dir, 0, PCIE_ATU_UPPER_LIMIT, 0xFFFFFFFF);
82989473aa9SSerge Semin max = dw_pcie_readl_atu(pci, dir, 0, PCIE_ATU_UPPER_LIMIT);
83089473aa9SSerge Semin } else {
83189473aa9SSerge Semin max = 0;
83289473aa9SSerge Semin }
83389473aa9SSerge Semin
834281f1f99SRob Herring pci->num_ob_windows = ob;
83589473aa9SSerge Semin pci->num_ib_windows = ib;
83689473aa9SSerge Semin pci->region_align = 1 << fls(min);
83789473aa9SSerge Semin pci->region_limit = (max << 32) | (SZ_4G - 1);
838281f1f99SRob Herring
8399f67ecddSSerge Semin dev_info(pci->dev, "iATU: unroll %s, %u ob, %u ib, align %uK, limit %lluG\n",
8409f67ecddSSerge Semin dw_pcie_cap_is(pci, IATU_UNROLL) ? "T" : "F",
84189473aa9SSerge Semin pci->num_ob_windows, pci->num_ib_windows,
84289473aa9SSerge Semin pci->region_align / SZ_1K, (pci->region_limit + 1) / SZ_1G);
8438bcca265SHou Zhiqiang }
8448bcca265SHou Zhiqiang
dw_pcie_readl_dma(struct dw_pcie * pci,u32 reg)845939fbcd5SSerge Semin static u32 dw_pcie_readl_dma(struct dw_pcie *pci, u32 reg)
846939fbcd5SSerge Semin {
847939fbcd5SSerge Semin u32 val = 0;
848939fbcd5SSerge Semin int ret;
849939fbcd5SSerge Semin
850939fbcd5SSerge Semin if (pci->ops && pci->ops->read_dbi)
851939fbcd5SSerge Semin return pci->ops->read_dbi(pci, pci->edma.reg_base, reg, 4);
852939fbcd5SSerge Semin
853939fbcd5SSerge Semin ret = dw_pcie_read(pci->edma.reg_base + reg, 4, &val);
854939fbcd5SSerge Semin if (ret)
855939fbcd5SSerge Semin dev_err(pci->dev, "Read DMA address failed\n");
856939fbcd5SSerge Semin
857939fbcd5SSerge Semin return val;
858939fbcd5SSerge Semin }
859939fbcd5SSerge Semin
dw_pcie_edma_irq_vector(struct device * dev,unsigned int nr)860939fbcd5SSerge Semin static int dw_pcie_edma_irq_vector(struct device *dev, unsigned int nr)
861939fbcd5SSerge Semin {
862939fbcd5SSerge Semin struct platform_device *pdev = to_platform_device(dev);
863939fbcd5SSerge Semin char name[6];
864939fbcd5SSerge Semin int ret;
865939fbcd5SSerge Semin
866939fbcd5SSerge Semin if (nr >= EDMA_MAX_WR_CH + EDMA_MAX_RD_CH)
867939fbcd5SSerge Semin return -EINVAL;
868939fbcd5SSerge Semin
869939fbcd5SSerge Semin ret = platform_get_irq_byname_optional(pdev, "dma");
870939fbcd5SSerge Semin if (ret > 0)
871939fbcd5SSerge Semin return ret;
872939fbcd5SSerge Semin
873939fbcd5SSerge Semin snprintf(name, sizeof(name), "dma%u", nr);
874939fbcd5SSerge Semin
875939fbcd5SSerge Semin return platform_get_irq_byname_optional(pdev, name);
876939fbcd5SSerge Semin }
877939fbcd5SSerge Semin
87848751755SCai Huoqing static struct dw_edma_plat_ops dw_pcie_edma_ops = {
879939fbcd5SSerge Semin .irq_vector = dw_pcie_edma_irq_vector,
880939fbcd5SSerge Semin };
881939fbcd5SSerge Semin
dw_pcie_edma_find_chip(struct dw_pcie * pci)882939fbcd5SSerge Semin static int dw_pcie_edma_find_chip(struct dw_pcie *pci)
883939fbcd5SSerge Semin {
884939fbcd5SSerge Semin u32 val;
885939fbcd5SSerge Semin
886939fbcd5SSerge Semin /*
887939fbcd5SSerge Semin * Indirect eDMA CSRs access has been completely removed since v5.40a
888939fbcd5SSerge Semin * thus no space is now reserved for the eDMA channels viewport and
889939fbcd5SSerge Semin * former DMA CTRL register is no longer fixed to FFs.
890939fbcd5SSerge Semin */
891939fbcd5SSerge Semin if (dw_pcie_ver_is_ge(pci, 540A))
892939fbcd5SSerge Semin val = 0xFFFFFFFF;
893939fbcd5SSerge Semin else
894939fbcd5SSerge Semin val = dw_pcie_readl_dbi(pci, PCIE_DMA_VIEWPORT_BASE + PCIE_DMA_CTRL);
895939fbcd5SSerge Semin
896939fbcd5SSerge Semin if (val == 0xFFFFFFFF && pci->edma.reg_base) {
897939fbcd5SSerge Semin pci->edma.mf = EDMA_MF_EDMA_UNROLL;
898939fbcd5SSerge Semin
899939fbcd5SSerge Semin val = dw_pcie_readl_dma(pci, PCIE_DMA_CTRL);
900939fbcd5SSerge Semin } else if (val != 0xFFFFFFFF) {
901939fbcd5SSerge Semin pci->edma.mf = EDMA_MF_EDMA_LEGACY;
902939fbcd5SSerge Semin
903939fbcd5SSerge Semin pci->edma.reg_base = pci->dbi_base + PCIE_DMA_VIEWPORT_BASE;
904939fbcd5SSerge Semin } else {
905939fbcd5SSerge Semin return -ENODEV;
906939fbcd5SSerge Semin }
907939fbcd5SSerge Semin
908939fbcd5SSerge Semin pci->edma.dev = pci->dev;
909939fbcd5SSerge Semin
910939fbcd5SSerge Semin if (!pci->edma.ops)
911939fbcd5SSerge Semin pci->edma.ops = &dw_pcie_edma_ops;
912939fbcd5SSerge Semin
913939fbcd5SSerge Semin pci->edma.flags |= DW_EDMA_CHIP_LOCAL;
914939fbcd5SSerge Semin
915939fbcd5SSerge Semin pci->edma.ll_wr_cnt = FIELD_GET(PCIE_DMA_NUM_WR_CHAN, val);
916939fbcd5SSerge Semin pci->edma.ll_rd_cnt = FIELD_GET(PCIE_DMA_NUM_RD_CHAN, val);
917939fbcd5SSerge Semin
918939fbcd5SSerge Semin /* Sanity check the channels count if the mapping was incorrect */
919939fbcd5SSerge Semin if (!pci->edma.ll_wr_cnt || pci->edma.ll_wr_cnt > EDMA_MAX_WR_CH ||
920939fbcd5SSerge Semin !pci->edma.ll_rd_cnt || pci->edma.ll_rd_cnt > EDMA_MAX_RD_CH)
921939fbcd5SSerge Semin return -EINVAL;
922939fbcd5SSerge Semin
923939fbcd5SSerge Semin return 0;
924939fbcd5SSerge Semin }
925939fbcd5SSerge Semin
dw_pcie_edma_irq_verify(struct dw_pcie * pci)926939fbcd5SSerge Semin static int dw_pcie_edma_irq_verify(struct dw_pcie *pci)
927939fbcd5SSerge Semin {
928939fbcd5SSerge Semin struct platform_device *pdev = to_platform_device(pci->dev);
929939fbcd5SSerge Semin u16 ch_cnt = pci->edma.ll_wr_cnt + pci->edma.ll_rd_cnt;
930939fbcd5SSerge Semin char name[6];
931939fbcd5SSerge Semin int ret;
932939fbcd5SSerge Semin
933939fbcd5SSerge Semin if (pci->edma.nr_irqs == 1)
934939fbcd5SSerge Semin return 0;
935939fbcd5SSerge Semin else if (pci->edma.nr_irqs > 1)
936939fbcd5SSerge Semin return pci->edma.nr_irqs != ch_cnt ? -EINVAL : 0;
937939fbcd5SSerge Semin
938939fbcd5SSerge Semin ret = platform_get_irq_byname_optional(pdev, "dma");
939939fbcd5SSerge Semin if (ret > 0) {
940939fbcd5SSerge Semin pci->edma.nr_irqs = 1;
941939fbcd5SSerge Semin return 0;
942939fbcd5SSerge Semin }
943939fbcd5SSerge Semin
944939fbcd5SSerge Semin for (; pci->edma.nr_irqs < ch_cnt; pci->edma.nr_irqs++) {
945939fbcd5SSerge Semin snprintf(name, sizeof(name), "dma%d", pci->edma.nr_irqs);
946939fbcd5SSerge Semin
947939fbcd5SSerge Semin ret = platform_get_irq_byname_optional(pdev, name);
948939fbcd5SSerge Semin if (ret <= 0)
949939fbcd5SSerge Semin return -EINVAL;
950939fbcd5SSerge Semin }
951939fbcd5SSerge Semin
952939fbcd5SSerge Semin return 0;
953939fbcd5SSerge Semin }
954939fbcd5SSerge Semin
dw_pcie_edma_ll_alloc(struct dw_pcie * pci)955939fbcd5SSerge Semin static int dw_pcie_edma_ll_alloc(struct dw_pcie *pci)
956939fbcd5SSerge Semin {
957939fbcd5SSerge Semin struct dw_edma_region *ll;
958939fbcd5SSerge Semin dma_addr_t paddr;
959939fbcd5SSerge Semin int i;
960939fbcd5SSerge Semin
961939fbcd5SSerge Semin for (i = 0; i < pci->edma.ll_wr_cnt; i++) {
962939fbcd5SSerge Semin ll = &pci->edma.ll_region_wr[i];
963939fbcd5SSerge Semin ll->sz = DMA_LLP_MEM_SIZE;
964939fbcd5SSerge Semin ll->vaddr.mem = dmam_alloc_coherent(pci->dev, ll->sz,
965939fbcd5SSerge Semin &paddr, GFP_KERNEL);
966939fbcd5SSerge Semin if (!ll->vaddr.mem)
967939fbcd5SSerge Semin return -ENOMEM;
968939fbcd5SSerge Semin
969939fbcd5SSerge Semin ll->paddr = paddr;
970939fbcd5SSerge Semin }
971939fbcd5SSerge Semin
972939fbcd5SSerge Semin for (i = 0; i < pci->edma.ll_rd_cnt; i++) {
973939fbcd5SSerge Semin ll = &pci->edma.ll_region_rd[i];
974939fbcd5SSerge Semin ll->sz = DMA_LLP_MEM_SIZE;
975939fbcd5SSerge Semin ll->vaddr.mem = dmam_alloc_coherent(pci->dev, ll->sz,
976939fbcd5SSerge Semin &paddr, GFP_KERNEL);
977939fbcd5SSerge Semin if (!ll->vaddr.mem)
978939fbcd5SSerge Semin return -ENOMEM;
979939fbcd5SSerge Semin
980939fbcd5SSerge Semin ll->paddr = paddr;
981939fbcd5SSerge Semin }
982939fbcd5SSerge Semin
983939fbcd5SSerge Semin return 0;
984939fbcd5SSerge Semin }
985939fbcd5SSerge Semin
dw_pcie_edma_detect(struct dw_pcie * pci)986939fbcd5SSerge Semin int dw_pcie_edma_detect(struct dw_pcie *pci)
987939fbcd5SSerge Semin {
988939fbcd5SSerge Semin int ret;
989939fbcd5SSerge Semin
990939fbcd5SSerge Semin /* Don't fail if no eDMA was found (for the backward compatibility) */
991939fbcd5SSerge Semin ret = dw_pcie_edma_find_chip(pci);
992939fbcd5SSerge Semin if (ret)
993939fbcd5SSerge Semin return 0;
994939fbcd5SSerge Semin
995939fbcd5SSerge Semin /* Don't fail on the IRQs verification (for the backward compatibility) */
996939fbcd5SSerge Semin ret = dw_pcie_edma_irq_verify(pci);
997939fbcd5SSerge Semin if (ret) {
998939fbcd5SSerge Semin dev_err(pci->dev, "Invalid eDMA IRQs found\n");
999939fbcd5SSerge Semin return 0;
1000939fbcd5SSerge Semin }
1001939fbcd5SSerge Semin
1002939fbcd5SSerge Semin ret = dw_pcie_edma_ll_alloc(pci);
1003939fbcd5SSerge Semin if (ret) {
1004939fbcd5SSerge Semin dev_err(pci->dev, "Couldn't allocate LLP memory\n");
1005939fbcd5SSerge Semin return ret;
1006939fbcd5SSerge Semin }
1007939fbcd5SSerge Semin
1008939fbcd5SSerge Semin /* Don't fail if the DW eDMA driver can't find the device */
1009939fbcd5SSerge Semin ret = dw_edma_probe(&pci->edma);
1010939fbcd5SSerge Semin if (ret && ret != -ENODEV) {
1011939fbcd5SSerge Semin dev_err(pci->dev, "Couldn't register eDMA device\n");
1012939fbcd5SSerge Semin return ret;
1013939fbcd5SSerge Semin }
1014939fbcd5SSerge Semin
1015939fbcd5SSerge Semin dev_info(pci->dev, "eDMA: unroll %s, %hu wr, %hu rd\n",
1016939fbcd5SSerge Semin pci->edma.mf == EDMA_MF_EDMA_UNROLL ? "T" : "F",
1017939fbcd5SSerge Semin pci->edma.ll_wr_cnt, pci->edma.ll_rd_cnt);
1018939fbcd5SSerge Semin
1019939fbcd5SSerge Semin return 0;
1020939fbcd5SSerge Semin }
1021939fbcd5SSerge Semin
dw_pcie_edma_remove(struct dw_pcie * pci)1022939fbcd5SSerge Semin void dw_pcie_edma_remove(struct dw_pcie *pci)
1023939fbcd5SSerge Semin {
1024939fbcd5SSerge Semin dw_edma_remove(&pci->edma);
1025939fbcd5SSerge Semin }
1026939fbcd5SSerge Semin
dw_pcie_setup(struct dw_pcie * pci)10278bcca265SHou Zhiqiang void dw_pcie_setup(struct dw_pcie *pci)
10288bcca265SHou Zhiqiang {
10298bcca265SHou Zhiqiang u32 val;
1030281f1f99SRob Herring
103139bc5006SRob Herring if (pci->link_gen > 0)
103239bc5006SRob Herring dw_pcie_link_set_max_speed(pci, pci->link_gen);
103339bc5006SRob Herring
1034aeaa0bfeSRob Herring /* Configure Gen1 N_FTS */
1035aeaa0bfeSRob Herring if (pci->n_fts[0]) {
1036aeaa0bfeSRob Herring val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
1037aeaa0bfeSRob Herring val &= ~(PORT_AFR_N_FTS_MASK | PORT_AFR_CC_N_FTS_MASK);
1038aeaa0bfeSRob Herring val |= PORT_AFR_N_FTS(pci->n_fts[0]);
1039aeaa0bfeSRob Herring val |= PORT_AFR_CC_N_FTS(pci->n_fts[0]);
1040aeaa0bfeSRob Herring dw_pcie_writel_dbi(pci, PCIE_PORT_AFR, val);
1041aeaa0bfeSRob Herring }
1042aeaa0bfeSRob Herring
1043aeaa0bfeSRob Herring /* Configure Gen2+ N_FTS */
1044aeaa0bfeSRob Herring if (pci->n_fts[1]) {
1045aeaa0bfeSRob Herring val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
1046aeaa0bfeSRob Herring val &= ~PORT_LOGIC_N_FTS_MASK;
104766110361SVidya Sagar val |= pci->n_fts[1];
1048aeaa0bfeSRob Herring dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
1049aeaa0bfeSRob Herring }
1050aeaa0bfeSRob Herring
1051ef8c5887SSerge Semin if (dw_pcie_cap_is(pci, CDM_CHECK)) {
1052ec7b952fSSerge Semin val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
1053ec7b952fSSerge Semin val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS |
1054ec7b952fSSerge Semin PCIE_PL_CHK_REG_CHK_REG_START;
1055ec7b952fSSerge Semin dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
1056ec7b952fSSerge Semin }
1057ec7b952fSSerge Semin
1058cdce6709SYoshihiro Shimoda val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
1059cdce6709SYoshihiro Shimoda val &= ~PORT_LINK_FAST_LINK_MODE;
1060cdce6709SYoshihiro Shimoda val |= PORT_LINK_DLL_LINK_EN;
1061cdce6709SYoshihiro Shimoda dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
1062cdce6709SYoshihiro Shimoda
1063e8bde5ebSYoshihiro Shimoda dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
10646e0832faSShawn Lin }
1065