diff options
Diffstat (limited to 'drivers/pci/controller/pcie-rcar.c')
| -rw-r--r-- | drivers/pci/controller/pcie-rcar.c | 85 | 
1 files changed, 55 insertions, 30 deletions
diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c index c8febb009454..f6a669a9af41 100644 --- a/drivers/pci/controller/pcie-rcar.c +++ b/drivers/pci/controller/pcie-rcar.c @@ -46,14 +46,15 @@  /* Transfer control */  #define PCIETCTLR		0x02000 -#define  CFINIT			1 +#define  DL_DOWN		BIT(3) +#define  CFINIT			BIT(0)  #define PCIETSTR		0x02004 -#define  DATA_LINK_ACTIVE	1 +#define  DATA_LINK_ACTIVE	BIT(0)  #define PCIEERRFR		0x02020  #define  UNSUPPORTED_REQUEST	BIT(4)  #define PCIEMSIFR		0x02044  #define PCIEMSIALR		0x02048 -#define  MSIFE			1 +#define  MSIFE			BIT(0)  #define PCIEMSIAUR		0x0204c  #define PCIEMSIIER		0x02050 @@ -94,6 +95,7 @@  #define MACCTLR			0x011058  #define  SPEED_CHANGE		BIT(24)  #define  SCRAMBLE_DISABLE	BIT(27) +#define PMSR			0x01105c  #define MACS2R			0x011078  #define MACCGSPSETR		0x011084  #define  SPCNGRSN		BIT(31) @@ -152,14 +154,13 @@ struct rcar_pcie {  	struct			rcar_msi msi;  }; -static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val, -			       unsigned long reg) +static void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val, +			       unsigned int reg)  {  	writel(val, pcie->base + reg);  } -static unsigned long rcar_pci_read_reg(struct rcar_pcie *pcie, -				       unsigned long reg) +static u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int reg)  {  	return readl(pcie->base + reg);  } @@ -171,7 +172,7 @@ enum {  static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)  { -	int shift = 8 * (where & 3); +	unsigned int shift = BITS_PER_BYTE * (where & 3);  	u32 val = rcar_pci_read_reg(pcie, where & ~3);  	val &= ~(mask << shift); @@ -181,7 +182,7 @@ static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)  static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)  { -	int shift = 8 * (where & 3); +	unsigned int shift = BITS_PER_BYTE * (where & 3);  	u32 val = rcar_pci_read_reg(pcie, where & ~3);  	return val >> shift; @@ -192,7 +193,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,  		unsigned char access_type, struct pci_bus *bus,  		unsigned int devfn, int where, u32 *data)  { -	int dev, func, reg, index; +	unsigned int dev, func, reg, index;  	dev = PCI_SLOT(devfn);  	func = PCI_FUNC(devfn); @@ -281,12 +282,12 @@ static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,  	}  	if (size == 1) -		*val = (*val >> (8 * (where & 3))) & 0xff; +		*val = (*val >> (BITS_PER_BYTE * (where & 3))) & 0xff;  	else if (size == 2) -		*val = (*val >> (8 * (where & 2))) & 0xffff; +		*val = (*val >> (BITS_PER_BYTE * (where & 2))) & 0xffff; -	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n", -		bus->number, devfn, where, size, (unsigned long)*val); +	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", +		bus->number, devfn, where, size, *val);  	return ret;  } @@ -296,23 +297,24 @@ static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,  				int where, int size, u32 val)  {  	struct rcar_pcie *pcie = bus->sysdata; -	int shift, ret; +	unsigned int shift;  	u32 data; +	int ret;  	ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,  				      bus, devfn, where, &data);  	if (ret != PCIBIOS_SUCCESSFUL)  		return ret; -	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n", -		bus->number, devfn, where, size, (unsigned long)val); +	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", +		bus->number, devfn, where, size, val);  	if (size == 1) { -		shift = 8 * (where & 3); +		shift = BITS_PER_BYTE * (where & 3);  		data &= ~(0xff << shift);  		data |= ((val & 0xff) << shift);  	} else if (size == 2) { -		shift = 8 * (where & 2); +		shift = BITS_PER_BYTE * (where & 2);  		data &= ~(0xffff << shift);  		data |= ((val & 0xffff) << shift);  	} else @@ -507,10 +509,10 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)  }  static void phy_write_reg(struct rcar_pcie *pcie, -				 unsigned int rate, unsigned int addr, -				 unsigned int lane, unsigned int data) +			  unsigned int rate, u32 addr, +			  unsigned int lane, u32 data)  { -	unsigned long phyaddr; +	u32 phyaddr;  	phyaddr = WRITE_CMD |  		((rate & 1) << RATE_POS) | @@ -738,15 +740,15 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)  	while (reg) {  		unsigned int index = find_first_bit(®, 32); -		unsigned int irq; +		unsigned int msi_irq;  		/* clear the interrupt */  		rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR); -		irq = irq_find_mapping(msi->domain, index); -		if (irq) { +		msi_irq = irq_find_mapping(msi->domain, index); +		if (msi_irq) {  			if (test_bit(index, msi->used)) -				generic_handle_irq(irq); +				generic_handle_irq(msi_irq);  			else  				dev_info(dev, "unhandled MSI\n");  		} else { @@ -890,7 +892,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)  {  	struct device *dev = pcie->dev;  	struct rcar_msi *msi = &pcie->msi; -	unsigned long base; +	phys_addr_t base;  	int err, i;  	mutex_init(&msi->lock); @@ -929,10 +931,14 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)  	/* setup MSI data target */  	msi->pages = __get_free_pages(GFP_KERNEL, 0); +	if (!msi->pages) { +		err = -ENOMEM; +		goto err; +	}  	base = virt_to_phys((void *)msi->pages); -	rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR); -	rcar_pci_write_reg(pcie, 0, PCIEMSIAUR); +	rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR); +	rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR);  	/* enable all MSI interrupts */  	rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER); @@ -1118,7 +1124,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev;  	struct rcar_pcie *pcie; -	unsigned int data; +	u32 data;  	int err;  	int (*phy_init_fn)(struct rcar_pcie *);  	struct pci_host_bridge *bridge; @@ -1130,6 +1136,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)  	pcie = pci_host_bridge_priv(bridge);  	pcie->dev = dev; +	platform_set_drvdata(pdev, pcie);  	err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL);  	if (err) @@ -1221,10 +1228,28 @@ err_free_bridge:  	return err;  } +static int rcar_pcie_resume_noirq(struct device *dev) +{ +	struct rcar_pcie *pcie = dev_get_drvdata(dev); + +	if (rcar_pci_read_reg(pcie, PMSR) && +	    !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) +		return 0; + +	/* Re-establish the PCIe link */ +	rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); +	return rcar_pcie_wait_for_dl(pcie); +} + +static const struct dev_pm_ops rcar_pcie_pm_ops = { +	.resume_noirq = rcar_pcie_resume_noirq, +}; +  static struct platform_driver rcar_pcie_driver = {  	.driver = {  		.name = "rcar-pcie",  		.of_match_table = rcar_pcie_of_match, +		.pm = &rcar_pcie_pm_ops,  		.suppress_bind_attrs = true,  	},  	.probe = rcar_pcie_probe,  |