Skip to content

Commit 3f1ccd6

Browse files
marcanMani-Sadhasivam
authored andcommitted
PCI: apple: Abstract register offsets via a SoC-specific structure
Newer versions of the Apple PCIe block have a bunch of small, but annoying differences. In order to embrace this diversity of implementations, move the currently hardcoded offsets into a hw_info structure. Future SoCs will provide their own structure describing the applicable offsets. Signed-off-by: Hector Martin <[email protected]> Signed-off-by: Alyssa Rosenzweig <[email protected]> [maz: split from original patch to only address T8103] Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Manivannan Sadhasivam <[email protected]> Tested-by: Janne Grunau <[email protected]> Reviewed-by: Rob Herring (Arm) <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]> Acked-by: Alyssa Rosenzweig <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 7334364 commit 3f1ccd6

File tree

1 file changed

+72
-17
lines changed

1 file changed

+72
-17
lines changed

drivers/pci/controller/pcie-apple.c

Lines changed: 72 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* Author: Marc Zyngier <[email protected]>
1919
*/
2020

21+
#include <linux/bitfield.h>
2122
#include <linux/gpio/consumer.h>
2223
#include <linux/kernel.h>
2324
#include <linux/iopoll.h>
@@ -29,6 +30,7 @@
2930
#include <linux/of_irq.h>
3031
#include <linux/pci-ecam.h>
3132

33+
/* T8103 (original M1) and related SoCs */
3234
#define CORE_RC_PHYIF_CTL 0x00024
3335
#define CORE_RC_PHYIF_CTL_RUN BIT(0)
3436
#define CORE_RC_PHYIF_STAT 0x00028
@@ -104,7 +106,7 @@
104106
#define PORT_REFCLK_CGDIS BIT(8)
105107
#define PORT_PERST 0x00814
106108
#define PORT_PERST_OFF BIT(0)
107-
#define PORT_RID2SID(i16) (0x00828 + 4 * (i16))
109+
#define PORT_RID2SID 0x00828
108110
#define PORT_RID2SID_VALID BIT(31)
109111
#define PORT_RID2SID_SID_SHIFT 16
110112
#define PORT_RID2SID_BUS_SHIFT 8
@@ -122,7 +124,8 @@
122124
#define PORT_TUNSTAT_PERST_ACK_PEND BIT(1)
123125
#define PORT_PREFMEM_ENABLE 0x00994
124126

125-
#define MAX_RID2SID 64
127+
#define PORT_MSIMAP_ENABLE BIT(31)
128+
#define PORT_MSIMAP_TARGET GENMASK(7, 0)
126129

127130
/*
128131
* The doorbell address is set to 0xfffff000, which by convention
@@ -133,10 +136,33 @@
133136
*/
134137
#define DOORBELL_ADDR CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR
135138

139+
struct hw_info {
140+
u32 phy_lane_ctl;
141+
u32 port_msiaddr;
142+
u32 port_msiaddr_hi;
143+
u32 port_refclk;
144+
u32 port_perst;
145+
u32 port_rid2sid;
146+
u32 port_msimap;
147+
u32 max_rid2sid;
148+
};
149+
150+
static const struct hw_info t8103_hw = {
151+
.phy_lane_ctl = PHY_LANE_CTL,
152+
.port_msiaddr = PORT_MSIADDR,
153+
.port_msiaddr_hi = 0,
154+
.port_refclk = PORT_REFCLK,
155+
.port_perst = PORT_PERST,
156+
.port_rid2sid = PORT_RID2SID,
157+
.port_msimap = 0,
158+
.max_rid2sid = 64,
159+
};
160+
136161
struct apple_pcie {
137162
struct mutex lock;
138163
struct device *dev;
139164
void __iomem *base;
165+
const struct hw_info *hw;
140166
struct irq_domain *domain;
141167
unsigned long *bitmap;
142168
struct list_head ports;
@@ -380,7 +406,9 @@ static void apple_port_irq_handler(struct irq_desc *desc)
380406
static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
381407
{
382408
struct fwnode_handle *fwnode = &port->np->fwnode;
409+
struct apple_pcie *pcie = port->pcie;
383410
unsigned int irq;
411+
u32 val = 0;
384412

385413
/* FIXME: consider moving each interrupt under each port */
386414
irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)),
@@ -402,13 +430,23 @@ static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
402430

403431
/* Configure MSI base address */
404432
BUILD_BUG_ON(upper_32_bits(DOORBELL_ADDR));
405-
writel_relaxed(lower_32_bits(DOORBELL_ADDR), port->base + PORT_MSIADDR);
433+
writel_relaxed(lower_32_bits(DOORBELL_ADDR),
434+
port->base + pcie->hw->port_msiaddr);
435+
if (pcie->hw->port_msiaddr_hi)
436+
writel_relaxed(0, port->base + pcie->hw->port_msiaddr_hi);
406437

