#include <linux/reset.h>
#include <linux/regmap.h>
-#define PCIE_CLIENT_BASE 0x0
-#define PCIE_RC_CONFIG_NORMAL_BASE 0x800000
-#define PCIE_RC_CONFIG_BASE 0xa00000
-#define PCIE_RC_CONFIG_LCSR 0xd0
-#define PCIE_RC_CONFIG_LCSR_LBMIE BIT(10)
-#define PCIE_RC_CONFIG_LCSR_LABIE BIT(11)
-#define PCIE_RC_CONFIG_LCSR_LBMS BIT(30)
-#define PCIE_RC_CONFIG_LCSR_LAMS BIT(31)
-#define PCIE_CORE_CTRL_MGMT_BASE 0x900000
-#define PCIE_CORE_AXI_CONF_BASE 0xc00000
-#define PCIE_CORE_AXI_INBOUND_BASE 0xc00800
-#define PCIE_CLIENT_BASIC_STATUS1 0x48
-#define PCIE_CLIENT_INT_MASK 0x4c
-#define PCIE_CLIENT_INT_STATUS 0x50
-#define PCIE_CLIENT_INT_LEGACY_DONE BIT(15)
-#define PCIE_CLIENT_INT_MSG BIT(14)
-#define PCIE_CLIENT_INT_HOT_RST BIT(13)
-#define PCIE_CLIENT_INT_DPA BIT(12)
-#define PCIE_CLIENT_INT_FATAL_ERR BIT(11)
-#define PCIE_CLIENT_INT_NFATAL_ERR BIT(10)
-#define PCIE_CLIENT_INT_CORR_ERR BIT(9)
-#define PCIE_CLIENT_INT_INTD BIT(8)
-#define PCIE_CLIENT_INT_INTC BIT(7)
-#define PCIE_CLIENT_INT_INTB BIT(6)
-#define PCIE_CLIENT_INT_INTA BIT(5)
-#define PCIE_CLIENT_INT_LOCAL BIT(4)
-#define PCIE_CLIENT_INT_UDMA BIT(3)
-#define PCIE_CLIENT_INT_PHY BIT(2)
-#define PCIE_CLIENT_INT_HOT_PLUG BIT(1)
-#define PCIE_CLIENT_INT_PWR_STCG BIT(0)
-#define PCIE_RC_CONFIG_RID_CCR 0x8
-#define PCIE_RC_CONFIG_LCS 0xd0
-#define PCIE_RC_BAR_CONF 0x300
-#define PCIE_CORE_OB_REGION_ADDR1 0x4
-#define PCIE_CORE_OB_REGION_DESC0 0x8
-#define PCIE_CORE_OB_REGION_DESC1 0xc
-#define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f
-#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00
-#define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f
-#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00
-#define PCIE_RP_IB_ADDR_TRANS 0x4
-#define PCIE_CORE_INT_MASK 0x900210
-#define PCIE_CORE_INT_STATUS 0x90020c
-#define PCIE_CORE_INT_PRFPE BIT(0)
-#define PCIE_CORE_INT_CRFPE BIT(1)
-#define PCIE_CORE_INT_RRPE BIT(2)
-#define PCIE_CORE_INT_PRFO BIT(3)
-#define PCIE_CORE_INT_CRFO BIT(4)
-#define PCIE_CORE_INT_RT BIT(5)
-#define PCIE_CORE_INT_RTR BIT(6)
-#define PCIE_CORE_INT_PE BIT(7)
-#define PCIE_CORE_INT_MTR BIT(8)
-#define PCIE_CORE_INT_UCR BIT(9)
-#define PCIE_CORE_INT_FCE BIT(10)
-#define PCIE_CORE_INT_CT BIT(11)
-#define PCIE_CORE_INT_UTC BIT(18)
-#define PCIE_CORE_INT_MMVC BIT(19)
+/*
+ * The upper 16 bits of PCIE_CLIENT_CONFIG are a write mask for the lower 16
+ * bits. This allows atomic updates of the register without locking.
+ */
+#define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val))
+#define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val)
+
+#define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4)
+
+#define PCIE_CLIENT_BASE 0x0
+#define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00)
+#define PCIE_CLIENT_CONF_ENABLE HIWORD_UPDATE_BIT(0x0001)
+#define PCIE_CLIENT_LINK_TRAIN_ENABLE HIWORD_UPDATE_BIT(0x0002)
+#define PCIE_CLIENT_ARI_ENABLE HIWORD_UPDATE_BIT(0x0008)
+#define PCIE_CLIENT_CONF_LANE_NUM(x) HIWORD_UPDATE(0x0030, ENCODE_LANES(x))
+#define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040)
+#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080)
+#define PCIE_CLIENT_BASIC_STATUS1 (PCIE_CLIENT_BASE + 0x48)
+#define PCIE_CLIENT_LINK_STATUS_UP 0x00300000
+#define PCIE_CLIENT_LINK_STATUS_MASK 0x00300000
+#define PCIE_CLIENT_INT_MASK (PCIE_CLIENT_BASE + 0x4c)
+#define PCIE_CLIENT_INT_STATUS (PCIE_CLIENT_BASE + 0x50)
+#define PCIE_CLIENT_INTR_MASK GENMASK(8, 5)
+#define PCIE_CLIENT_INTR_SHIFT 5
+#define PCIE_CLIENT_INT_LEGACY_DONE BIT(15)
+#define PCIE_CLIENT_INT_MSG BIT(14)
+#define PCIE_CLIENT_INT_HOT_RST BIT(13)
+#define PCIE_CLIENT_INT_DPA BIT(12)
+#define PCIE_CLIENT_INT_FATAL_ERR BIT(11)
+#define PCIE_CLIENT_INT_NFATAL_ERR BIT(10)
+#define PCIE_CLIENT_INT_CORR_ERR BIT(9)
+#define PCIE_CLIENT_INT_INTD BIT(8)
+#define PCIE_CLIENT_INT_INTC BIT(7)
+#define PCIE_CLIENT_INT_INTB BIT(6)
+#define PCIE_CLIENT_INT_INTA BIT(5)
+#define PCIE_CLIENT_INT_LOCAL BIT(4)
+#define PCIE_CLIENT_INT_UDMA BIT(3)
+#define PCIE_CLIENT_INT_PHY BIT(2)
+#define PCIE_CLIENT_INT_HOT_PLUG BIT(1)
+#define PCIE_CLIENT_INT_PWR_STCG BIT(0)
+
+#define PCIE_CLIENT_INT_LEGACY \
+ (PCIE_CLIENT_INT_INTA | PCIE_CLIENT_INT_INTB | \
+ PCIE_CLIENT_INT_INTC | PCIE_CLIENT_INT_INTD)
+
+#define PCIE_CLIENT_INT_CLI \
+ (PCIE_CLIENT_INT_CORR_ERR | PCIE_CLIENT_INT_NFATAL_ERR | \
+ PCIE_CLIENT_INT_FATAL_ERR | PCIE_CLIENT_INT_DPA | \
+ PCIE_CLIENT_INT_HOT_RST | PCIE_CLIENT_INT_MSG | \
+ PCIE_CLIENT_INT_LEGACY_DONE | PCIE_CLIENT_INT_LEGACY | \
+ PCIE_CLIENT_INT_PHY)
+
+#define PCIE_CORE_CTRL_MGMT_BASE 0x900000
+#define PCIE_CORE_CTRL (PCIE_CORE_CTRL_MGMT_BASE + 0x000)
+#define PCIE_CORE_PL_CONF_SPEED_5G 0x00000008
+#define PCIE_CORE_PL_CONF_SPEED_MASK 0x00000018
+#define PCIE_CORE_PL_CONF_LANE_MASK 0x00000006
+#define PCIE_CORE_PL_CONF_LANE_SHIFT 1
+#define PCIE_CORE_INT_STATUS (PCIE_CORE_CTRL_MGMT_BASE + 0x20c)
+#define PCIE_CORE_INT_PRFPE BIT(0)
+#define PCIE_CORE_INT_CRFPE BIT(1)
+#define PCIE_CORE_INT_RRPE BIT(2)
+#define PCIE_CORE_INT_PRFO BIT(3)
+#define PCIE_CORE_INT_CRFO BIT(4)
+#define PCIE_CORE_INT_RT BIT(5)
+#define PCIE_CORE_INT_RTR BIT(6)
+#define PCIE_CORE_INT_PE BIT(7)
+#define PCIE_CORE_INT_MTR BIT(8)
+#define PCIE_CORE_INT_UCR BIT(9)
+#define PCIE_CORE_INT_FCE BIT(10)
+#define PCIE_CORE_INT_CT BIT(11)
+#define PCIE_CORE_INT_UTC BIT(18)
+#define PCIE_CORE_INT_MMVC BIT(19)
+#define PCIE_CORE_INT_MASK (PCIE_CORE_CTRL_MGMT_BASE + 0x210)
+#define PCIE_RC_BAR_CONF (PCIE_CORE_CTRL_MGMT_BASE + 0x300)
+
+#define PCIE_CORE_INT \
+ (PCIE_CORE_INT_PRFPE | PCIE_CORE_INT_CRFPE | \
+ PCIE_CORE_INT_RRPE | PCIE_CORE_INT_CRFO | \
+ PCIE_CORE_INT_RT | PCIE_CORE_INT_RTR | \
+ PCIE_CORE_INT_PE | PCIE_CORE_INT_MTR | \
+ PCIE_CORE_INT_UCR | PCIE_CORE_INT_FCE | \
+ PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \
+ PCIE_CORE_INT_MMVC)
+
+#define PCIE_RC_CONFIG_BASE 0xa00000
+#define PCIE_RC_CONFIG_VENDOR (PCIE_RC_CONFIG_BASE + 0x00)
+#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
+#define PCIE_RC_CONFIG_SCC_SHIFT 16
+#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0)
+#define PCIE_RC_CONFIG_LCS_RETRAIN_LINK BIT(5)
+#define PCIE_RC_CONFIG_LCS_LBMIE BIT(10)
+#define PCIE_RC_CONFIG_LCS_LABIE BIT(11)
+#define PCIE_RC_CONFIG_LCS_LBMS BIT(30)
+#define PCIE_RC_CONFIG_LCS_LAMS BIT(31)
+#define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c)
+
+#define PCIE_CORE_AXI_CONF_BASE 0xc00000
+#define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0)
+#define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f
+#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00
+#define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4)
+#define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8)
+#define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc)
+
+#define PCIE_CORE_AXI_INBOUND_BASE 0xc00800
+#define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0)
+#define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f
+#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00
+#define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4)
/* Size of one AXI Region (not Region 0) */
#define AXI_REGION_SIZE BIT(20)
(PCIE_ECAM_BUS(bus) | PCIE_ECAM_DEV(dev) | \
PCIE_ECAM_FUNC(func) | PCIE_ECAM_REG(reg))
-/*
- * The higher 16-bit of this register is used for write protection
- * only if BIT(x + 16) set to 1 the BIT(x) can be written.
- */
-#define HIWORD_UPDATE(val, mask, shift) \
- ((val) << (shift) | (mask) << ((shift) + 16))
-
#define RC_REGION_0_ADDR_TRANS_H 0x00000000
#define RC_REGION_0_ADDR_TRANS_L 0x00000000
#define RC_REGION_0_PASS_BITS (25 - 1)
-#define RC_REGION_1_ADDR_TRANS_H 0x00000000
-#define RC_REGION_1_ADDR_TRANS_L 0x00400000
-#define RC_REGION_1_PASS_BITS (20 - 1)
#define MAX_AXI_WRAPPER_REGION_NUM 33
-#define PCIE_CORE_LCSR_RETRAIN_LINK BIT(5)
-#define PCIE_CLIENT_CONF_ENABLE BIT(0)
-#define PCIE_CLIENT_CONF_ENABLE_SHIFT 0
-#define PCIE_CLIENT_CONF_ENABLE_MASK 0x1
-#define PCIE_CLIENT_LINK_TRAIN_ENABLE 1
-#define PCIE_CLIENT_LINK_TRAIN_SHIFT 1
-#define PCIE_CLIENT_LINK_TRAIN_MASK 0x1
-#define PCIE_CLIENT_ARI_ENABLE BIT(0)
-#define PCIE_CLIENT_ARI_ENABLE_SHIFT 3
-#define PCIE_CLIENT_ARI_ENABLE_MASK 0x1
-#define PCIE_CLIENT_CONF_LANE_NUM(x) (x / 2)
-#define PCIE_CLIENT_CONF_LANE_NUM_SHIFT 4
-#define PCIE_CLIENT_CONF_LANE_NUM_MASK 0x3
-#define PCIE_CLIENT_MODE_RC BIT(0)
-#define PCIE_CLIENT_MODE_SHIFT 6
-#define PCIE_CLIENT_MODE_MASK 0x1
-#define PCIE_CLIENT_GEN_SEL_2 1
-#define PCIE_CLIENT_GEN_SEL_1 0
-#define PCIE_CLIENT_GEN_SEL_SHIFT 7
-#define PCIE_CLIENT_GEN_SEL_MASK 0x1
-#define PCIE_CLIENT_LINK_STATUS_UP 0x3
-#define PCIE_CLIENT_LINK_STATUS_SHIFT 20
-#define PCIE_CLIENT_LINK_STATUS_MASK 0x3
-#define PCIE_CORE_PL_CONF_SPEED_2_5G 0x0
-#define PCIE_CORE_PL_CONF_SPEED_5G 0x1
-#define PCIE_CORE_PL_CONF_SPEED_8G 0x2
-#define PCIE_CORE_PL_CONF_SPEED_SHIFT 3
-#define PCIE_CORE_PL_CONF_SPEED_MASK 0x3
-#define PCIE_CORE_PL_CONF_LANE_SHIFT 1
-#define PCIE_CORE_PL_CONF_LANE_MASK 0x3
-#define PCIE_CORE_RC_CONF_SCC_SHIFT 16
-
-#define ROCKCHIP_PCIE_RPIFR1_INTR_MASK GENMASK(8, 5)
-#define ROCKCHIP_PCIE_RPIFR1_INTR_SHIFT 5
-
-#define PCIE_CORE_INT \
- (PCIE_CORE_INT_PRFPE | PCIE_CORE_INT_CRFPE | \
- PCIE_CORE_INT_RRPE | PCIE_CORE_INT_CRFO | \
- PCIE_CORE_INT_RT | PCIE_CORE_INT_RTR | \
- PCIE_CORE_INT_PE | PCIE_CORE_INT_MTR | \
- PCIE_CORE_INT_UCR | PCIE_CORE_INT_FCE | \
- PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \
- PCIE_CORE_INT_MMVC)
-
-#define PCIE_CLIENT_INT_SUBSYSTEM \
- (PCIE_CLIENT_INT_PWR_STCG | PCIE_CLIENT_INT_HOT_PLUG | \
- PCIE_CLIENT_INT_PHY | PCIE_CLIENT_INT_UDMA | \
- PCIE_CLIENT_INT_LOCAL)
-
-#define PCIE_CLIENT_INT_LEGACY \
- (PCIE_CLIENT_INT_INTA | PCIE_CLIENT_INT_INTB | \
- PCIE_CLIENT_INT_INTC | PCIE_CLIENT_INT_INTD)
-#define PCIE_CLIENT_INT_CLI \
- (PCIE_CLIENT_INT_CORR_ERR | PCIE_CLIENT_INT_NFATAL_ERR | \
- PCIE_CLIENT_INT_FATAL_ERR | PCIE_CLIENT_INT_DPA | \
- PCIE_CLIENT_INT_HOT_RST | PCIE_CLIENT_INT_MSG | \
- PCIE_CLIENT_INT_LEGACY_DONE | PCIE_CLIENT_INT_LEGACY | \
- PCIE_CLIENT_INT_PHY)
-
-struct rockchip_pcie_port {
- void __iomem *reg_base;
- void __iomem *apb_base;
+struct rockchip_pcie {
+ void __iomem *reg_base; /* DT axi-base */
+ void __iomem *apb_base; /* DT apb-base */
struct phy *phy;
struct reset_control *core_rst;
struct reset_control *mgmt_rst;
struct irq_domain *irq_domain;
};
-static inline u32 pcie_read(struct rockchip_pcie_port *port, u32 reg)
+static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg)
{
- return readl(port->apb_base + reg);
+ return readl(rockchip->apb_base + reg);
}
-static inline void pcie_write(struct rockchip_pcie_port *port, u32 val, u32 reg)
+static void rockchip_pcie_write(struct rockchip_pcie *rockchip, u32 val,
+ u32 reg)
{
- writel(val, port->apb_base + reg);
+ writel(val, rockchip->apb_base + reg);
}
-static void rockchip_pcie_enable_bw_int(struct rockchip_pcie_port *port)
+static void rockchip_pcie_enable_bw_int(struct rockchip_pcie *rockchip)
{
u32 status;
- status = pcie_read(port, PCIE_RC_CONFIG_BASE + PCIE_RC_CONFIG_LCSR);
- status |= (PCIE_RC_CONFIG_LCSR_LBMIE | PCIE_RC_CONFIG_LCSR_LABIE);
- pcie_write(port, status, PCIE_RC_CONFIG_BASE + PCIE_RC_CONFIG_LCSR);
+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
+ status |= (PCIE_RC_CONFIG_LCS_LBMIE | PCIE_RC_CONFIG_LCS_LABIE);
+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
}
-static void rockchip_pcie_clr_bw_int(struct rockchip_pcie_port *port)
+static void rockchip_pcie_clr_bw_int(struct rockchip_pcie *rockchip)
{
u32 status;
- status = pcie_read(port, PCIE_RC_CONFIG_BASE + PCIE_RC_CONFIG_LCSR);
- status |= (PCIE_RC_CONFIG_LCSR_LBMS | PCIE_RC_CONFIG_LCSR_LAMS);
- pcie_write(port, status, PCIE_RC_CONFIG_BASE + PCIE_RC_CONFIG_LCSR);
+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
+ status |= (PCIE_RC_CONFIG_LCS_LBMS | PCIE_RC_CONFIG_LCS_LAMS);
+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
}
-static int rockchip_pcie_valid_config(struct rockchip_pcie_port *pp,
+static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip,
struct pci_bus *bus, int dev)
{
/* access only one slot on each root port */
- if (bus->number == pp->root_bus_nr && dev > 0)
+ if (bus->number == rockchip->root_bus_nr && dev > 0)
return 0;
/*
* do not read more than one device on the bus directly attached
* to RC's downstream side.
*/
- if (bus->primary == pp->root_bus_nr && dev > 0)
+ if (bus->primary == rockchip->root_bus_nr && dev > 0)
return 0;
return 1;
}
-static int rockchip_pcie_rd_own_conf(struct rockchip_pcie_port *pp,
- int where, int size,
- u32 *val)
+static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip,
+ int where, int size, u32 *val)
{
- void __iomem *addr = pp->apb_base + PCIE_RC_CONFIG_BASE + where;
+ void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where;
if (!IS_ALIGNED((uintptr_t)addr, size)) {
*val = 0;
return PCIBIOS_SUCCESSFUL;
}
-static int rockchip_pcie_wr_own_conf(struct rockchip_pcie_port *pp,
+static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip,
int where, int size, u32 val)
{
u32 mask, tmp, offset;
- offset = (where & (~0x3));
+ offset = where & ~0x3;
if (size == 4) {
- writel(val, pp->apb_base + PCIE_RC_CONFIG_BASE + offset);
+ writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
return PCIBIOS_SUCCESSFUL;
}
mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
- tmp = readl(pp->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask;
+ /*
+ * N.B. This read/modify/write isn't safe in general because it can
+ * corrupt RW1C bits in adjacent registers. But the hardware
+ * doesn't support smaller writes.
+ */
+ tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask;
tmp |= val << ((where & 0x3) * 8);
- writel(tmp, pp->apb_base + PCIE_RC_CONFIG_BASE + offset);
+ writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
return PCIBIOS_SUCCESSFUL;
}
-static int rockchip_pcie_rd_other_conf(struct rockchip_pcie_port *pp,
+static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip,
struct pci_bus *bus, u32 devfn,
int where, int size, u32 *val)
{
}
if (size == 4) {
- *val = readl(pp->reg_base + busdev);
+ *val = readl(rockchip->reg_base + busdev);
} else if (size == 2) {
- *val = readw(pp->reg_base + busdev);
+ *val = readw(rockchip->reg_base + busdev);
} else if (size == 1) {
- *val = readb(pp->reg_base + busdev);
+ *val = readb(rockchip->reg_base + busdev);
} else {
*val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
return PCIBIOS_SUCCESSFUL;
}
-static int rockchip_pcie_wr_other_conf(struct rockchip_pcie_port *pp,
+static int rockchip_pcie_wr_other_conf(struct rockchip_pcie *rockchip,
struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
return PCIBIOS_BAD_REGISTER_NUMBER;
if (size == 4)
- writel(val, pp->reg_base + busdev);
+ writel(val, rockchip->reg_base + busdev);
else if (size == 2)
- writew(val, pp->reg_base + busdev);
+ writew(val, rockchip->reg_base + busdev);
else if (size == 1)
- writeb(val, pp->reg_base + busdev);
+ writeb(val, rockchip->reg_base + busdev);
else
return PCIBIOS_BAD_REGISTER_NUMBER;
static int rockchip_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct rockchip_pcie_port *pp = bus->sysdata;
+ struct rockchip_pcie *rockchip = bus->sysdata;
- if (!rockchip_pcie_valid_config(pp, bus, PCI_SLOT(devfn))) {
+ if (!rockchip_pcie_valid_device(rockchip, bus, PCI_SLOT(devfn))) {
*val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
- if (bus->number == pp->root_bus_nr)
- return rockchip_pcie_rd_own_conf(pp, where, size, val);
-
- return rockchip_pcie_rd_other_conf(pp, bus, devfn, where, size, val);
+ if (bus->number == rockchip->root_bus_nr)
+ return rockchip_pcie_rd_own_conf(rockchip, where, size, val);
+ return rockchip_pcie_rd_other_conf(rockchip, bus, devfn, where, size, val);
}
static int rockchip_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct rockchip_pcie_port *pp = bus->sysdata;
+ struct rockchip_pcie *rockchip = bus->sysdata;
- if (!rockchip_pcie_valid_config(pp, bus, PCI_SLOT(devfn)))
+ if (!rockchip_pcie_valid_device(rockchip, bus, PCI_SLOT(devfn)))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (bus->number == pp->root_bus_nr)
- return rockchip_pcie_wr_own_conf(pp, where, size, val);
+ if (bus->number == rockchip->root_bus_nr)
+ return rockchip_pcie_wr_own_conf(rockchip, where, size, val);
- return rockchip_pcie_wr_other_conf(pp, bus, devfn, where, size, val);
+ return rockchip_pcie_wr_other_conf(rockchip, bus, devfn, where, size, val);
}
static struct pci_ops rockchip_pcie_ops = {
/**
* rockchip_pcie_init_port - Initialize hardware
- * @port: PCIe port information
+ * @rockchip: PCIe port information
*/
-static int rockchip_pcie_init_port(struct rockchip_pcie_port *port)
+static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
{
+ struct device *dev = rockchip->dev;
int err;
u32 status;
unsigned long timeout;
- gpiod_set_value(port->ep_gpio, 0);
+ gpiod_set_value(rockchip->ep_gpio, 0);
- err = phy_init(port->phy);
+ err = phy_init(rockchip->phy);
if (err < 0) {
- dev_err(port->dev, "fail to init phy, err %d\n", err);
+ dev_err(dev, "fail to init phy, err %d\n", err);
return err;
}
- err = reset_control_assert(port->core_rst);
+ err = reset_control_assert(rockchip->core_rst);
if (err) {
- dev_err(port->dev, "assert core_rst err %d\n", err);
+ dev_err(dev, "assert core_rst err %d\n", err);
return err;
}
- err = reset_control_assert(port->mgmt_rst);
+ err = reset_control_assert(rockchip->mgmt_rst);
if (err) {
- dev_err(port->dev, "assert mgmt_rst err %d\n", err);
+ dev_err(dev, "assert mgmt_rst err %d\n", err);
return err;
}
- err = reset_control_assert(port->mgmt_sticky_rst);
+ err = reset_control_assert(rockchip->mgmt_sticky_rst);
if (err) {
- dev_err(port->dev, "assert mgmt_sticky_rst err %d\n", err);
+ dev_err(dev, "assert mgmt_sticky_rst err %d\n", err);
return err;
}
- err = reset_control_assert(port->pipe_rst);
+ err = reset_control_assert(rockchip->pipe_rst);
if (err) {
- dev_err(port->dev, "assert pipe_rst err %d\n", err);
+ dev_err(dev, "assert pipe_rst err %d\n", err);
return err;
}
- pcie_write(port,
- HIWORD_UPDATE(PCIE_CLIENT_CONF_ENABLE,
- PCIE_CLIENT_CONF_ENABLE_MASK,
- PCIE_CLIENT_CONF_ENABLE_SHIFT) |
- HIWORD_UPDATE(PCIE_CLIENT_CONF_LANE_NUM(port->lanes),
- PCIE_CLIENT_CONF_LANE_NUM_MASK,
- PCIE_CLIENT_CONF_LANE_NUM_SHIFT) |
- HIWORD_UPDATE(PCIE_CLIENT_MODE_RC,
- PCIE_CLIENT_MODE_MASK,
- PCIE_CLIENT_MODE_SHIFT) |
- HIWORD_UPDATE(PCIE_CLIENT_ARI_ENABLE,
- PCIE_CLIENT_ARI_ENABLE_MASK,
- PCIE_CLIENT_ARI_ENABLE_SHIFT) |
- HIWORD_UPDATE(PCIE_CLIENT_GEN_SEL_2,
- PCIE_CLIENT_GEN_SEL_MASK,
- PCIE_CLIENT_GEN_SEL_SHIFT),
- PCIE_CLIENT_BASE);
-
- err = phy_power_on(port->phy);
+ rockchip_pcie_write(rockchip,
+ PCIE_CLIENT_CONF_ENABLE |
+ PCIE_CLIENT_LINK_TRAIN_ENABLE |
+ PCIE_CLIENT_ARI_ENABLE |
+ PCIE_CLIENT_CONF_LANE_NUM(rockchip->lanes) |
+ PCIE_CLIENT_MODE_RC |
+ PCIE_CLIENT_GEN_SEL_2,
+ PCIE_CLIENT_CONFIG);
+
+ err = phy_power_on(rockchip->phy);
if (err) {
- dev_err(port->dev, "fail to power on phy, err %d\n", err);
+ dev_err(dev, "fail to power on phy, err %d\n", err);
return err;
}
- err = reset_control_deassert(port->core_rst);
+ err = reset_control_deassert(rockchip->core_rst);
if (err) {
- dev_err(port->dev, "deassert core_rst err %d\n", err);
+ dev_err(dev, "deassert core_rst err %d\n", err);
return err;
}
- err = reset_control_deassert(port->mgmt_rst);
+ err = reset_control_deassert(rockchip->mgmt_rst);
if (err) {
- dev_err(port->dev, "deassert mgmt_rst err %d\n", err);
+ dev_err(dev, "deassert mgmt_rst err %d\n", err);
return err;
}
- err = reset_control_deassert(port->mgmt_sticky_rst);
+ err = reset_control_deassert(rockchip->mgmt_sticky_rst);
if (err) {
- dev_err(port->dev, "deassert mgmt_sticky_rst err %d\n", err);
+ dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err);
return err;
}
- err = reset_control_deassert(port->pipe_rst);
+ err = reset_control_deassert(rockchip->pipe_rst);
if (err) {
- dev_err(port->dev, "deassert pipe_rst err %d\n", err);
+ dev_err(dev, "deassert pipe_rst err %d\n", err);
return err;
}
+ /*
+ * We need to read/write PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 before
+ * enabling ASPM. Otherwise L1PwrOnSc and L1PwrOnVal isn't
+ * reliable and enabling ASPM doesn't work. This is a controller
+ * bug we need to work around.
+ */
+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2);
+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2);
+
/* Enable Gen1 training */
- pcie_write(port,
- HIWORD_UPDATE(PCIE_CLIENT_LINK_TRAIN_ENABLE,
- PCIE_CLIENT_LINK_TRAIN_MASK,
- PCIE_CLIENT_LINK_TRAIN_SHIFT),
- PCIE_CLIENT_BASE);
+ rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE,
+ PCIE_CLIENT_CONFIG);
- gpiod_set_value(port->ep_gpio, 1);
+ gpiod_set_value(rockchip->ep_gpio, 1);
/* 500ms timeout value should be enough for Gen1/2 training */
timeout = jiffies + msecs_to_jiffies(500);
for (;;) {
- status = pcie_read(port, PCIE_CLIENT_BASIC_STATUS1);
- if (((status >> PCIE_CLIENT_LINK_STATUS_SHIFT) &
- PCIE_CLIENT_LINK_STATUS_MASK) ==
- PCIE_CLIENT_LINK_STATUS_UP) {
- dev_dbg(port->dev, "PCIe link training gen1 pass!\n");
+ status = rockchip_pcie_read(rockchip,
+ PCIE_CLIENT_BASIC_STATUS1);
+ if ((status & PCIE_CLIENT_LINK_STATUS_MASK) ==
+ PCIE_CLIENT_LINK_STATUS_UP) {
+ dev_dbg(dev, "PCIe link training gen1 pass!\n");
break;
}
- msleep(20);
-
- if (!time_before(jiffies, timeout)) {
- err = -ETIMEDOUT;
- break;
+ if (time_after(jiffies, timeout)) {
+ dev_err(dev, "PCIe link training gen1 timeout!\n");
+ return -ETIMEDOUT;
}
- }
-
- /* Double check gen1 training */
- if (err) {
- status = pcie_read(port, PCIE_CLIENT_BASIC_STATUS1);
- err = (((status >> PCIE_CLIENT_LINK_STATUS_SHIFT) &
- PCIE_CLIENT_LINK_STATUS_MASK) ==
- PCIE_CLIENT_LINK_STATUS_UP) ? 0 : -ETIMEDOUT;
- if (err) {
- dev_err(port->dev, "PCIe link training gen1 timeout!\n");
- return err;
- }
+ msleep(20);
}
/*
* Enable retrain for gen2. This should be configured only after
* gen1 finished.
*/
- status = pcie_read(port,
- PCIE_RC_CONFIG_LCS + PCIE_RC_CONFIG_BASE);
- status |= PCIE_CORE_LCSR_RETRAIN_LINK;
- pcie_write(port, status,
- PCIE_RC_CONFIG_LCS + PCIE_RC_CONFIG_BASE);
+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
+ status |= PCIE_RC_CONFIG_LCS_RETRAIN_LINK;
+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
timeout = jiffies + msecs_to_jiffies(500);
for (;;) {
- status = pcie_read(port, PCIE_CORE_CTRL_MGMT_BASE);
- if (((status >> PCIE_CORE_PL_CONF_SPEED_SHIFT) &
- PCIE_CORE_PL_CONF_SPEED_MASK) ==
- PCIE_CORE_PL_CONF_SPEED_5G) {
- dev_dbg(port->dev, "PCIe link training gen2 pass!\n");
+ status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
+ if ((status & PCIE_CORE_PL_CONF_SPEED_MASK) ==
+ PCIE_CORE_PL_CONF_SPEED_5G) {
+ dev_dbg(dev, "PCIe link training gen2 pass!\n");
break;
}
- msleep(20);
-
- if (!time_before(jiffies, timeout)) {
- err = -ETIMEDOUT;
+ if (time_after(jiffies, timeout)) {
+ dev_dbg(dev, "PCIe link training gen2 timeout, fall back to gen1!\n");
break;
}
- }
- /* Double check gen2 training */
- if (err) {
- status = pcie_read(port, PCIE_CORE_CTRL_MGMT_BASE);
- err = (((status >> PCIE_CORE_PL_CONF_SPEED_SHIFT) &
- PCIE_CORE_PL_CONF_SPEED_MASK) ==
- PCIE_CORE_PL_CONF_SPEED_5G) ? 0 : -ETIMEDOUT;
- if (err)
- dev_dbg(port->dev, "PCIe link training gen2 timeout, fall back to gen1!\n");
+ msleep(20);
}
/* Check the final link width from negotiated lane counter from MGMT */
- status = pcie_read(port, PCIE_CORE_CTRL_MGMT_BASE);
- status = 0x1 << ((status >> PCIE_CORE_PL_CONF_LANE_SHIFT) &
- PCIE_CORE_PL_CONF_LANE_MASK);
- dev_dbg(port->dev, "current link width is x%d\n", status);
-
- pcie_write(port, ROCKCHIP_VENDOR_ID, PCIE_RC_CONFIG_BASE);
- pcie_write(port, PCI_CLASS_BRIDGE_PCI << PCIE_CORE_RC_CONF_SCC_SHIFT,
- PCIE_RC_CONFIG_BASE + PCIE_RC_CONFIG_RID_CCR);
- pcie_write(port, 0x0, PCIE_CORE_CTRL_MGMT_BASE + PCIE_RC_BAR_CONF);
-
- pcie_write(port, (RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS),
- PCIE_CORE_AXI_CONF_BASE);
- pcie_write(port, RC_REGION_0_ADDR_TRANS_H,
- PCIE_CORE_AXI_CONF_BASE + PCIE_CORE_OB_REGION_ADDR1);
- pcie_write(port, 0x0080000a,
- PCIE_CORE_AXI_CONF_BASE + PCIE_CORE_OB_REGION_DESC0);
- pcie_write(port, 0x0,
- PCIE_CORE_AXI_CONF_BASE + PCIE_CORE_OB_REGION_DESC1);
+ status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
+ status = 0x1 << ((status & PCIE_CORE_PL_CONF_LANE_MASK) >>
+ PCIE_CORE_PL_CONF_LANE_MASK);
+ dev_dbg(dev, "current link width is x%d\n", status);
+
+ rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID,
+ PCIE_RC_CONFIG_VENDOR);
+ rockchip_pcie_write(rockchip,
+ PCI_CLASS_BRIDGE_PCI << PCIE_RC_CONFIG_SCC_SHIFT,
+ PCIE_RC_CONFIG_RID_CCR);
+ rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
+
+ rockchip_pcie_write(rockchip,
+ (RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS),
+ PCIE_CORE_OB_REGION_ADDR0);
+ rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H,
+ PCIE_CORE_OB_REGION_ADDR1);
+ rockchip_pcie_write(rockchip, 0x0080000a, PCIE_CORE_OB_REGION_DESC0);
+ rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1);
return 0;
}
static irqreturn_t rockchip_pcie_subsys_irq_handler(int irq, void *arg)
{
- struct rockchip_pcie_port *pp = arg;
+ struct rockchip_pcie *rockchip = arg;
+ struct device *dev = rockchip->dev;
u32 reg;
u32 sub_reg;
- reg = pcie_read(pp, PCIE_CLIENT_INT_STATUS);
+ reg = rockchip_pcie_read(rockchip, PCIE_CLIENT_INT_STATUS);
if (reg & PCIE_CLIENT_INT_LOCAL) {
- dev_dbg(pp->dev, "local interrupt received\n");
- sub_reg = pcie_read(pp, PCIE_CORE_INT_STATUS);
+ dev_dbg(dev, "local interrupt received\n");
+ sub_reg = rockchip_pcie_read(rockchip, PCIE_CORE_INT_STATUS);
if (sub_reg & PCIE_CORE_INT_PRFPE)
- dev_dbg(pp->dev, "parity error detected while reading from the PNP receive FIFO RAM\n");
+ dev_dbg(dev, "parity error detected while reading from the PNP receive FIFO RAM\n");
if (sub_reg & PCIE_CORE_INT_CRFPE)
- dev_dbg(pp->dev, "parity error detected while reading from the Completion Receive FIFO RAM\n");
+ dev_dbg(dev, "parity error detected while reading from the Completion Receive FIFO RAM\n");
if (sub_reg & PCIE_CORE_INT_RRPE)
- dev_dbg(pp->dev, "parity error detected while reading from replay buffer RAM\n");
+ dev_dbg(dev, "parity error detected while reading from replay buffer RAM\n");
if (sub_reg & PCIE_CORE_INT_PRFO)
- dev_dbg(pp->dev, "overflow occurred in the PNP receive FIFO\n");
+ dev_dbg(dev, "overflow occurred in the PNP receive FIFO\n");
if (sub_reg & PCIE_CORE_INT_CRFO)
- dev_dbg(pp->dev, "overflow occurred in the completion receive FIFO\n");
+ dev_dbg(dev, "overflow occurred in the completion receive FIFO\n");
if (sub_reg & PCIE_CORE_INT_RT)
- dev_dbg(pp->dev, "replay timer timed out\n");
+ dev_dbg(dev, "replay timer timed out\n");
if (sub_reg & PCIE_CORE_INT_RTR)
- dev_dbg(pp->dev, "replay timer rolled over after 4 transmissions of the same TLP\n");
+ dev_dbg(dev, "replay timer rolled over after 4 transmissions of the same TLP\n");
if (sub_reg & PCIE_CORE_INT_PE)
- dev_dbg(pp->dev, "phy error detected on receive side\n");
+ dev_dbg(dev, "phy error detected on receive side\n");
if (sub_reg & PCIE_CORE_INT_MTR)
- dev_dbg(pp->dev, "malformed TLP received from the link\n");
+ dev_dbg(dev, "malformed TLP received from the link\n");
if (sub_reg & PCIE_CORE_INT_UCR)
- dev_dbg(pp->dev, "malformed TLP received from the link\n");
+ dev_dbg(dev, "malformed TLP received from the link\n");
if (sub_reg & PCIE_CORE_INT_FCE)
- dev_dbg(pp->dev, "an error was observed in the flow control advertisements from the other side\n");
+ dev_dbg(dev, "an error was observed in the flow control advertisements from the other side\n");
if (sub_reg & PCIE_CORE_INT_CT)
- dev_dbg(pp->dev, "a request timed out waiting for completion\n");
+ dev_dbg(dev, "a request timed out waiting for completion\n");
if (sub_reg & PCIE_CORE_INT_UTC)
- dev_dbg(pp->dev, "unmapped TC error\n");
+ dev_dbg(dev, "unmapped TC error\n");
if (sub_reg & PCIE_CORE_INT_MMVC)
- dev_dbg(pp->dev, "MSI mask register changes\n");
+ dev_dbg(dev, "MSI mask register changes\n");
- pcie_write(pp, sub_reg, PCIE_CORE_INT_STATUS);
+ rockchip_pcie_write(rockchip, sub_reg, PCIE_CORE_INT_STATUS);
} else if (reg & PCIE_CLIENT_INT_PHY) {
- dev_dbg(pp->dev, "phy link changes\n");
- rockchip_pcie_clr_bw_int(pp);
+ dev_dbg(dev, "phy link changes\n");
+ rockchip_pcie_clr_bw_int(rockchip);
}
- pcie_write(pp, reg & PCIE_CLIENT_INT_LOCAL, PCIE_CLIENT_INT_STATUS);
+ rockchip_pcie_write(rockchip, reg & PCIE_CLIENT_INT_LOCAL,
+ PCIE_CLIENT_INT_STATUS);
return IRQ_HANDLED;
}
static irqreturn_t rockchip_pcie_client_irq_handler(int irq, void *arg)
{
- struct rockchip_pcie_port *pp = arg;
+ struct rockchip_pcie *rockchip = arg;
+ struct device *dev = rockchip->dev;
u32 reg;
- reg = pcie_read(pp, PCIE_CLIENT_INT_STATUS);
+ reg = rockchip_pcie_read(rockchip, PCIE_CLIENT_INT_STATUS);
if (reg & PCIE_CLIENT_INT_LEGACY_DONE)
- dev_dbg(pp->dev, "legacy done interrupt received\n");
+ dev_dbg(dev, "legacy done interrupt received\n");
if (reg & PCIE_CLIENT_INT_MSG)
- dev_dbg(pp->dev, "message done interrupt received\n");
+ dev_dbg(dev, "message done interrupt received\n");
if (reg & PCIE_CLIENT_INT_HOT_RST)
- dev_dbg(pp->dev, "hot reset interrupt received\n");
+ dev_dbg(dev, "hot reset interrupt received\n");
if (reg & PCIE_CLIENT_INT_DPA)
- dev_dbg(pp->dev, "dpa interrupt received\n");
+ dev_dbg(dev, "dpa interrupt received\n");
if (reg & PCIE_CLIENT_INT_FATAL_ERR)
- dev_dbg(pp->dev, "fatal error interrupt received\n");
+ dev_dbg(dev, "fatal error interrupt received\n");
if (reg & PCIE_CLIENT_INT_NFATAL_ERR)
- dev_dbg(pp->dev, "no fatal error interrupt received\n");
+ dev_dbg(dev, "no fatal error interrupt received\n");
if (reg & PCIE_CLIENT_INT_CORR_ERR)
- dev_dbg(pp->dev, "correctable error interrupt received\n");
+ dev_dbg(dev, "correctable error interrupt received\n");
if (reg & PCIE_CLIENT_INT_PHY)
- dev_dbg(pp->dev, "phy interrupt received\n");
+ dev_dbg(dev, "phy interrupt received\n");
- pcie_write(pp, reg & (PCIE_CLIENT_INT_LEGACY_DONE |
+ rockchip_pcie_write(rockchip, reg & (PCIE_CLIENT_INT_LEGACY_DONE |
PCIE_CLIENT_INT_MSG | PCIE_CLIENT_INT_HOT_RST |
PCIE_CLIENT_INT_DPA | PCIE_CLIENT_INT_FATAL_ERR |
PCIE_CLIENT_INT_NFATAL_ERR |
PCIE_CLIENT_INT_CORR_ERR |
PCIE_CLIENT_INT_PHY),
- PCIE_CLIENT_INT_STATUS);
+ PCIE_CLIENT_INT_STATUS);
+
return IRQ_HANDLED;
}
static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
- struct rockchip_pcie_port *port;
+ struct rockchip_pcie *rockchip = irq_desc_get_handler_data(desc);
+ struct device *dev = rockchip->dev;
u32 reg;
u32 hwirq;
u32 virq;
chained_irq_enter(chip, desc);
- port = irq_desc_get_handler_data(desc);
- reg = pcie_read(port, PCIE_CLIENT_INT_STATUS);
- reg = (reg & ROCKCHIP_PCIE_RPIFR1_INTR_MASK) >>
- ROCKCHIP_PCIE_RPIFR1_INTR_SHIFT;
+ reg = rockchip_pcie_read(rockchip, PCIE_CLIENT_INT_STATUS);
+ reg = (reg & PCIE_CLIENT_INTR_MASK) >> PCIE_CLIENT_INTR_SHIFT;
while (reg) {
hwirq = ffs(reg) - 1;
reg &= ~BIT(hwirq);
- virq = irq_find_mapping(port->irq_domain, hwirq);
+ virq = irq_find_mapping(rockchip->irq_domain, hwirq);
if (virq)
generic_handle_irq(virq);
else
- dev_err(port->dev, "unexpected IRQ, INT%d\n", hwirq);
+ dev_err(dev, "unexpected IRQ, INT%d\n", hwirq);
}
chained_irq_exit(chip, desc);
/**
* rockchip_pcie_parse_dt - Parse Device Tree
- * @port: PCIe port information
+ * @rockchip: PCIe port information
*
* Return: '0' on success and error value on failure
*/
-static int rockchip_pcie_parse_dt(struct rockchip_pcie_port *port)
+static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
{
- struct device *dev = port->dev;
+ struct device *dev = rockchip->dev;
struct platform_device *pdev = to_platform_device(dev);
struct device_node *node = dev->of_node;
struct resource *regs;
regs = platform_get_resource_byname(pdev,
IORESOURCE_MEM,
"axi-base");
- if (!regs) {
- dev_err(dev, "missing axi-base property\n");
- return -ENODEV;
- }
-
- port->reg_base = devm_ioremap_resource(dev, regs);
- if (IS_ERR(port->reg_base))
- return PTR_ERR(port->reg_base);
+ rockchip->reg_base = devm_ioremap_resource(dev, regs);
+ if (IS_ERR(rockchip->reg_base))
+ return PTR_ERR(rockchip->reg_base);
regs = platform_get_resource_byname(pdev,
IORESOURCE_MEM,
"apb-base");
- if (!regs) {
- dev_err(dev, "missing apb-base property\n");
- return -ENODEV;
- }
-
- port->apb_base = devm_ioremap_resource(dev, regs);
- if (IS_ERR(port->apb_base))
- return PTR_ERR(port->apb_base);
+ rockchip->apb_base = devm_ioremap_resource(dev, regs);
+ if (IS_ERR(rockchip->apb_base))
+ return PTR_ERR(rockchip->apb_base);
- port->phy = devm_phy_get(dev, "pcie-phy");
- if (IS_ERR(port->phy)) {
- if (PTR_ERR(port->phy) != -EPROBE_DEFER)
+ rockchip->phy = devm_phy_get(dev, "pcie-phy");
+ if (IS_ERR(rockchip->phy)) {
+ if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER)
dev_err(dev, "missing phy\n");
- return PTR_ERR(port->phy);
+ return PTR_ERR(rockchip->phy);
}
- port->lanes = 1;
- err = of_property_read_u32(node, "num-lanes", &port->lanes);
- if (!err && ((port->lanes == 0) ||
- (port->lanes == 3) ||
- (port->lanes > 4))) {
- dev_warn(dev, "invalid num-lanes, default use one lane\n");
- port->lanes = 1;
+ rockchip->lanes = 1;
+ err = of_property_read_u32(node, "num-lanes", &rockchip->lanes);
+ if (!err && (rockchip->lanes == 0 ||
+ rockchip->lanes == 3 ||
+ rockchip->lanes > 4)) {
+ dev_warn(dev, "invalid num-lanes, default to use one lane\n");
+ rockchip->lanes = 1;
}
- port->core_rst = devm_reset_control_get(dev, "core");
- if (IS_ERR(port->core_rst)) {
- if (PTR_ERR(port->core_rst) != -EPROBE_DEFER)
- dev_err(dev, "missing core rst property in node\n");
- return PTR_ERR(port->core_rst);
+ rockchip->core_rst = devm_reset_control_get(dev, "core");
+ if (IS_ERR(rockchip->core_rst)) {
+ if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER)
+ dev_err(dev, "missing core reset property in node\n");
+ return PTR_ERR(rockchip->core_rst);
}
- port->mgmt_rst = devm_reset_control_get(dev, "mgmt");
- if (IS_ERR(port->mgmt_rst)) {
- if (PTR_ERR(port->mgmt_rst) != -EPROBE_DEFER)
- dev_err(dev, "missing mgmt rst property in node\n");
- return PTR_ERR(port->mgmt_rst);
+ rockchip->mgmt_rst = devm_reset_control_get(dev, "mgmt");
+ if (IS_ERR(rockchip->mgmt_rst)) {
+ if (PTR_ERR(rockchip->mgmt_rst) != -EPROBE_DEFER)
+ dev_err(dev, "missing mgmt reset property in node\n");
+ return PTR_ERR(rockchip->mgmt_rst);
}
- port->mgmt_sticky_rst = devm_reset_control_get(dev, "mgmt-sticky");
- if (IS_ERR(port->mgmt_sticky_rst)) {
- if (PTR_ERR(port->mgmt_sticky_rst) != -EPROBE_DEFER)
- dev_err(dev, "missing mgmt-sticky rst property in node\n");
- return PTR_ERR(port->mgmt_sticky_rst);
+ rockchip->mgmt_sticky_rst = devm_reset_control_get(dev, "mgmt-sticky");
+ if (IS_ERR(rockchip->mgmt_sticky_rst)) {
+ if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER)
+ dev_err(dev, "missing mgmt-sticky reset property in node\n");
+ return PTR_ERR(rockchip->mgmt_sticky_rst);
}
- port->pipe_rst = devm_reset_control_get(dev, "pipe");
- if (IS_ERR(port->pipe_rst)) {
- if (PTR_ERR(port->pipe_rst) != -EPROBE_DEFER)
- dev_err(dev, "missing pipe rst property in node\n");
- return PTR_ERR(port->pipe_rst);
+ rockchip->pipe_rst = devm_reset_control_get(dev, "pipe");
+ if (IS_ERR(rockchip->pipe_rst)) {
+ if (PTR_ERR(rockchip->pipe_rst) != -EPROBE_DEFER)
+ dev_err(dev, "missing pipe reset property in node\n");
+ return PTR_ERR(rockchip->pipe_rst);
}
- port->ep_gpio = devm_gpiod_get(dev, "ep", GPIOD_OUT_HIGH);
- if (IS_ERR(port->ep_gpio)) {
+ rockchip->ep_gpio = devm_gpiod_get(dev, "ep", GPIOD_OUT_HIGH);
+ if (IS_ERR(rockchip->ep_gpio)) {
dev_err(dev, "missing ep-gpios property in node\n");
- return PTR_ERR(port->ep_gpio);
+ return PTR_ERR(rockchip->ep_gpio);
}
- port->aclk_pcie = devm_clk_get(dev, "aclk");
- if (IS_ERR(port->aclk_pcie)) {
+ rockchip->aclk_pcie = devm_clk_get(dev, "aclk");
+ if (IS_ERR(rockchip->aclk_pcie)) {
dev_err(dev, "aclk clock not found\n");
- return PTR_ERR(port->aclk_pcie);
+ return PTR_ERR(rockchip->aclk_pcie);
}
- port->aclk_perf_pcie = devm_clk_get(dev, "aclk-perf");
- if (IS_ERR(port->aclk_perf_pcie)) {
+ rockchip->aclk_perf_pcie = devm_clk_get(dev, "aclk-perf");
+ if (IS_ERR(rockchip->aclk_perf_pcie)) {
dev_err(dev, "aclk_perf clock not found\n");
- return PTR_ERR(port->aclk_perf_pcie);
+ return PTR_ERR(rockchip->aclk_perf_pcie);
}
- port->hclk_pcie = devm_clk_get(dev, "hclk");
- if (IS_ERR(port->hclk_pcie)) {
+ rockchip->hclk_pcie = devm_clk_get(dev, "hclk");
+ if (IS_ERR(rockchip->hclk_pcie)) {
dev_err(dev, "hclk clock not found\n");
- return PTR_ERR(port->hclk_pcie);
+ return PTR_ERR(rockchip->hclk_pcie);
}
- port->clk_pcie_pm = devm_clk_get(dev, "pm");
- if (IS_ERR(port->clk_pcie_pm)) {
+ rockchip->clk_pcie_pm = devm_clk_get(dev, "pm");
+ if (IS_ERR(rockchip->clk_pcie_pm)) {
dev_err(dev, "pm clock not found\n");
- return PTR_ERR(port->clk_pcie_pm);
+ return PTR_ERR(rockchip->clk_pcie_pm);
}
irq = platform_get_irq_byname(pdev, "sys");
}
err = devm_request_irq(dev, irq, rockchip_pcie_subsys_irq_handler,
- IRQF_SHARED, "pcie-sys", port);
+ IRQF_SHARED, "pcie-sys", rockchip);
if (err) {
dev_err(dev, "failed to request PCIe subsystem IRQ\n");
return err;
irq_set_chained_handler_and_data(irq,
rockchip_pcie_legacy_int_handler,
- port);
+ rockchip);
irq = platform_get_irq_byname(pdev, "client");
if (irq < 0) {
}
err = devm_request_irq(dev, irq, rockchip_pcie_client_irq_handler,
- IRQF_SHARED, "pcie-client", port);
+ IRQF_SHARED, "pcie-client", rockchip);
if (err) {
dev_err(dev, "failed to request PCIe client IRQ\n");
return err;
}
- port->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3");
- if (IS_ERR(port->vpcie3v3)) {
- if (PTR_ERR(port->vpcie3v3) == -EPROBE_DEFER)
+ rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3");
+ if (IS_ERR(rockchip->vpcie3v3)) {
+ if (PTR_ERR(rockchip->vpcie3v3) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "no vpcie3v3 regulator found\n");
}
- port->vpcie1v8 = devm_regulator_get_optional(dev, "vpcie1v8");
- if (IS_ERR(port->vpcie1v8)) {
- if (PTR_ERR(port->vpcie1v8) == -EPROBE_DEFER)
+ rockchip->vpcie1v8 = devm_regulator_get_optional(dev, "vpcie1v8");
+ if (IS_ERR(rockchip->vpcie1v8)) {
+ if (PTR_ERR(rockchip->vpcie1v8) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "no vpcie1v8 regulator found\n");
}
- port->vpcie0v9 = devm_regulator_get_optional(dev, "vpcie0v9");
- if (IS_ERR(port->vpcie0v9)) {
- if (PTR_ERR(port->vpcie0v9) == -EPROBE_DEFER)
+ rockchip->vpcie0v9 = devm_regulator_get_optional(dev, "vpcie0v9");
+ if (IS_ERR(rockchip->vpcie0v9)) {
+ if (PTR_ERR(rockchip->vpcie0v9) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "no vpcie0v9 regulator found\n");
}
return 0;
}
-static int rockchip_pcie_set_vpcie(struct rockchip_pcie_port *port)
+static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip)
{
+ struct device *dev = rockchip->dev;
int err;
- if (!IS_ERR(port->vpcie3v3)) {
- err = regulator_enable(port->vpcie3v3);
+ if (!IS_ERR(rockchip->vpcie3v3)) {
+ err = regulator_enable(rockchip->vpcie3v3);
if (err) {
- dev_err(port->dev, "fail to enable vpcie3v3 regulator\n");
+ dev_err(dev, "fail to enable vpcie3v3 regulator\n");
goto err_out;
}
}
- if (!IS_ERR(port->vpcie1v8)) {
- err = regulator_enable(port->vpcie1v8);
+ if (!IS_ERR(rockchip->vpcie1v8)) {
+ err = regulator_enable(rockchip->vpcie1v8);
if (err) {
- dev_err(port->dev, "fail to enable vpcie1v8 regulator\n");
+ dev_err(dev, "fail to enable vpcie1v8 regulator\n");
goto err_disable_3v3;
}
}
- if (!IS_ERR(port->vpcie0v9)) {
- err = regulator_enable(port->vpcie0v9);
+ if (!IS_ERR(rockchip->vpcie0v9)) {
+ err = regulator_enable(rockchip->vpcie0v9);
if (err) {
- dev_err(port->dev, "fail to enable vpcie0v9 regulator\n");
+ dev_err(dev, "fail to enable vpcie0v9 regulator\n");
goto err_disable_1v8;
}
}
return 0;
err_disable_1v8:
- if (!IS_ERR(port->vpcie1v8))
- regulator_disable(port->vpcie1v8);
+ if (!IS_ERR(rockchip->vpcie1v8))
+ regulator_disable(rockchip->vpcie1v8);
err_disable_3v3:
- if (!IS_ERR(port->vpcie3v3))
- regulator_disable(port->vpcie3v3);
+ if (!IS_ERR(rockchip->vpcie3v3))
+ regulator_disable(rockchip->vpcie3v3);
err_out:
return err;
}
-static void rockchip_pcie_enable_interrupts(struct rockchip_pcie_port *port)
+static void rockchip_pcie_enable_interrupts(struct rockchip_pcie *rockchip)
{
- pcie_write(port, (PCIE_CLIENT_INT_CLI << 16) &
- (~PCIE_CLIENT_INT_CLI), PCIE_CLIENT_INT_MASK);
- pcie_write(port, (u32)(~PCIE_CORE_INT), PCIE_CORE_INT_MASK);
+ rockchip_pcie_write(rockchip, (PCIE_CLIENT_INT_CLI << 16) &
+ (~PCIE_CLIENT_INT_CLI), PCIE_CLIENT_INT_MASK);
+ rockchip_pcie_write(rockchip, (u32)(~PCIE_CORE_INT),
+ PCIE_CORE_INT_MASK);
- rockchip_pcie_enable_bw_int(port);
+ rockchip_pcie_enable_bw_int(rockchip);
}
static int rockchip_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
.map = rockchip_pcie_intx_map,
};
-static int rockchip_pcie_init_irq_domain(struct rockchip_pcie_port *pp)
+static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip)
{
- struct device *dev = pp->dev;
+ struct device *dev = rockchip->dev;
struct device_node *intc = of_get_next_child(dev->of_node, NULL);
if (!intc) {
return -EINVAL;
}
- pp->irq_domain = irq_domain_add_linear(intc, 4, &intx_domain_ops, pp);
- if (!pp->irq_domain) {
+ rockchip->irq_domain = irq_domain_add_linear(intc, 4,
+ &intx_domain_ops, rockchip);
+ if (!rockchip->irq_domain) {
dev_err(dev, "failed to get a INTx IRQ domain\n");
return -EINVAL;
}
return 0;
}
-static int rockchip_pcie_prog_ob_atu(struct rockchip_pcie_port *pp,
+static int rockchip_pcie_prog_ob_atu(struct rockchip_pcie *rockchip,
int region_no, int type, u8 num_pass_bits,
u32 lower_addr, u32 upper_addr)
{
u32 ob_addr_0;
u32 ob_addr_1;
u32 ob_desc_0;
- void __iomem *aw_base;
+ u32 aw_offset;
if (region_no >= MAX_AXI_WRAPPER_REGION_NUM)
return -EINVAL;
- if ((num_pass_bits + 1) < 8)
+ if (num_pass_bits + 1 < 8)
return -EINVAL;
if (num_pass_bits > 63)
return -EINVAL;
return -EINVAL;
}
- aw_base = pp->apb_base + PCIE_CORE_AXI_CONF_BASE;
- aw_base += (region_no << OB_REG_SIZE_SHIFT);
+ aw_offset = (region_no << OB_REG_SIZE_SHIFT);
ob_addr_0 = num_pass_bits & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS;
ob_addr_0 |= lower_addr & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR;
ob_addr_1 = upper_addr;
ob_desc_0 = (1 << 23 | type);
- writel(ob_addr_0, aw_base);
- writel(ob_addr_1, aw_base + PCIE_CORE_OB_REGION_ADDR1);
- writel(ob_desc_0, aw_base + PCIE_CORE_OB_REGION_DESC0);
- writel(0, aw_base + PCIE_CORE_OB_REGION_DESC1);
+ rockchip_pcie_write(rockchip, ob_addr_0,
+ PCIE_CORE_OB_REGION_ADDR0 + aw_offset);
+ rockchip_pcie_write(rockchip, ob_addr_1,
+ PCIE_CORE_OB_REGION_ADDR1 + aw_offset);
+ rockchip_pcie_write(rockchip, ob_desc_0,
+ PCIE_CORE_OB_REGION_DESC0 + aw_offset);
+ rockchip_pcie_write(rockchip, 0,
+ PCIE_CORE_OB_REGION_DESC1 + aw_offset);
return 0;
}
-static int rockchip_pcie_prog_ib_atu(struct rockchip_pcie_port *pp,
+static int rockchip_pcie_prog_ib_atu(struct rockchip_pcie *rockchip,
int region_no, u8 num_pass_bits,
u32 lower_addr, u32 upper_addr)
{
u32 ib_addr_0;
u32 ib_addr_1;
- void __iomem *aw_base;
+ u32 aw_offset;
if (region_no > MAX_AXI_IB_ROOTPORT_REGION_NUM)
return -EINVAL;
- if ((num_pass_bits + 1) < MIN_AXI_ADDR_BITS_PASSED)
+ if (num_pass_bits + 1 < MIN_AXI_ADDR_BITS_PASSED)
return -EINVAL;
if (num_pass_bits > 63)
return -EINVAL;
- aw_base = pp->apb_base + PCIE_CORE_AXI_INBOUND_BASE;
- aw_base += (region_no << IB_ROOT_PORT_REG_SIZE_SHIFT);
+ aw_offset = (region_no << IB_ROOT_PORT_REG_SIZE_SHIFT);
ib_addr_0 = num_pass_bits & PCIE_CORE_IB_REGION_ADDR0_NUM_BITS;
ib_addr_0 |= (lower_addr << 8) & PCIE_CORE_IB_REGION_ADDR0_LO_ADDR;
ib_addr_1 = upper_addr;
- writel(ib_addr_0, aw_base);
- writel(ib_addr_1, aw_base + PCIE_RP_IB_ADDR_TRANS);
+ rockchip_pcie_write(rockchip, ib_addr_0, PCIE_RP_IB_ADDR0 + aw_offset);
+ rockchip_pcie_write(rockchip, ib_addr_1, PCIE_RP_IB_ADDR1 + aw_offset);
return 0;
}
static int rockchip_pcie_probe(struct platform_device *pdev)
{
- struct rockchip_pcie_port *port;
+ struct rockchip_pcie *rockchip;
struct device *dev = &pdev->dev;
struct pci_bus *bus, *child;
struct resource_entry *win;
resource_size_t io_base;
- struct resource *busn = NULL;
struct resource *mem;
struct resource *io;
phys_addr_t io_bus_addr = 0;
if (!dev->of_node)
return -ENODEV;
- port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
- if (!port)
+ rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
+ if (!rockchip)
return -ENOMEM;
- port->dev = dev;
+ rockchip->dev = dev;
- err = rockchip_pcie_parse_dt(port);
+ err = rockchip_pcie_parse_dt(rockchip);
if (err)
return err;
- err = clk_prepare_enable(port->aclk_pcie);
+ err = clk_prepare_enable(rockchip->aclk_pcie);
if (err) {
dev_err(dev, "unable to enable aclk_pcie clock\n");
goto err_aclk_pcie;
}
- err = clk_prepare_enable(port->aclk_perf_pcie);
+ err = clk_prepare_enable(rockchip->aclk_perf_pcie);
if (err) {
dev_err(dev, "unable to enable aclk_perf_pcie clock\n");
goto err_aclk_perf_pcie;
}
- err = clk_prepare_enable(port->hclk_pcie);
+ err = clk_prepare_enable(rockchip->hclk_pcie);
if (err) {
dev_err(dev, "unable to enable hclk_pcie clock\n");
goto err_hclk_pcie;
}
- err = clk_prepare_enable(port->clk_pcie_pm);
+ err = clk_prepare_enable(rockchip->clk_pcie_pm);
if (err) {
dev_err(dev, "unable to enable hclk_pcie clock\n");
goto err_pcie_pm;
}
- err = rockchip_pcie_set_vpcie(port);
+ err = rockchip_pcie_set_vpcie(rockchip);
if (err) {
- dev_err(port->dev, "failed to set vpcie regulator\n");
+ dev_err(dev, "failed to set vpcie regulator\n");
goto err_set_vpcie;
}
- err = rockchip_pcie_init_port(port);
+ err = rockchip_pcie_init_port(rockchip);
if (err)
goto err_vpcie;
- platform_set_drvdata(pdev, port);
+ platform_set_drvdata(pdev, rockchip);
- rockchip_pcie_enable_interrupts(port);
+ rockchip_pcie_enable_interrupts(rockchip);
- err = rockchip_pcie_init_irq_domain(port);
+ err = rockchip_pcie_init_irq_domain(rockchip);
if (err < 0)
goto err_vpcie;
goto err_vpcie;
/* Get the I/O and memory ranges from DT */
+ io_size = 0;
resource_list_for_each_entry(win, &res) {
switch (resource_type(win->res)) {
case IORESOURCE_IO:
io_bus_addr = io->start - win->offset;
err = pci_remap_iospace(io, io_base);
if (err) {
- dev_warn(port->dev, "error %d: failed to map resource %pR\n",
+ dev_warn(dev, "error %d: failed to map resource %pR\n",
err, io);
continue;
}
mem_bus_addr = mem->start - win->offset;
break;
case IORESOURCE_BUS:
- busn = win->res;
+ rockchip->root_bus_nr = win->res->start;
break;
default:
continue;
}
}
- if (mem_size)
+ if (mem_size) {
for (reg_no = 0; reg_no < (mem_size >> 20); reg_no++) {
- err = rockchip_pcie_prog_ob_atu(port, reg_no + 1,
+ err = rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1,
AXI_WRAPPER_MEM_WRITE,
20 - 1,
mem_bus_addr +
goto err_vpcie;
}
}
+ }
- err = rockchip_pcie_prog_ib_atu(port, 2, 32 - 1, 0x0, 0);
+ err = rockchip_pcie_prog_ib_atu(rockchip, 2, 32 - 1, 0x0, 0);
if (err) {
dev_err(dev, "program RC mem inbound ATU failed\n");
goto err_vpcie;
offset = mem_size >> 20;
- if (io_size)
+ if (io_size) {
for (reg_no = 0; reg_no < (io_size >> 20); reg_no++) {
- err = rockchip_pcie_prog_ob_atu(port,
+ err = rockchip_pcie_prog_ob_atu(rockchip,
reg_no + 1 + offset,
AXI_WRAPPER_IO_WRITE,
20 - 1,
goto err_vpcie;
}
}
+ }
- if (busn)
- port->root_bus_nr = busn->start;
-
- bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, port, &res);
-
+ bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res);
if (!bus) {
err = -ENOMEM;
goto err_vpcie;
return err;
err_vpcie:
- if (!IS_ERR(port->vpcie3v3))
- regulator_disable(port->vpcie3v3);
- if (!IS_ERR(port->vpcie1v8))
- regulator_disable(port->vpcie1v8);
- if (!IS_ERR(port->vpcie0v9))
- regulator_disable(port->vpcie0v9);
+ if (!IS_ERR(rockchip->vpcie3v3))
+ regulator_disable(rockchip->vpcie3v3);
+ if (!IS_ERR(rockchip->vpcie1v8))
+ regulator_disable(rockchip->vpcie1v8);
+ if (!IS_ERR(rockchip->vpcie0v9))
+ regulator_disable(rockchip->vpcie0v9);
err_set_vpcie:
- clk_disable_unprepare(port->clk_pcie_pm);
+ clk_disable_unprepare(rockchip->clk_pcie_pm);
err_pcie_pm:
- clk_disable_unprepare(port->hclk_pcie);
+ clk_disable_unprepare(rockchip->hclk_pcie);
err_hclk_pcie:
- clk_disable_unprepare(port->aclk_perf_pcie);
+ clk_disable_unprepare(rockchip->aclk_perf_pcie);
err_aclk_perf_pcie:
- clk_disable_unprepare(port->aclk_pcie);
+ clk_disable_unprepare(rockchip->aclk_pcie);
err_aclk_pcie:
return err;
}