18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Ralink RT3662/RT3883 SoC PCI support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *  Parts of this file are based on Ralink's 2.6.21 BSP
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/types.h>
118c2ecf20Sopenharmony_ci#include <linux/pci.h>
128c2ecf20Sopenharmony_ci#include <linux/io.h>
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/delay.h>
158c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
168c2ecf20Sopenharmony_ci#include <linux/of.h>
178c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
188c2ecf20Sopenharmony_ci#include <linux/of_pci.h>
198c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <asm/mach-ralink/rt3883.h>
228c2ecf20Sopenharmony_ci#include <asm/mach-ralink/ralink_regs.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define RT3883_MEMORY_BASE		0x00000000
258c2ecf20Sopenharmony_ci#define RT3883_MEMORY_SIZE		0x02000000
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_PCICFG		0x00
288c2ecf20Sopenharmony_ci#define   RT3883_PCICFG_P2P_BR_DEVNUM_M 0xf
298c2ecf20Sopenharmony_ci#define   RT3883_PCICFG_P2P_BR_DEVNUM_S 16
308c2ecf20Sopenharmony_ci#define   RT3883_PCICFG_PCIRST		BIT(1)
318c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_PCIRAW		0x04
328c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_PCIINT		0x08
338c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_PCIENA		0x0c
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_CFGADDR		0x20
368c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_CFGDATA		0x24
378c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_MEMBASE		0x28
388c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_IOBASE		0x2c
398c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_ARBCTL		0x80
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_BASE(_x)		(0x1000 + (_x) * 0x1000)
428c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_BAR0SETUP(_x)	(RT3883_PCI_REG_BASE((_x)) + 0x10)
438c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_IMBASEBAR0(_x)	(RT3883_PCI_REG_BASE((_x)) + 0x18)
448c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_ID(_x)		(RT3883_PCI_REG_BASE((_x)) + 0x30)
458c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_CLASS(_x)	(RT3883_PCI_REG_BASE((_x)) + 0x34)
468c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_SUBID(_x)	(RT3883_PCI_REG_BASE((_x)) + 0x38)
478c2ecf20Sopenharmony_ci#define RT3883_PCI_REG_STATUS(_x)	(RT3883_PCI_REG_BASE((_x)) + 0x50)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define RT3883_PCI_MODE_NONE	0
508c2ecf20Sopenharmony_ci#define RT3883_PCI_MODE_PCI	BIT(0)
518c2ecf20Sopenharmony_ci#define RT3883_PCI_MODE_PCIE	BIT(1)
528c2ecf20Sopenharmony_ci#define RT3883_PCI_MODE_BOTH	(RT3883_PCI_MODE_PCI | RT3883_PCI_MODE_PCIE)
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define RT3883_PCI_IRQ_COUNT	32
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define RT3883_P2P_BR_DEVNUM	1
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistruct rt3883_pci_controller {
598c2ecf20Sopenharmony_ci	void __iomem *base;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	struct device_node *intc_of_node;
628c2ecf20Sopenharmony_ci	struct irq_domain *irq_domain;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	struct pci_controller pci_controller;
658c2ecf20Sopenharmony_ci	struct resource io_res;
668c2ecf20Sopenharmony_ci	struct resource mem_res;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	bool pcie_ready;
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic inline struct rt3883_pci_controller *
728c2ecf20Sopenharmony_cipci_bus_to_rt3883_controller(struct pci_bus *bus)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct pci_controller *hose;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	hose = (struct pci_controller *) bus->sysdata;
778c2ecf20Sopenharmony_ci	return container_of(hose, struct rt3883_pci_controller, pci_controller);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic inline u32 rt3883_pci_r32(struct rt3883_pci_controller *rpc,
818c2ecf20Sopenharmony_ci				 unsigned reg)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	return ioread32(rpc->base + reg);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc,
878c2ecf20Sopenharmony_ci				  u32 val, unsigned reg)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	iowrite32(val, rpc->base + reg);
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot,
938c2ecf20Sopenharmony_ci					 unsigned int func, unsigned int where)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	return (bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) |
968c2ecf20Sopenharmony_ci	       0x80000000;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc,
1008c2ecf20Sopenharmony_ci			       unsigned bus, unsigned slot,
1018c2ecf20Sopenharmony_ci			       unsigned func, unsigned reg)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	unsigned long flags;
1048c2ecf20Sopenharmony_ci	u32 address;
1058c2ecf20Sopenharmony_ci	u32 ret;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	address = rt3883_pci_get_cfgaddr(bus, slot, func, reg);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
1108c2ecf20Sopenharmony_ci	ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	return ret;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc,
1168c2ecf20Sopenharmony_ci				 unsigned bus, unsigned slot,
1178c2ecf20Sopenharmony_ci				 unsigned func, unsigned reg, u32 val)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	unsigned long flags;
1208c2ecf20Sopenharmony_ci	u32 address;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	address = rt3883_pci_get_cfgaddr(bus, slot, func, reg);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
1258c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic void rt3883_pci_irq_handler(struct irq_desc *desc)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	struct rt3883_pci_controller *rpc;
1318c2ecf20Sopenharmony_ci	u32 pending;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	rpc = irq_desc_get_handler_data(desc);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) &
1368c2ecf20Sopenharmony_ci		  rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	if (!pending) {
1398c2ecf20Sopenharmony_ci		spurious_interrupt();
1408c2ecf20Sopenharmony_ci		return;
1418c2ecf20Sopenharmony_ci	}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	while (pending) {
1448c2ecf20Sopenharmony_ci		unsigned irq, bit = __ffs(pending);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci		irq = irq_find_mapping(rpc->irq_domain, bit);
1478c2ecf20Sopenharmony_ci		generic_handle_irq(irq);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci		pending &= ~BIT(bit);
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic void rt3883_pci_irq_unmask(struct irq_data *d)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	struct rt3883_pci_controller *rpc;
1568c2ecf20Sopenharmony_ci	u32 t;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	rpc = irq_data_get_irq_chip_data(d);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
1618c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, t | BIT(d->hwirq), RT3883_PCI_REG_PCIENA);
1628c2ecf20Sopenharmony_ci	/* flush write */
1638c2ecf20Sopenharmony_ci	rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic void rt3883_pci_irq_mask(struct irq_data *d)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct rt3883_pci_controller *rpc;
1698c2ecf20Sopenharmony_ci	u32 t;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	rpc = irq_data_get_irq_chip_data(d);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
1748c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, t & ~BIT(d->hwirq), RT3883_PCI_REG_PCIENA);
1758c2ecf20Sopenharmony_ci	/* flush write */
1768c2ecf20Sopenharmony_ci	rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic struct irq_chip rt3883_pci_irq_chip = {
1808c2ecf20Sopenharmony_ci	.name		= "RT3883 PCI",
1818c2ecf20Sopenharmony_ci	.irq_mask	= rt3883_pci_irq_mask,
1828c2ecf20Sopenharmony_ci	.irq_unmask	= rt3883_pci_irq_unmask,
1838c2ecf20Sopenharmony_ci	.irq_mask_ack	= rt3883_pci_irq_mask,
1848c2ecf20Sopenharmony_ci};
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistatic int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq,
1878c2ecf20Sopenharmony_ci			      irq_hw_number_t hw)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	irq_set_chip_and_handler(irq, &rt3883_pci_irq_chip, handle_level_irq);
1908c2ecf20Sopenharmony_ci	irq_set_chip_data(irq, d->host_data);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	return 0;
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cistatic const struct irq_domain_ops rt3883_pci_irq_domain_ops = {
1968c2ecf20Sopenharmony_ci	.map = rt3883_pci_irq_map,
1978c2ecf20Sopenharmony_ci	.xlate = irq_domain_xlate_onecell,
1988c2ecf20Sopenharmony_ci};
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic int rt3883_pci_irq_init(struct device *dev,
2018c2ecf20Sopenharmony_ci			       struct rt3883_pci_controller *rpc)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	int irq;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	irq = irq_of_parse_and_map(rpc->intc_of_node, 0);
2068c2ecf20Sopenharmony_ci	if (irq == 0) {
2078c2ecf20Sopenharmony_ci		dev_err(dev, "%pOF has no IRQ", rpc->intc_of_node);
2088c2ecf20Sopenharmony_ci		return -EINVAL;
2098c2ecf20Sopenharmony_ci	}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/* disable all interrupts */
2128c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	rpc->irq_domain =
2158c2ecf20Sopenharmony_ci		irq_domain_add_linear(rpc->intc_of_node, RT3883_PCI_IRQ_COUNT,
2168c2ecf20Sopenharmony_ci				      &rt3883_pci_irq_domain_ops,
2178c2ecf20Sopenharmony_ci				      rpc);
2188c2ecf20Sopenharmony_ci	if (!rpc->irq_domain) {
2198c2ecf20Sopenharmony_ci		dev_err(dev, "unable to add IRQ domain\n");
2208c2ecf20Sopenharmony_ci		return -ENODEV;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	irq_set_chained_handler_and_data(irq, rt3883_pci_irq_handler, rpc);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	return 0;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn,
2298c2ecf20Sopenharmony_ci				  int where, int size, u32 *val)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	struct rt3883_pci_controller *rpc;
2328c2ecf20Sopenharmony_ci	unsigned long flags;
2338c2ecf20Sopenharmony_ci	u32 address;
2348c2ecf20Sopenharmony_ci	u32 data;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	rpc = pci_bus_to_rt3883_controller(bus);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	if (!rpc->pcie_ready && bus->number == 1)
2398c2ecf20Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
2428c2ecf20Sopenharmony_ci					 PCI_FUNC(devfn), where);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
2458c2ecf20Sopenharmony_ci	data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	switch (size) {
2488c2ecf20Sopenharmony_ci	case 1:
2498c2ecf20Sopenharmony_ci		*val = (data >> ((where & 3) << 3)) & 0xff;
2508c2ecf20Sopenharmony_ci		break;
2518c2ecf20Sopenharmony_ci	case 2:
2528c2ecf20Sopenharmony_ci		*val = (data >> ((where & 3) << 3)) & 0xffff;
2538c2ecf20Sopenharmony_ci		break;
2548c2ecf20Sopenharmony_ci	case 4:
2558c2ecf20Sopenharmony_ci		*val = data;
2568c2ecf20Sopenharmony_ci		break;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return PCIBIOS_SUCCESSFUL;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn,
2638c2ecf20Sopenharmony_ci				   int where, int size, u32 val)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	struct rt3883_pci_controller *rpc;
2668c2ecf20Sopenharmony_ci	unsigned long flags;
2678c2ecf20Sopenharmony_ci	u32 address;
2688c2ecf20Sopenharmony_ci	u32 data;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	rpc = pci_bus_to_rt3883_controller(bus);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	if (!rpc->pcie_ready && bus->number == 1)
2738c2ecf20Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
2768c2ecf20Sopenharmony_ci					 PCI_FUNC(devfn), where);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
2798c2ecf20Sopenharmony_ci	data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	switch (size) {
2828c2ecf20Sopenharmony_ci	case 1:
2838c2ecf20Sopenharmony_ci		data = (data & ~(0xff << ((where & 3) << 3))) |
2848c2ecf20Sopenharmony_ci		       (val << ((where & 3) << 3));
2858c2ecf20Sopenharmony_ci		break;
2868c2ecf20Sopenharmony_ci	case 2:
2878c2ecf20Sopenharmony_ci		data = (data & ~(0xffff << ((where & 3) << 3))) |
2888c2ecf20Sopenharmony_ci		       (val << ((where & 3) << 3));
2898c2ecf20Sopenharmony_ci		break;
2908c2ecf20Sopenharmony_ci	case 4:
2918c2ecf20Sopenharmony_ci		data = val;
2928c2ecf20Sopenharmony_ci		break;
2938c2ecf20Sopenharmony_ci	}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	return PCIBIOS_SUCCESSFUL;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic struct pci_ops rt3883_pci_ops = {
3018c2ecf20Sopenharmony_ci	.read	= rt3883_pci_config_read,
3028c2ecf20Sopenharmony_ci	.write	= rt3883_pci_config_write,
3038c2ecf20Sopenharmony_ci};
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic void rt3883_pci_preinit(struct rt3883_pci_controller *rpc, unsigned mode)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	u32 syscfg1;
3088c2ecf20Sopenharmony_ci	u32 rstctrl;
3098c2ecf20Sopenharmony_ci	u32 clkcfg1;
3108c2ecf20Sopenharmony_ci	u32 t;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	rstctrl = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
3138c2ecf20Sopenharmony_ci	syscfg1 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1);
3148c2ecf20Sopenharmony_ci	clkcfg1 = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	if (mode & RT3883_PCI_MODE_PCIE) {
3178c2ecf20Sopenharmony_ci		rstctrl |= RT3883_RSTCTRL_PCIE;
3188c2ecf20Sopenharmony_ci		rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci		/* setup PCI PAD drive mode */
3218c2ecf20Sopenharmony_ci		syscfg1 &= ~(0x30);
3228c2ecf20Sopenharmony_ci		syscfg1 |= (2 << 4);
3238c2ecf20Sopenharmony_ci		rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci		t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0);
3268c2ecf20Sopenharmony_ci		t &= ~BIT(31);
3278c2ecf20Sopenharmony_ci		rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci		t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1);
3308c2ecf20Sopenharmony_ci		t &= 0x80ffffff;
3318c2ecf20Sopenharmony_ci		rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1);
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci		t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1);
3348c2ecf20Sopenharmony_ci		t |= 0xa << 24;
3358c2ecf20Sopenharmony_ci		rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci		t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0);
3388c2ecf20Sopenharmony_ci		t |= BIT(31);
3398c2ecf20Sopenharmony_ci		rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci		msleep(50);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		rstctrl &= ~RT3883_RSTCTRL_PCIE;
3448c2ecf20Sopenharmony_ci		rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL);
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	syscfg1 |= (RT3883_SYSCFG1_PCIE_RC_MODE | RT3883_SYSCFG1_PCI_HOST_MODE);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | RT3883_CLKCFG1_PCIE_CLK_EN);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	if (mode & RT3883_PCI_MODE_PCI) {
3528c2ecf20Sopenharmony_ci		clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN;
3538c2ecf20Sopenharmony_ci		rstctrl &= ~RT3883_RSTCTRL_PCI;
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	if (mode & RT3883_PCI_MODE_PCIE) {
3578c2ecf20Sopenharmony_ci		clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN;
3588c2ecf20Sopenharmony_ci		rstctrl &= ~RT3883_RSTCTRL_PCIE;
3598c2ecf20Sopenharmony_ci	}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1);
3628c2ecf20Sopenharmony_ci	rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL);
3638c2ecf20Sopenharmony_ci	rt_sysc_w32(clkcfg1, RT3883_SYSC_REG_CLKCFG1);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	msleep(500);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	/*
3688c2ecf20Sopenharmony_ci	 * setup the device number of the P2P bridge
3698c2ecf20Sopenharmony_ci	 * and de-assert the reset line
3708c2ecf20Sopenharmony_ci	 */
3718c2ecf20Sopenharmony_ci	t = (RT3883_P2P_BR_DEVNUM << RT3883_PCICFG_P2P_BR_DEVNUM_S);
3728c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, t, RT3883_PCI_REG_PCICFG);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	/* flush write */
3758c2ecf20Sopenharmony_ci	rt3883_pci_r32(rpc, RT3883_PCI_REG_PCICFG);
3768c2ecf20Sopenharmony_ci	msleep(500);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	if (mode & RT3883_PCI_MODE_PCIE) {
3798c2ecf20Sopenharmony_ci		msleep(500);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		t = rt3883_pci_r32(rpc, RT3883_PCI_REG_STATUS(1));
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci		rpc->pcie_ready = t & BIT(0);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci		if (!rpc->pcie_ready) {
3868c2ecf20Sopenharmony_ci			/* reset the PCIe block */
3878c2ecf20Sopenharmony_ci			t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
3888c2ecf20Sopenharmony_ci			t |= RT3883_RSTCTRL_PCIE;
3898c2ecf20Sopenharmony_ci			rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
3908c2ecf20Sopenharmony_ci			t &= ~RT3883_RSTCTRL_PCIE;
3918c2ecf20Sopenharmony_ci			rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci			/* turn off PCIe clock */
3948c2ecf20Sopenharmony_ci			t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1);
3958c2ecf20Sopenharmony_ci			t &= ~RT3883_CLKCFG1_PCIE_CLK_EN;
3968c2ecf20Sopenharmony_ci			rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci			t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0);
3998c2ecf20Sopenharmony_ci			t &= ~0xf000c080;
4008c2ecf20Sopenharmony_ci			rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0);
4018c2ecf20Sopenharmony_ci		}
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	/* enable PCI arbiter */
4058c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x79, RT3883_PCI_REG_ARBCTL);
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic int rt3883_pci_probe(struct platform_device *pdev)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct rt3883_pci_controller *rpc;
4118c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
4128c2ecf20Sopenharmony_ci	struct device_node *np = dev->of_node;
4138c2ecf20Sopenharmony_ci	struct resource *res;
4148c2ecf20Sopenharmony_ci	struct device_node *child;
4158c2ecf20Sopenharmony_ci	u32 val;
4168c2ecf20Sopenharmony_ci	int err;
4178c2ecf20Sopenharmony_ci	int mode;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL);
4208c2ecf20Sopenharmony_ci	if (!rpc)
4218c2ecf20Sopenharmony_ci		return -ENOMEM;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4248c2ecf20Sopenharmony_ci	rpc->base = devm_ioremap_resource(dev, res);
4258c2ecf20Sopenharmony_ci	if (IS_ERR(rpc->base))
4268c2ecf20Sopenharmony_ci		return PTR_ERR(rpc->base);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* find the interrupt controller child node */
4298c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
4308c2ecf20Sopenharmony_ci		if (of_get_property(child, "interrupt-controller", NULL)) {
4318c2ecf20Sopenharmony_ci			rpc->intc_of_node = child;
4328c2ecf20Sopenharmony_ci			break;
4338c2ecf20Sopenharmony_ci		}
4348c2ecf20Sopenharmony_ci	}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	if (!rpc->intc_of_node) {
4378c2ecf20Sopenharmony_ci		dev_err(dev, "%pOF has no %s child node",
4388c2ecf20Sopenharmony_ci			rpc->intc_of_node,
4398c2ecf20Sopenharmony_ci			"interrupt controller");
4408c2ecf20Sopenharmony_ci		return -EINVAL;
4418c2ecf20Sopenharmony_ci	}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	/* find the PCI host bridge child node */
4448c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
4458c2ecf20Sopenharmony_ci		if (of_node_is_type(child, "pci")) {
4468c2ecf20Sopenharmony_ci			rpc->pci_controller.of_node = child;
4478c2ecf20Sopenharmony_ci			break;
4488c2ecf20Sopenharmony_ci		}
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (!rpc->pci_controller.of_node) {
4528c2ecf20Sopenharmony_ci		dev_err(dev, "%pOF has no %s child node",
4538c2ecf20Sopenharmony_ci			rpc->intc_of_node,
4548c2ecf20Sopenharmony_ci			"PCI host bridge");
4558c2ecf20Sopenharmony_ci		err = -EINVAL;
4568c2ecf20Sopenharmony_ci		goto err_put_intc_node;
4578c2ecf20Sopenharmony_ci	}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	mode = RT3883_PCI_MODE_NONE;
4608c2ecf20Sopenharmony_ci	for_each_available_child_of_node(rpc->pci_controller.of_node, child) {
4618c2ecf20Sopenharmony_ci		int devfn;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci		if (!of_node_is_type(child, "pci"))
4648c2ecf20Sopenharmony_ci			continue;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci		devfn = of_pci_get_devfn(child);
4678c2ecf20Sopenharmony_ci		if (devfn < 0)
4688c2ecf20Sopenharmony_ci			continue;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci		switch (PCI_SLOT(devfn)) {
4718c2ecf20Sopenharmony_ci		case 1:
4728c2ecf20Sopenharmony_ci			mode |= RT3883_PCI_MODE_PCIE;
4738c2ecf20Sopenharmony_ci			break;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		case 17:
4768c2ecf20Sopenharmony_ci		case 18:
4778c2ecf20Sopenharmony_ci			mode |= RT3883_PCI_MODE_PCI;
4788c2ecf20Sopenharmony_ci			break;
4798c2ecf20Sopenharmony_ci		}
4808c2ecf20Sopenharmony_ci	}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	if (mode == RT3883_PCI_MODE_NONE) {
4838c2ecf20Sopenharmony_ci		dev_err(dev, "unable to determine PCI mode\n");
4848c2ecf20Sopenharmony_ci		err = -EINVAL;
4858c2ecf20Sopenharmony_ci		goto err_put_hb_node;
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	dev_info(dev, "mode:%s%s\n",
4898c2ecf20Sopenharmony_ci		 (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "",
4908c2ecf20Sopenharmony_ci		 (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : "");
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	rt3883_pci_preinit(rpc, mode);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	rpc->pci_controller.pci_ops = &rt3883_pci_ops;
4958c2ecf20Sopenharmony_ci	rpc->pci_controller.io_resource = &rpc->io_res;
4968c2ecf20Sopenharmony_ci	rpc->pci_controller.mem_resource = &rpc->mem_res;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	/* Load PCI I/O and memory resources from DT */
4998c2ecf20Sopenharmony_ci	pci_load_of_ranges(&rpc->pci_controller,
5008c2ecf20Sopenharmony_ci			   rpc->pci_controller.of_node);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, rpc->mem_res.start, RT3883_PCI_REG_MEMBASE);
5038c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, rpc->io_res.start, RT3883_PCI_REG_IOBASE);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	ioport_resource.start = rpc->io_res.start;
5068c2ecf20Sopenharmony_ci	ioport_resource.end = rpc->io_res.end;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* PCI */
5098c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(0));
5108c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(0));
5118c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(0));
5128c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x00800001, RT3883_PCI_REG_CLASS(0));
5138c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(0));
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/* PCIe */
5168c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(1));
5178c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(1));
5188c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(1));
5198c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x06040001, RT3883_PCI_REG_CLASS(1));
5208c2ecf20Sopenharmony_ci	rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(1));
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	err = rt3883_pci_irq_init(dev, rpc);
5238c2ecf20Sopenharmony_ci	if (err)
5248c2ecf20Sopenharmony_ci		goto err_put_hb_node;
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	/* PCIe */
5278c2ecf20Sopenharmony_ci	val = rt3883_pci_read_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND);
5288c2ecf20Sopenharmony_ci	val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
5298c2ecf20Sopenharmony_ci	rt3883_pci_write_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND, val);
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	/* PCI */
5328c2ecf20Sopenharmony_ci	val = rt3883_pci_read_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND);
5338c2ecf20Sopenharmony_ci	val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
5348c2ecf20Sopenharmony_ci	rt3883_pci_write_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND, val);
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	if (mode == RT3883_PCI_MODE_PCIE) {
5378c2ecf20Sopenharmony_ci		rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(0));
5388c2ecf20Sopenharmony_ci		rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(1));
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0,
5418c2ecf20Sopenharmony_ci				       PCI_BASE_ADDRESS_0,
5428c2ecf20Sopenharmony_ci				       RT3883_MEMORY_BASE);
5438c2ecf20Sopenharmony_ci		/* flush write */
5448c2ecf20Sopenharmony_ci		rt3883_pci_read_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0,
5458c2ecf20Sopenharmony_ci				      PCI_BASE_ADDRESS_0);
5468c2ecf20Sopenharmony_ci	} else {
5478c2ecf20Sopenharmony_ci		rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0,
5488c2ecf20Sopenharmony_ci				       PCI_IO_BASE, 0x00000101);
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	register_pci_controller(&rpc->pci_controller);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	return 0;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cierr_put_hb_node:
5568c2ecf20Sopenharmony_ci	of_node_put(rpc->pci_controller.of_node);
5578c2ecf20Sopenharmony_cierr_put_intc_node:
5588c2ecf20Sopenharmony_ci	of_node_put(rpc->intc_of_node);
5598c2ecf20Sopenharmony_ci	return err;
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ciint pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	return of_irq_parse_and_map_pci(dev, slot, pin);
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ciint pcibios_plat_dev_init(struct pci_dev *dev)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	return 0;
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_cistatic const struct of_device_id rt3883_pci_ids[] = {
5738c2ecf20Sopenharmony_ci	{ .compatible = "ralink,rt3883-pci" },
5748c2ecf20Sopenharmony_ci	{},
5758c2ecf20Sopenharmony_ci};
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_cistatic struct platform_driver rt3883_pci_driver = {
5788c2ecf20Sopenharmony_ci	.probe = rt3883_pci_probe,
5798c2ecf20Sopenharmony_ci	.driver = {
5808c2ecf20Sopenharmony_ci		.name = "rt3883-pci",
5818c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(rt3883_pci_ids),
5828c2ecf20Sopenharmony_ci	},
5838c2ecf20Sopenharmony_ci};
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_cistatic int __init rt3883_pci_init(void)
5868c2ecf20Sopenharmony_ci{
5878c2ecf20Sopenharmony_ci	return platform_driver_register(&rt3883_pci_driver);
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_cipostcore_initcall(rt3883_pci_init);
591