18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * PCIe host controller driver for Mobiveil PCIe Host controller 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2018 Mobiveil Inc. 68c2ecf20Sopenharmony_ci * Copyright 2019 NXP 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Author: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in> 98c2ecf20Sopenharmony_ci * Hou Zhiqiang <Zhiqiang.Hou@nxp.com> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifndef _PCIE_MOBIVEIL_H 138c2ecf20Sopenharmony_ci#define _PCIE_MOBIVEIL_H 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/pci.h> 168c2ecf20Sopenharmony_ci#include <linux/irq.h> 178c2ecf20Sopenharmony_ci#include <linux/msi.h> 188c2ecf20Sopenharmony_ci#include "../../pci.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* register offsets and bit positions */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* 238c2ecf20Sopenharmony_ci * translation tables are grouped into windows, each window registers are 248c2ecf20Sopenharmony_ci * grouped into blocks of 4 or 16 registers each 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci#define PAB_REG_BLOCK_SIZE 16 278c2ecf20Sopenharmony_ci#define PAB_EXT_REG_BLOCK_SIZE 4 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define PAB_REG_ADDR(offset, win) \ 308c2ecf20Sopenharmony_ci (offset + (win * PAB_REG_BLOCK_SIZE)) 318c2ecf20Sopenharmony_ci#define PAB_EXT_REG_ADDR(offset, win) \ 328c2ecf20Sopenharmony_ci (offset + (win * PAB_EXT_REG_BLOCK_SIZE)) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define LTSSM_STATUS 0x0404 358c2ecf20Sopenharmony_ci#define LTSSM_STATUS_L0_MASK 0x3f 368c2ecf20Sopenharmony_ci#define LTSSM_STATUS_L0 0x2d 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define PAB_CTRL 0x0808 398c2ecf20Sopenharmony_ci#define AMBA_PIO_ENABLE_SHIFT 0 408c2ecf20Sopenharmony_ci#define PEX_PIO_ENABLE_SHIFT 1 418c2ecf20Sopenharmony_ci#define PAGE_SEL_SHIFT 13 428c2ecf20Sopenharmony_ci#define PAGE_SEL_MASK 0x3f 438c2ecf20Sopenharmony_ci#define PAGE_LO_MASK 0x3ff 448c2ecf20Sopenharmony_ci#define PAGE_SEL_OFFSET_SHIFT 10 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define PAB_ACTIVITY_STAT 0x81c 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define PAB_AXI_PIO_CTRL 0x0840 498c2ecf20Sopenharmony_ci#define APIO_EN_MASK 0xf 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define PAB_PEX_PIO_CTRL 0x08c0 528c2ecf20Sopenharmony_ci#define PIO_ENABLE_SHIFT 0 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define PAB_INTP_AMBA_MISC_ENB 0x0b0c 558c2ecf20Sopenharmony_ci#define PAB_INTP_AMBA_MISC_STAT 0x0b1c 568c2ecf20Sopenharmony_ci#define PAB_INTP_RESET BIT(1) 578c2ecf20Sopenharmony_ci#define PAB_INTP_MSI BIT(3) 588c2ecf20Sopenharmony_ci#define PAB_INTP_INTA BIT(5) 598c2ecf20Sopenharmony_ci#define PAB_INTP_INTB BIT(6) 608c2ecf20Sopenharmony_ci#define PAB_INTP_INTC BIT(7) 618c2ecf20Sopenharmony_ci#define PAB_INTP_INTD BIT(8) 628c2ecf20Sopenharmony_ci#define PAB_INTP_PCIE_UE BIT(9) 638c2ecf20Sopenharmony_ci#define PAB_INTP_IE_PMREDI BIT(29) 648c2ecf20Sopenharmony_ci#define PAB_INTP_IE_EC BIT(30) 658c2ecf20Sopenharmony_ci#define PAB_INTP_MSI_MASK PAB_INTP_MSI 668c2ecf20Sopenharmony_ci#define PAB_INTP_INTX_MASK (PAB_INTP_INTA | PAB_INTP_INTB |\ 678c2ecf20Sopenharmony_ci PAB_INTP_INTC | PAB_INTP_INTD) 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win) 708c2ecf20Sopenharmony_ci#define WIN_ENABLE_SHIFT 0 718c2ecf20Sopenharmony_ci#define WIN_TYPE_SHIFT 1 728c2ecf20Sopenharmony_ci#define WIN_TYPE_MASK 0x3 738c2ecf20Sopenharmony_ci#define WIN_SIZE_MASK 0xfffffc00 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define PAB_EXT_AXI_AMAP_SIZE(win) PAB_EXT_REG_ADDR(0xbaf0, win) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define PAB_EXT_AXI_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0x80a0, win) 788c2ecf20Sopenharmony_ci#define PAB_AXI_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x0ba4, win) 798c2ecf20Sopenharmony_ci#define AXI_WINDOW_ALIGN_MASK 3 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define PAB_AXI_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x0ba8, win) 828c2ecf20Sopenharmony_ci#define PAB_BUS_SHIFT 24 838c2ecf20Sopenharmony_ci#define PAB_DEVICE_SHIFT 19 848c2ecf20Sopenharmony_ci#define PAB_FUNCTION_SHIFT 16 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define PAB_AXI_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x0bac, win) 878c2ecf20Sopenharmony_ci#define PAB_INTP_AXI_PIO_CLASS 0x474 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define PAB_PEX_AMAP_CTRL(win) PAB_REG_ADDR(0x4ba0, win) 908c2ecf20Sopenharmony_ci#define AMAP_CTRL_EN_SHIFT 0 918c2ecf20Sopenharmony_ci#define AMAP_CTRL_TYPE_SHIFT 1 928c2ecf20Sopenharmony_ci#define AMAP_CTRL_TYPE_MASK 3 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#define PAB_EXT_PEX_AMAP_SIZEN(win) PAB_EXT_REG_ADDR(0xbef0, win) 958c2ecf20Sopenharmony_ci#define PAB_EXT_PEX_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0xb4a0, win) 968c2ecf20Sopenharmony_ci#define PAB_PEX_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x4ba4, win) 978c2ecf20Sopenharmony_ci#define PAB_PEX_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x4ba8, win) 988c2ecf20Sopenharmony_ci#define PAB_PEX_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x4bac, win) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* starting offset of INTX bits in status register */ 1018c2ecf20Sopenharmony_ci#define PAB_INTX_START 5 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* supported number of MSI interrupts */ 1048c2ecf20Sopenharmony_ci#define PCI_NUM_MSI 16 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* MSI registers */ 1078c2ecf20Sopenharmony_ci#define MSI_BASE_LO_OFFSET 0x04 1088c2ecf20Sopenharmony_ci#define MSI_BASE_HI_OFFSET 0x08 1098c2ecf20Sopenharmony_ci#define MSI_SIZE_OFFSET 0x0c 1108c2ecf20Sopenharmony_ci#define MSI_ENABLE_OFFSET 0x14 1118c2ecf20Sopenharmony_ci#define MSI_STATUS_OFFSET 0x18 1128c2ecf20Sopenharmony_ci#define MSI_DATA_OFFSET 0x20 1138c2ecf20Sopenharmony_ci#define MSI_ADDR_L_OFFSET 0x24 1148c2ecf20Sopenharmony_ci#define MSI_ADDR_H_OFFSET 0x28 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* outbound and inbound window definitions */ 1178c2ecf20Sopenharmony_ci#define WIN_NUM_0 0 1188c2ecf20Sopenharmony_ci#define WIN_NUM_1 1 1198c2ecf20Sopenharmony_ci#define CFG_WINDOW_TYPE 0 1208c2ecf20Sopenharmony_ci#define IO_WINDOW_TYPE 1 1218c2ecf20Sopenharmony_ci#define MEM_WINDOW_TYPE 2 1228c2ecf20Sopenharmony_ci#define IB_WIN_SIZE ((u64)256 * 1024 * 1024 * 1024) 1238c2ecf20Sopenharmony_ci#define MAX_PIO_WINDOWS 8 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* Parameters for the waiting for link up routine */ 1268c2ecf20Sopenharmony_ci#define LINK_WAIT_MAX_RETRIES 10 1278c2ecf20Sopenharmony_ci#define LINK_WAIT_MIN 90000 1288c2ecf20Sopenharmony_ci#define LINK_WAIT_MAX 100000 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci#define PAGED_ADDR_BNDRY 0xc00 1318c2ecf20Sopenharmony_ci#define OFFSET_TO_PAGE_ADDR(off) \ 1328c2ecf20Sopenharmony_ci ((off & PAGE_LO_MASK) | PAGED_ADDR_BNDRY) 1338c2ecf20Sopenharmony_ci#define OFFSET_TO_PAGE_IDX(off) \ 1348c2ecf20Sopenharmony_ci ((off >> PAGE_SEL_OFFSET_SHIFT) & PAGE_SEL_MASK) 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistruct mobiveil_msi { /* MSI information */ 1378c2ecf20Sopenharmony_ci struct mutex lock; /* protect bitmap variable */ 1388c2ecf20Sopenharmony_ci struct irq_domain *msi_domain; 1398c2ecf20Sopenharmony_ci struct irq_domain *dev_domain; 1408c2ecf20Sopenharmony_ci phys_addr_t msi_pages_phys; 1418c2ecf20Sopenharmony_ci int num_of_vectors; 1428c2ecf20Sopenharmony_ci DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI); 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistruct mobiveil_pcie; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistruct mobiveil_rp_ops { 1488c2ecf20Sopenharmony_ci int (*interrupt_init)(struct mobiveil_pcie *pcie); 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistruct mobiveil_root_port { 1528c2ecf20Sopenharmony_ci void __iomem *config_axi_slave_base; /* endpoint config base */ 1538c2ecf20Sopenharmony_ci struct resource *ob_io_res; 1548c2ecf20Sopenharmony_ci struct mobiveil_rp_ops *ops; 1558c2ecf20Sopenharmony_ci int irq; 1568c2ecf20Sopenharmony_ci raw_spinlock_t intx_mask_lock; 1578c2ecf20Sopenharmony_ci struct irq_domain *intx_domain; 1588c2ecf20Sopenharmony_ci struct mobiveil_msi msi; 1598c2ecf20Sopenharmony_ci struct pci_host_bridge *bridge; 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistruct mobiveil_pab_ops { 1638c2ecf20Sopenharmony_ci int (*link_up)(struct mobiveil_pcie *pcie); 1648c2ecf20Sopenharmony_ci}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistruct mobiveil_pcie { 1678c2ecf20Sopenharmony_ci struct platform_device *pdev; 1688c2ecf20Sopenharmony_ci void __iomem *csr_axi_slave_base; /* root port config base */ 1698c2ecf20Sopenharmony_ci void __iomem *apb_csr_base; /* MSI register base */ 1708c2ecf20Sopenharmony_ci phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */ 1718c2ecf20Sopenharmony_ci int apio_wins; 1728c2ecf20Sopenharmony_ci int ppio_wins; 1738c2ecf20Sopenharmony_ci int ob_wins_configured; /* configured outbound windows */ 1748c2ecf20Sopenharmony_ci int ib_wins_configured; /* configured inbound windows */ 1758c2ecf20Sopenharmony_ci const struct mobiveil_pab_ops *ops; 1768c2ecf20Sopenharmony_ci struct mobiveil_root_port rp; 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ciint mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie); 1808c2ecf20Sopenharmony_ciint mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit); 1818c2ecf20Sopenharmony_cibool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie); 1828c2ecf20Sopenharmony_ciint mobiveil_bringup_link(struct mobiveil_pcie *pcie); 1838c2ecf20Sopenharmony_civoid program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr, 1848c2ecf20Sopenharmony_ci u64 pci_addr, u32 type, u64 size); 1858c2ecf20Sopenharmony_civoid program_ib_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr, 1868c2ecf20Sopenharmony_ci u64 pci_addr, u32 type, u64 size); 1878c2ecf20Sopenharmony_ciu32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size); 1888c2ecf20Sopenharmony_civoid mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off, 1898c2ecf20Sopenharmony_ci size_t size); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic inline u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci return mobiveil_csr_read(pcie, off, 0x4); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic inline u16 mobiveil_csr_readw(struct mobiveil_pcie *pcie, u32 off) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci return mobiveil_csr_read(pcie, off, 0x2); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic inline u8 mobiveil_csr_readb(struct mobiveil_pcie *pcie, u32 off) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci return mobiveil_csr_read(pcie, off, 0x1); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val, 2088c2ecf20Sopenharmony_ci u32 off) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci mobiveil_csr_write(pcie, val, off, 0x4); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic inline void mobiveil_csr_writew(struct mobiveil_pcie *pcie, u16 val, 2148c2ecf20Sopenharmony_ci u32 off) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci mobiveil_csr_write(pcie, val, off, 0x2); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic inline void mobiveil_csr_writeb(struct mobiveil_pcie *pcie, u8 val, 2208c2ecf20Sopenharmony_ci u32 off) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci mobiveil_csr_write(pcie, val, off, 0x1); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci#endif /* _PCIE_MOBIVEIL_H */ 226