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