blob: 3824862ea144f41de6c2ada825976dd481cc0a3c [file] [log] [blame]
Oliver Hübers7d6bc562018-07-13 15:41:06 +02001// SPDX-License-Identifier: GPL-2.0+
Sergio Paracuellos335bbd92018-11-04 11:49:32 +01002/*
3 * BRIEF MODULE DESCRIPTION
John Crispin03f152e2018-03-15 07:22:35 +11004 * PCI init for Ralink RT2880 solution
5 *
Sergio Paracuellos335bbd92018-11-04 11:49:32 +01006 * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
John Crispin03f152e2018-03-15 07:22:35 +11007 *
John Crispin03f152e2018-03-15 07:22:35 +11008 * May 2007 Bruce Chang
9 * Initial Release
10 *
11 * May 2009 Bruce Chang
12 * support RT2880/RT3883 PCIe
13 *
14 * May 2011 Bruce Chang
15 * support RT6855/MT7620 PCIe
John Crispin03f152e2018-03-15 07:22:35 +110016 */
17
Sergio Paracuelloscd7d07d2018-08-03 10:27:02 +020018#include <linux/bitops.h>
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +020019#include <linux/clk.h>
John Crispin03f152e2018-03-15 07:22:35 +110020#include <linux/delay.h>
Sergio Paracuellos07420a02019-06-19 09:44:56 +020021#include <linux/gpio/consumer.h>
Sergio Paracuelloscd7d07d2018-08-03 10:27:02 +020022#include <linux/module.h>
John Crispin03f152e2018-03-15 07:22:35 +110023#include <linux/of.h>
Sergio Paracuellos8571c622018-08-03 10:26:54 +020024#include <linux/of_address.h>
Sergio Paracuelloscd7d07d2018-08-03 10:27:02 +020025#include <linux/of_pci.h>
26#include <linux/of_platform.h>
27#include <linux/pci.h>
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +010028#include <linux/phy/phy.h>
John Crispin03f152e2018-03-15 07:22:35 +110029#include <linux/platform_device.h>
Sergio Paracuelloscd7d07d2018-08-03 10:27:02 +020030#include <linux/reset.h>
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +020031#include <linux/sys_soc.h>
Sergio Paracuellos8571c622018-08-03 10:26:54 +020032
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +020033/* MediaTek-specific configuration registers */
Sergio Paracuellosa4b2eb92018-11-04 11:49:51 +010034#define PCIE_FTS_NUM 0x70c
35#define PCIE_FTS_NUM_MASK GENMASK(15, 8)
Sergio Paracuellos0ae0cf52019-06-26 14:43:18 +020036#define PCIE_FTS_NUM_L0(x) (((x) & 0xff) << 8)
Sergio Paracuellosa4b2eb92018-11-04 11:49:51 +010037
Sergio Paracuellosa934d902018-11-04 11:49:48 +010038/* Host-PCI bridge registers */
Sergio Paracuellos152f3892018-08-03 10:27:03 +020039#define RALINK_PCI_PCICFG_ADDR 0x0000
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +020040#define RALINK_PCI_PCIMSK_ADDR 0x000c
Sergio Paracuellosa934d902018-11-04 11:49:48 +010041#define RALINK_PCI_CONFIG_ADDR 0x0020
42#define RALINK_PCI_CONFIG_DATA 0x0024
43#define RALINK_PCI_MEMBASE 0x0028
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +020044#define RALINK_PCI_IOBASE 0x002c
John Crispin03f152e2018-03-15 07:22:35 +110045
Sergio Paracuellosa934d902018-11-04 11:49:48 +010046/* PCIe RC control registers */
Sergio Paracuellose38bb172018-08-03 10:27:01 +020047#define RALINK_PCI_ID 0x0030
48#define RALINK_PCI_CLASS 0x0034
49#define RALINK_PCI_SUBID 0x0038
50#define RALINK_PCI_STATUS 0x0050
John Crispin03f152e2018-03-15 07:22:35 +110051
Sergio Paracuellosa934d902018-11-04 11:49:48 +010052/* Some definition values */
Sergio Paracuellos301c15b2018-11-04 11:49:52 +010053#define PCIE_REVISION_ID BIT(0)
54#define PCIE_CLASS_CODE (0x60400 << 8)
55#define PCIE_BAR_MAP_MAX GENMASK(30, 16)
56#define PCIE_BAR_ENABLE BIT(0)
57#define PCIE_PORT_INT_EN(x) BIT(20 + (x))
Sergio Paracuellosbd1a05b2018-11-04 11:49:54 +010058#define PCIE_PORT_LINKUP BIT(0)
Sergio Paracuellos7d761b02021-08-23 19:08:03 +020059#define PCIE_PORT_CNT 3
Sergio Paracuellos301c15b2018-11-04 11:49:52 +010060
Sergio Paracuellos475fe232020-03-13 21:09:09 +010061#define PERST_DELAY_MS 100
Sergio Paracuellos6b767902018-11-04 11:49:36 +010062
Sergio Paracuellos8571c622018-08-03 10:26:54 +020063/**
64 * struct mt7621_pcie_port - PCIe port information
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +010065 * @base: I/O mapped register base
Sergio Paracuellos8571c622018-08-03 10:26:54 +020066 * @list: port list
67 * @pcie: pointer to PCIe host info
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +020068 * @clk: pointer to the port clock gate
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +010069 * @phy: pointer to PHY control block
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +010070 * @pcie_rst: pointer to port reset control
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +010071 * @gpio_rst: gpio reset
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +010072 * @slot: port slot
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +010073 * @enabled: indicates if port is enabled
Sergio Paracuellos8571c622018-08-03 10:26:54 +020074 */
75struct mt7621_pcie_port {
76 void __iomem *base;
77 struct list_head list;
78 struct mt7621_pcie *pcie;
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +020079 struct clk *clk;
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +010080 struct phy *phy;
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +010081 struct reset_control *pcie_rst;
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +010082 struct gpio_desc *gpio_rst;
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +010083 u32 slot;
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +010084 bool enabled;
Sergio Paracuellos8571c622018-08-03 10:26:54 +020085};
86
87/**
88 * struct mt7621_pcie - PCIe host information
89 * @base: IO Mapped Register Base
Sergio Paracuellos8571c622018-08-03 10:26:54 +020090 * @dev: Pointer to PCIe device
91 * @ports: pointer to PCIe port information
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +020092 * @resets_inverted: depends on chip revision
93 * reset lines are inverted.
Sergio Paracuellos8571c622018-08-03 10:26:54 +020094 */
95struct mt7621_pcie {
Sergio Paracuellos8571c622018-08-03 10:26:54 +020096 struct device *dev;
Bjorn Helgaas47938952021-12-22 19:10:48 -060097 void __iomem *base;
Sergio Paracuellos8571c622018-08-03 10:26:54 +020098 struct list_head ports;
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +020099 bool resets_inverted;
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200100};
101
Sergio Paracuellos52ed7272018-08-03 10:26:56 +0200102static inline u32 pcie_read(struct mt7621_pcie *pcie, u32 reg)
103{
Sergio Paracuellos860bce42021-06-07 14:01:50 +0200104 return readl_relaxed(pcie->base + reg);
Sergio Paracuellos52ed7272018-08-03 10:26:56 +0200105}
106
107static inline void pcie_write(struct mt7621_pcie *pcie, u32 val, u32 reg)
108{
Sergio Paracuellos860bce42021-06-07 14:01:50 +0200109 writel_relaxed(val, pcie->base + reg);
Sergio Paracuellos52ed7272018-08-03 10:26:56 +0200110}
111
Sergio Paracuellos9a5e71a2020-03-08 10:19:27 +0100112static inline void pcie_rmw(struct mt7621_pcie *pcie, u32 reg, u32 clr, u32 set)
113{
Sergio Paracuellos860bce42021-06-07 14:01:50 +0200114 u32 val = readl_relaxed(pcie->base + reg);
Sergio Paracuellos9a5e71a2020-03-08 10:19:27 +0100115
116 val &= ~clr;
117 val |= set;
Sergio Paracuellos860bce42021-06-07 14:01:50 +0200118 writel_relaxed(val, pcie->base + reg);
Sergio Paracuellos9a5e71a2020-03-08 10:19:27 +0100119}
120
Sergio Paracuellosc8242be2018-11-04 11:49:29 +0100121static inline u32 pcie_port_read(struct mt7621_pcie_port *port, u32 reg)
122{
Sergio Paracuellos860bce42021-06-07 14:01:50 +0200123 return readl_relaxed(port->base + reg);
Sergio Paracuellosc8242be2018-11-04 11:49:29 +0100124}
125
126static inline void pcie_port_write(struct mt7621_pcie_port *port,
127 u32 val, u32 reg)
128{
Sergio Paracuellos860bce42021-06-07 14:01:50 +0200129 writel_relaxed(val, port->base + reg);
Sergio Paracuellosc8242be2018-11-04 11:49:29 +0100130}
131
Bjorn Helgaas47938952021-12-22 19:10:48 -0600132static inline u32 mt7621_pcie_get_cfgaddr(unsigned int bus, unsigned int slot,
Sergio Paracuellos2427d172018-07-09 22:21:04 +0200133 unsigned int func, unsigned int where)
134{
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +0200135 return (((where & 0xf00) >> 8) << 24) | (bus << 16) | (slot << 11) |
Sergio Paracuellos2427d172018-07-09 22:21:04 +0200136 (func << 8) | (where & 0xfc) | 0x80000000;
137}
138
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200139static void __iomem *mt7621_pcie_map_bus(struct pci_bus *bus,
140 unsigned int devfn, int where)
141{
142 struct mt7621_pcie *pcie = bus->sysdata;
Bjorn Helgaas47938952021-12-22 19:10:48 -0600143 u32 address = mt7621_pcie_get_cfgaddr(bus->number, PCI_SLOT(devfn),
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200144 PCI_FUNC(devfn), where);
John Crispin03f152e2018-03-15 07:22:35 +1100145
Sergio Paracuellos860bce42021-06-07 14:01:50 +0200146 writel_relaxed(address, pcie->base + RALINK_PCI_CONFIG_ADDR);
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200147
Sergio Paracuellos85943512018-08-03 10:27:06 +0200148 return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3);
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200149}
150
Bjorn Helgaas87c71932022-01-13 09:57:53 -0600151static struct pci_ops mt7621_pcie_ops = {
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200152 .map_bus = mt7621_pcie_map_bus,
153 .read = pci_generic_config_read,
154 .write = pci_generic_config_write,
John Crispin03f152e2018-03-15 07:22:35 +1100155};
156
Sergio Paracuellosce3368d2018-11-04 11:49:50 +0100157static u32 read_config(struct mt7621_pcie *pcie, unsigned int dev, u32 reg)
John Crispin03f152e2018-03-15 07:22:35 +1100158{
Bjorn Helgaas47938952021-12-22 19:10:48 -0600159 u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg);
John Crispin03f152e2018-03-15 07:22:35 +1100160
Sergio Paracuellos9f999b42018-08-03 10:26:57 +0200161 pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR);
Sergio Paracuellos85943512018-08-03 10:27:06 +0200162 return pcie_read(pcie, RALINK_PCI_CONFIG_DATA);
John Crispin03f152e2018-03-15 07:22:35 +1100163}
164
Sergio Paracuellosce3368d2018-11-04 11:49:50 +0100165static void write_config(struct mt7621_pcie *pcie, unsigned int dev,
166 u32 reg, u32 val)
John Crispin03f152e2018-03-15 07:22:35 +1100167{
Bjorn Helgaas47938952021-12-22 19:10:48 -0600168 u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg);
John Crispin03f152e2018-03-15 07:22:35 +1100169
Sergio Paracuellos9f999b42018-08-03 10:26:57 +0200170 pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR);
Sergio Paracuellos85943512018-08-03 10:27:06 +0200171 pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA);
John Crispin03f152e2018-03-15 07:22:35 +1100172}
173
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100174static inline void mt7621_rst_gpio_pcie_assert(struct mt7621_pcie_port *port)
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200175{
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100176 if (port->gpio_rst)
177 gpiod_set_value(port->gpio_rst, 1);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200178}
179
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100180static inline void mt7621_rst_gpio_pcie_deassert(struct mt7621_pcie_port *port)
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200181{
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100182 if (port->gpio_rst)
183 gpiod_set_value(port->gpio_rst, 0);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200184}
185
186static inline bool mt7621_pcie_port_is_linkup(struct mt7621_pcie_port *port)
187{
188 return (pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) != 0;
189}
190
Sergio Paracuellose51844b2018-11-24 18:54:54 +0100191static inline void mt7621_control_assert(struct mt7621_pcie_port *port)
192{
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +0200193 struct mt7621_pcie *pcie = port->pcie;
Sergio Paracuellose51844b2018-11-24 18:54:54 +0100194
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +0200195 if (pcie->resets_inverted)
Sergio Paracuellose51844b2018-11-24 18:54:54 +0100196 reset_control_assert(port->pcie_rst);
197 else
198 reset_control_deassert(port->pcie_rst);
199}
200
201static inline void mt7621_control_deassert(struct mt7621_pcie_port *port)
202{
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +0200203 struct mt7621_pcie *pcie = port->pcie;
Sergio Paracuellose51844b2018-11-24 18:54:54 +0100204
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +0200205 if (pcie->resets_inverted)
Sergio Paracuellose51844b2018-11-24 18:54:54 +0100206 reset_control_deassert(port->pcie_rst);
207 else
208 reset_control_assert(port->pcie_rst);
209}
210
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100211static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200212 struct device_node *node,
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100213 int slot)
214{
215 struct mt7621_pcie_port *port;
216 struct device *dev = pcie->dev;
Sergio Paracuellosfab67102020-04-13 07:59:42 +0200217 struct platform_device *pdev = to_platform_device(dev);
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +0100218 char name[10];
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200219 int err;
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100220
221 port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
222 if (!port)
223 return -ENOMEM;
224
Sergio Paracuellos108b2f22020-11-23 10:36:36 +0100225 port->base = devm_platform_ioremap_resource(pdev, slot + 1);
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100226 if (IS_ERR(port->base))
227 return PTR_ERR(port->base);
228
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200229 port->clk = devm_get_clk_from_child(dev, node, NULL);
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +0200230 if (IS_ERR(port->clk)) {
231 dev_err(dev, "failed to get pcie%d clock\n", slot);
232 return PTR_ERR(port->clk);
233 }
234
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200235 port->pcie_rst = of_reset_control_get_exclusive(node, NULL);
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100236 if (PTR_ERR(port->pcie_rst) == -EPROBE_DEFER) {
237 dev_err(dev, "failed to get pcie%d reset control\n", slot);
238 return PTR_ERR(port->pcie_rst);
239 }
240
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +0100241 snprintf(name, sizeof(name), "pcie-phy%d", slot);
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200242 port->phy = devm_of_phy_get(dev, node, name);
243 if (IS_ERR(port->phy)) {
244 dev_err(dev, "failed to get pcie-phy%d\n", slot);
245 err = PTR_ERR(port->phy);
246 goto remove_reset;
247 }
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +0100248
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100249 port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot,
250 GPIOD_OUT_LOW);
Sergio Paracuellos825c6f42020-03-20 12:01:23 +0100251 if (IS_ERR(port->gpio_rst)) {
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +0200252 dev_err(dev, "failed to get GPIO for PCIe%d\n", slot);
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200253 err = PTR_ERR(port->gpio_rst);
254 goto remove_reset;
Sergio Paracuellos825c6f42020-03-20 12:01:23 +0100255 }
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100256
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100257 port->slot = slot;
258 port->pcie = pcie;
259
260 INIT_LIST_HEAD(&port->list);
261 list_add_tail(&port->list, &pcie->ports);
262
263 return 0;
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200264
265remove_reset:
266 reset_control_put(port->pcie_rst);
267 return err;
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100268}
269
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200270static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie)
271{
272 struct device *dev = pcie->dev;
Sergio Paracuellos108b2f22020-11-23 10:36:36 +0100273 struct platform_device *pdev = to_platform_device(dev);
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100274 struct device_node *node = dev->of_node, *child;
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200275 int err;
276
Sergio Paracuellos108b2f22020-11-23 10:36:36 +0100277 pcie->base = devm_platform_ioremap_resource(pdev, 0);
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200278 if (IS_ERR(pcie->base))
279 return PTR_ERR(pcie->base);
280
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100281 for_each_available_child_of_node(node, child) {
282 int slot;
283
284 err = of_pci_get_devfn(child);
285 if (err < 0) {
Nishka Dasgupta2125a442019-07-16 11:29:44 +0530286 of_node_put(child);
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100287 dev_err(dev, "failed to parse devfn: %d\n", err);
288 return err;
289 }
290
291 slot = PCI_SLOT(err);
292
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200293 err = mt7621_pcie_parse_port(pcie, child, slot);
Nishka Dasgupta2125a442019-07-16 11:29:44 +0530294 if (err) {
295 of_node_put(child);
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100296 return err;
Nishka Dasgupta2125a442019-07-16 11:29:44 +0530297 }
Sergio Paracuellosad9c87e2018-11-04 11:49:27 +0100298 }
299
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200300 return 0;
301}
302
Sergio Paracuellos4fdf3ab2018-11-04 11:49:39 +0100303static int mt7621_pcie_init_port(struct mt7621_pcie_port *port)
Sergio Paracuellos745eeea2018-11-04 11:49:30 +0100304{
305 struct mt7621_pcie *pcie = port->pcie;
306 struct device *dev = pcie->dev;
307 u32 slot = port->slot;
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +0100308 int err;
Sergio Paracuellos745eeea2018-11-04 11:49:30 +0100309
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +0100310 err = phy_init(port->phy);
311 if (err) {
312 dev_err(dev, "failed to initialize port%d phy\n", slot);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200313 return err;
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +0100314 }
315
316 err = phy_power_on(port->phy);
317 if (err) {
318 dev_err(dev, "failed to power on port%d phy\n", slot);
Sergio Paracuelloscdf6f832019-06-21 08:15:15 +0200319 phy_exit(port->phy);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200320 return err;
Sergio Paracuellos745eeea2018-11-04 11:49:30 +0100321 }
322
Sergio Paracuellos61f9bde2019-01-04 08:08:22 +0100323 port->enabled = true;
Sergio Paracuellos3beb6da2018-11-04 11:49:37 +0100324
Sergio Paracuellos745eeea2018-11-04 11:49:30 +0100325 return 0;
326}
327
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100328static void mt7621_pcie_reset_assert(struct mt7621_pcie *pcie)
329{
330 struct mt7621_pcie_port *port;
331
332 list_for_each_entry(port, &pcie->ports, list) {
333 /* PCIe RC reset assert */
334 mt7621_control_assert(port);
335
336 /* PCIe EP reset assert */
337 mt7621_rst_gpio_pcie_assert(port);
338 }
339
Sergio Paracuellos4ab4ca22021-05-05 14:17:31 +0200340 msleep(PERST_DELAY_MS);
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100341}
342
343static void mt7621_pcie_reset_rc_deassert(struct mt7621_pcie *pcie)
344{
345 struct mt7621_pcie_port *port;
346
347 list_for_each_entry(port, &pcie->ports, list)
348 mt7621_control_deassert(port);
349}
350
351static void mt7621_pcie_reset_ep_deassert(struct mt7621_pcie *pcie)
352{
353 struct mt7621_pcie_port *port;
354
355 list_for_each_entry(port, &pcie->ports, list)
356 mt7621_rst_gpio_pcie_deassert(port);
357
Sergio Paracuellos4ab4ca22021-05-05 14:17:31 +0200358 msleep(PERST_DELAY_MS);
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100359}
360
Sergio Paracuellos7d761b02021-08-23 19:08:03 +0200361static int mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
Sergio Paracuelloscd910f12018-11-04 11:49:46 +0100362{
363 struct device *dev = pcie->dev;
364 struct mt7621_pcie_port *port, *tmp;
Sergio Paracuellos7d761b02021-08-23 19:08:03 +0200365 u8 num_disabled = 0;
Sergio Paracuelloscd910f12018-11-04 11:49:46 +0100366 int err;
367
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100368 mt7621_pcie_reset_assert(pcie);
369 mt7621_pcie_reset_rc_deassert(pcie);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200370
Sergio Paracuelloscd910f12018-11-04 11:49:46 +0100371 list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
372 u32 slot = port->slot;
373
Sergio Paracuellosbf516f42020-03-20 12:01:21 +0100374 if (slot == 1) {
375 port->enabled = true;
376 continue;
377 }
378
Sergio Paracuelloscd910f12018-11-04 11:49:46 +0100379 err = mt7621_pcie_init_port(port);
380 if (err) {
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +0200381 dev_err(dev, "initializing port %d failed\n", slot);
Sergio Paracuelloscd910f12018-11-04 11:49:46 +0100382 list_del(&port->list);
383 }
384 }
Sergio Paracuellosb8d97d432018-11-04 11:49:58 +0100385
Sergio Paracuellosb27e35f2020-03-13 21:09:08 +0100386 mt7621_pcie_reset_ep_deassert(pcie);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200387
Sergio Paracuellos5fcded52020-04-09 13:16:52 +0200388 tmp = NULL;
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200389 list_for_each_entry(port, &pcie->ports, list) {
390 u32 slot = port->slot;
391
392 if (!mt7621_pcie_port_is_linkup(port)) {
393 dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n",
394 slot);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200395 mt7621_control_assert(port);
396 port->enabled = false;
Sergio Paracuellos7d761b02021-08-23 19:08:03 +0200397 num_disabled++;
Sergio Paracuellos5fcded52020-04-09 13:16:52 +0200398
399 if (slot == 0) {
400 tmp = port;
401 continue;
402 }
403
404 if (slot == 1 && tmp && !tmp->enabled)
405 phy_power_off(tmp->phy);
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200406 }
407 }
Sergio Paracuellos7d761b02021-08-23 19:08:03 +0200408
409 return (num_disabled != PCIE_PORT_CNT) ? 0 : -ENODEV;
Sergio Paracuelloscd910f12018-11-04 11:49:46 +0100410}
411
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200412static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port)
Sergio Paracuellos802a2f72018-11-04 11:49:57 +0100413{
414 struct mt7621_pcie *pcie = port->pcie;
415 u32 slot = port->slot;
Sergio Paracuellos802a2f72018-11-04 11:49:57 +0100416 u32 val;
Sergio Paracuellos802a2f72018-11-04 11:49:57 +0100417
418 /* enable pcie interrupt */
419 val = pcie_read(pcie, RALINK_PCI_PCIMSK_ADDR);
420 val |= PCIE_PORT_INT_EN(slot);
421 pcie_write(pcie, val, RALINK_PCI_PCIMSK_ADDR);
422
423 /* map 2G DDR region */
Sergio Paracuellos25203e32021-06-07 14:01:53 +0200424 pcie_port_write(port, PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE,
425 PCI_BASE_ADDRESS_0);
Sergio Paracuellos802a2f72018-11-04 11:49:57 +0100426
427 /* configure class code and revision ID */
Sergio Paracuellos25203e32021-06-07 14:01:53 +0200428 pcie_port_write(port, PCIE_CLASS_CODE | PCIE_REVISION_ID,
429 RALINK_PCI_CLASS);
Sergio Paracuellosa3bb1d02021-06-07 14:01:48 +0200430
431 /* configure RC FTS number to 250 when it leaves L0s */
432 val = read_config(pcie, slot, PCIE_FTS_NUM);
433 val &= ~PCIE_FTS_NUM_MASK;
434 val |= PCIE_FTS_NUM_L0(0x50);
435 write_config(pcie, slot, PCIE_FTS_NUM, val);
Sergio Paracuellos802a2f72018-11-04 11:49:57 +0100436}
437
Sergio Paracuellosb15606e2021-06-14 12:06:16 +0200438static int mt7621_pcie_enable_ports(struct pci_host_bridge *host)
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +0100439{
Sergio Paracuellosb15606e2021-06-14 12:06:16 +0200440 struct mt7621_pcie *pcie = pci_host_bridge_priv(host);
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +0100441 struct device *dev = pcie->dev;
442 struct mt7621_pcie_port *port;
Sergio Paracuellosb15606e2021-06-14 12:06:16 +0200443 struct resource_entry *entry;
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +0200444 int err;
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +0100445
Sergio Paracuellosb15606e2021-06-14 12:06:16 +0200446 entry = resource_list_first_type(&host->windows, IORESOURCE_IO);
447 if (!entry) {
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +0200448 dev_err(dev, "cannot get io resource\n");
Sergio Paracuellosb15606e2021-06-14 12:06:16 +0200449 return -EINVAL;
450 }
451
Sergio Paracuellos09dd6292020-03-18 10:44:45 +0100452 /* Setup MEMWIN and IOWIN */
453 pcie_write(pcie, 0xffffffff, RALINK_PCI_MEMBASE);
Sergio Paracuellose0b91382021-09-25 22:32:24 +0200454 pcie_write(pcie, entry->res->start - entry->offset, RALINK_PCI_IOBASE);
Sergio Paracuellos09dd6292020-03-18 10:44:45 +0100455
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +0100456 list_for_each_entry(port, &pcie->ports, list) {
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +0100457 if (port->enabled) {
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +0200458 err = clk_prepare_enable(port->clk);
459 if (err) {
Sergio Paracuellosa3bb1d02021-06-07 14:01:48 +0200460 dev_err(dev, "enabling clk pcie%d\n",
461 port->slot);
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +0200462 return err;
463 }
464
Sergio Paracuellos07420a02019-06-19 09:44:56 +0200465 mt7621_pcie_enable_port(port);
Sergio Paracuellos7846a982020-03-20 12:01:22 +0100466 dev_info(dev, "PCIE%d enabled\n", port->slot);
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +0100467 }
468 }
469
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +0200470 return 0;
Sergio Paracuellosa41a1f82018-11-04 11:49:44 +0100471}
472
Sergio Paracuellos2fc08982020-11-23 10:36:35 +0100473static int mt7621_pcie_register_host(struct pci_host_bridge *host)
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200474{
475 struct mt7621_pcie *pcie = pci_host_bridge_priv(host);
476
Bjorn Helgaas47938952021-12-22 19:10:48 -0600477 host->ops = &mt7621_pcie_ops;
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200478 host->sysdata = pcie;
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200479 return pci_host_probe(host);
480}
481
Bjorn Helgaas47938952021-12-22 19:10:48 -0600482static const struct soc_device_attribute mt7621_pcie_quirks_match[] = {
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +0200483 { .soc_id = "mt7621", .revision = "E2" }
484};
485
Bjorn Helgaas47938952021-12-22 19:10:48 -0600486static int mt7621_pcie_probe(struct platform_device *pdev)
John Crispin03f152e2018-03-15 07:22:35 +1100487{
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200488 struct device *dev = &pdev->dev;
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +0200489 const struct soc_device_attribute *attr;
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200490 struct mt7621_pcie_port *port;
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200491 struct mt7621_pcie *pcie;
492 struct pci_host_bridge *bridge;
493 int err;
John Crispin03f152e2018-03-15 07:22:35 +1100494
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200495 if (!dev->of_node)
496 return -ENODEV;
497
498 bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
499 if (!bridge)
Sergio Paracuellosa80775d2018-11-04 11:49:28 +0100500 return -ENOMEM;
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200501
502 pcie = pci_host_bridge_priv(bridge);
503 pcie->dev = dev;
504 platform_set_drvdata(pdev, pcie);
505 INIT_LIST_HEAD(&pcie->ports);
506
Bjorn Helgaas47938952021-12-22 19:10:48 -0600507 attr = soc_device_match(mt7621_pcie_quirks_match);
Sergio Paracuellosb483b4e2019-10-06 20:10:32 +0200508 if (attr)
509 pcie->resets_inverted = true;
510
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200511 err = mt7621_pcie_parse_dt(pcie);
512 if (err) {
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +0200513 dev_err(dev, "parsing DT failed\n");
Sergio Paracuellos8571c622018-08-03 10:26:54 +0200514 return err;
515 }
516
Sergio Paracuellos7d761b02021-08-23 19:08:03 +0200517 err = mt7621_pcie_init_ports(pcie);
518 if (err) {
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +0200519 dev_err(dev, "nothing connected in virtual bridges\n");
Sergio Paracuellos7d761b02021-08-23 19:08:03 +0200520 return 0;
521 }
John Crispin03f152e2018-03-15 07:22:35 +1100522
Sergio Paracuellosb15606e2021-06-14 12:06:16 +0200523 err = mt7621_pcie_enable_ports(bridge);
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +0200524 if (err) {
Sergio Paracuellos2bdd5232021-09-22 07:00:34 +0200525 dev_err(dev, "error enabling pcie ports\n");
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200526 goto remove_resets;
Sergio Paracuelloscc4e8642021-05-05 14:17:27 +0200527 }
John Crispin03f152e2018-03-15 07:22:35 +1100528
Sergio Paracuellos35d96b82021-05-05 14:17:32 +0200529 return mt7621_pcie_register_host(bridge);
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200530
531remove_resets:
532 list_for_each_entry(port, &pcie->ports, list)
533 reset_control_put(port->pcie_rst);
534
535 return err;
536}
537
Bjorn Helgaas47938952021-12-22 19:10:48 -0600538static int mt7621_pcie_remove(struct platform_device *pdev)
Sergio Paracuellos2d3d2882021-06-07 14:01:52 +0200539{
540 struct mt7621_pcie *pcie = platform_get_drvdata(pdev);
541 struct mt7621_pcie_port *port;
542
543 list_for_each_entry(port, &pcie->ports, list)
544 reset_control_put(port->pcie_rst);
545
546 return 0;
John Crispin03f152e2018-03-15 07:22:35 +1100547}
548
Bjorn Helgaas47938952021-12-22 19:10:48 -0600549static const struct of_device_id mt7621_pcie_ids[] = {
John Crispin03f152e2018-03-15 07:22:35 +1100550 { .compatible = "mediatek,mt7621-pci" },
551 {},
552};
Bjorn Helgaas47938952021-12-22 19:10:48 -0600553MODULE_DEVICE_TABLE(of, mt7621_pcie_ids);
John Crispin03f152e2018-03-15 07:22:35 +1100554
Bjorn Helgaas47938952021-12-22 19:10:48 -0600555static struct platform_driver mt7621_pcie_driver = {
556 .probe = mt7621_pcie_probe,
557 .remove = mt7621_pcie_remove,
John Crispin03f152e2018-03-15 07:22:35 +1100558 .driver = {
559 .name = "mt7621-pci",
Bjorn Helgaas47938952021-12-22 19:10:48 -0600560 .of_match_table = of_match_ptr(mt7621_pcie_ids),
John Crispin03f152e2018-03-15 07:22:35 +1100561 },
562};
Bjorn Helgaas47938952021-12-22 19:10:48 -0600563builtin_platform_driver(mt7621_pcie_driver);
Sergio Paracuellose4b1cd02021-12-07 11:49:23 +0100564
565MODULE_LICENSE("GPL v2");