407438
/* Enable MSIs, shared between all ports */
408-
writel_relaxed(0, port->base + PORT_MSIBASE);
409-
writel_relaxed((ilog2(port->pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT) |
410-
PORT_MSICFG_EN, port->base + PORT_MSICFG);
439+
if (pcie->hw->port_msimap) {
440+
for (int i = 0; i < pcie->nvecs; i++)
441+
writel_relaxed(FIELD_PREP(PORT_MSIMAP_TARGET, i) |
442+
PORT_MSIMAP_ENABLE,
443+
port->base + pcie->hw->port_msimap + 4 * i);
444+
} else {
445+
writel_relaxed(0, port->base + PORT_MSIBASE);
446+
val = ilog2(pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT;
447+
}
411448

449+
writel_relaxed(val | PORT_MSICFG_EN, port->base + PORT_MSICFG);
412450
return 0;
413451
}
414452

@@ -475,7 +513,9 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie,
475513
u32 stat;
476514
int res;
477515

478-
rmw_set(PHY_LANE_CTL_CFGACC, port->phy + PHY_LANE_CTL);
516+
if (pcie->hw->phy_lane_ctl)
517+
rmw_set(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
518+
479519
rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG);
480520

481521
res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG,
@@ -492,20 +532,28 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie,
492532
if (res < 0)
493533
return res;
494534

495-
rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + PHY_LANE_CTL);
535+
if (pcie->hw->phy_lane_ctl)
536+
rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
496537

497538
rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG);
498-
rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK);
539+
540+
if (pcie->hw->port_refclk)
541+
rmw_set(PORT_REFCLK_EN, port->base + pcie->hw->port_refclk);
499542

500543
return 0;
501544
}
502545

546+
static void __iomem *port_rid2sid_addr(struct apple_pcie_port *port, int idx)
547+
{
548+
return port->base + port->pcie->hw->port_rid2sid + 4 * idx;
549+
}
550+
503551
static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port,
504552
int idx, u32 val)
505553
{
506-
writel_relaxed(val, port->base + PORT_RID2SID(idx));
554+
writel_relaxed(val, port_rid2sid_addr(port, idx));
507555
/* Read back to ensure completion of the write */
508-
return readl_relaxed(port->base + PORT_RID2SID(idx));
556+
return readl_relaxed(port_rid2sid_addr(port, idx));
509557
}
510558

511559
static int apple_pcie_setup_port(struct apple_pcie *pcie,
@@ -528,7 +576,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
528576
if (!port)
529577
return -ENOMEM;
530578

531-
port->sid_map = devm_bitmap_zalloc(pcie->dev, MAX_RID2SID, GFP_KERNEL);
579+
port->sid_map = devm_bitmap_zalloc(pcie->dev, pcie->hw->max_rid2sid, GFP_KERNEL);
532580
if (!port->sid_map)
533581
return -ENOMEM;
534582

@@ -572,7 +620,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
572620
usleep_range(100, 200);
573621

574622
/* Deassert PERST# */
575-
rmw_set(PORT_PERST_OFF, port->base + PORT_PERST);
623+
rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst);
576624
gpiod_set_value_cansleep(reset, 0);
577625

578626
/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
@@ -585,15 +633,19 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
585633
return ret;
586634
}
587635

588-
rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK);
636+
if (pcie->hw->port_refclk)
637+
rmw_clear(PORT_REFCLK_CGDIS, port->base + pcie->hw->port_refclk);
638+
else
639+
rmw_set(PHY_LANE_CFG_REFCLKCGEN, port->phy + PHY_LANE_CFG);
640+
589641
rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK);
590642

591643
ret = apple_pcie_port_setup_irq(port);
592644
if (ret)
593645
return ret;
594646

595647
/* Reset all RID/SID mappings, and check for RAZ/WI registers */
596-
for (i = 0; i < MAX_RID2SID; i++) {
648+
for (i = 0; i < pcie->hw->max_rid2sid; i++) {
597649
if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d)
598650
break;
599651
apple_pcie_rid2sid_write(port, i, 0);
@@ -741,7 +793,7 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci
741793
for_each_set_bit(idx, port->sid_map, port->sid_map_sz) {
742794
u32 val;
743795

744-
val = readl_relaxed(port->base + PORT_RID2SID(idx));
796+
val = readl_relaxed(port_rid2sid_addr(port, idx));
745797
if ((val & 0xffff) == rid) {
746798
apple_pcie_rid2sid_write(port, idx, 0);
747799
bitmap_release_region(port->sid_map, idx, 0);
@@ -792,6 +844,9 @@ static int apple_pcie_probe(struct platform_device *pdev)
792844
return -ENOMEM;
793845

794846
pcie->dev = dev;
847+
pcie->hw = of_device_get_match_data(dev);
848+
if (!pcie->hw)
849+
return -ENODEV;
795850
pcie->base = devm_platform_ioremap_resource(pdev, 1);
796851
if (IS_ERR(pcie->base))
797852
return PTR_ERR(pcie->base);
@@ -808,7 +863,7 @@ static int apple_pcie_probe(struct platform_device *pdev)
808863
}
809864

810865
static const struct of_device_id apple_pcie_of_match[] = {
811-
{ .compatible = "apple,pcie" },
866+
{ .compatible = "apple,pcie", .data = &t8103_hw },
812867
{ }
813868
};
814869
MODULE_DEVICE_TABLE(of, apple_pcie_of_match);

0 commit comments

Comments
 (0)