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