Release 4.16 drivers/pci/dwc/pcie-designware.c
// SPDX-License-Identifier: GPL-2.0
/*
* Synopsys DesignWare PCIe host controller driver
*
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Jingoo Han <jg1.han@samsung.com>
*/
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/types.h>
#include "pcie-designware.h"
/* PCIe Port Logic registers */
#define PLR_OFFSET 0x700
#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4)
#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
int dw_pcie_read(void __iomem *addr, int size, u32 *val)
{
if ((uintptr_t)addr & (size - 1)) {
*val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
}
if (size == 4) {
*val = readl(addr);
} else if (size == 2) {
*val = readw(addr);
} else if (size == 1) {
*val = readb(addr);
} else {
*val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
}
return PCIBIOS_SUCCESSFUL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jingoo Han | 49 | 47.12% | 2 | 33.33% |
Gabriele Paoloni | 48 | 46.15% | 2 | 33.33% |
Kishon Vijay Abraham I | 7 | 6.73% | 2 | 33.33% |
Total | 104 | 100.00% | 6 | 100.00% |
int dw_pcie_write(void __iomem *addr, int size, u32 val)
{
if ((uintptr_t)addr & (size - 1))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (size == 4)
writel(val, addr);
else if (size == 2)
writew(val, addr);
else if (size == 1)
writeb(val, addr);
else
return PCIBIOS_BAD_REGISTER_NUMBER;
return PCIBIOS_SUCCESSFUL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jingoo Han | 63 | 78.75% | 2 | 50.00% |
Gabriele Paoloni | 16 | 20.00% | 1 | 25.00% |
Kishon Vijay Abraham I | 1 | 1.25% | 1 | 25.00% |
Total | 80 | 100.00% | 4 | 100.00% |
u32 __dw_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
size_t size)
{
int ret;
u32 val;
if (pci->ops->read_dbi)
return pci->ops->read_dbi(pci, base, reg, size);
ret = dw_pcie_read(base + reg, size, &val);
if (ret)
dev_err(pci->dev, "read DBI address failed\n");
return val;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 51 | 62.96% | 3 | 42.86% |
Jingoo Han | 21 | 25.93% | 2 | 28.57% |
Seungwon Jeon | 5 | 6.17% | 1 | 14.29% |
Björn Helgaas | 4 | 4.94% | 1 | 14.29% |
Total | 81 | 100.00% | 7 | 100.00% |
void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
size_t size, u32 val)
{
int ret;
if (pci->ops->write_dbi) {
pci->ops->write_dbi(pci, base, reg, size, val);
return;
}
ret = dw_pcie_write(base + reg, size, val);
if (ret)
dev_err(pci->dev, "write DBI address failed\n");
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 47 | 58.02% | 3 | 42.86% |
Jingoo Han | 26 | 32.10% | 2 | 28.57% |
Seungwon Jeon | 4 | 4.94% | 1 | 14.29% |
Björn Helgaas | 4 | 4.94% | 1 | 14.29% |
Total | 81 | 100.00% | 7 | 100.00% |
static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
return dw_pcie_readl_dbi(pci, offset + reg);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Joao Pinto | 27 | 77.14% | 1 | 20.00% |
Kishon Vijay Abraham I | 5 | 14.29% | 2 | 40.00% |
Jingoo Han | 2 | 5.71% | 1 | 20.00% |
Seungwon Jeon | 1 | 2.86% | 1 | 20.00% |
Total | 35 | 100.00% | 5 | 100.00% |
static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
u32 val)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
dw_pcie_writel_dbi(pci, offset + reg, val);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jingoo Han | 15 | 38.46% | 1 | 14.29% |
Joao Pinto | 13 | 33.33% | 1 | 14.29% |
Kishon Vijay Abraham I | 5 | 12.82% | 2 | 28.57% |
Björn Helgaas | 4 | 10.26% | 2 | 28.57% |
Seungwon Jeon | 2 | 5.13% | 1 | 14.29% |
Total | 39 | 100.00% | 7 | 100.00% |
static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
int type, u64 cpu_addr,
u64 pci_addr, u32 size)
{
u32 retries, val;
dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
lower_32_bits(cpu_addr));
dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
upper_32_bits(cpu_addr));
dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
lower_32_bits(cpu_addr + size - 1));
dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
lower_32_bits(pci_addr));
dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
upper_32_bits(pci_addr));
dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
type);
dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
PCIE_ATU_ENABLE);
/*
* Make sure ATU enable takes effect before any subsequent config
* and I/O accesses.
*/
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
val = dw_pcie_readl_ob_unroll(pci, index,
PCIE_ATU_UNR_REGION_CTRL2);
if (val & PCIE_ATU_ENABLE)
return;
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
}
dev_err(pci->dev, "outbound iATU is not being enabled\n");
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 67 | 37.85% | 2 | 22.22% |
Joao Pinto | 65 | 36.72% | 2 | 22.22% |
JiSheng Zhang | 21 | 11.86% | 1 | 11.11% |
Björn Helgaas | 14 | 7.91% | 1 | 11.11% |
Jingoo Han | 6 | 3.39% | 1 | 11.11% |
Stanimir Varbanov | 3 | 1.69% | 1 | 11.11% |
Carlos Palminha | 1 | 0.56% | 1 | 11.11% |
Total | 177 | 100.00% | 9 | 100.00% |
void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
u64 cpu_addr, u64 pci_addr, u32 size)
{
u32 retries, val;
if (pci->ops->cpu_addr_fixup)
cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
if (pci->iatu_unroll_enabled) {
dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr,
pci_addr, size);
return;
}
dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
PCIE_ATU_REGION_OUTBOUND | index);
dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE,
lower_32_bits(cpu_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE,
upper_32_bits(cpu_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT,
lower_32_bits(cpu_addr + size - 1));
dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET,
lower_32_bits(pci_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
upper_32_bits(pci_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
/*
* Make sure ATU enable takes effect before any subsequent config
* and I/O accesses.
*/
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
if (val & PCIE_ATU_ENABLE)
return;
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
}
dev_err(pci->dev, "outbound iATU is not being enabled\n");
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 91 | 42.13% | 2 | 22.22% |
JiSheng Zhang | 64 | 29.63% | 2 | 22.22% |
Joao Pinto | 32 | 14.81% | 1 | 11.11% |
Björn Helgaas | 18 | 8.33% | 2 | 22.22% |
Stanimir Varbanov | 9 | 4.17% | 1 | 11.11% |
Niklas Cassel | 2 | 0.93% | 1 | 11.11% |
Total | 216 | 100.00% | 9 | 100.00% |
static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
return dw_pcie_readl_dbi(pci, offset + reg);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 35 | 100.00% | 1 | 100.00% |
Total | 35 | 100.00% | 1 | 100.00% |
static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
u32 val)
{
u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
dw_pcie_writel_dbi(pci, offset + reg, val);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 39 | 100.00% | 1 | 100.00% |
Total | 39 | 100.00% | 1 | 100.00% |
static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
int bar, u64 cpu_addr,
enum dw_pcie_as_type as_type)
{
int type;
u32 retries, val;
dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
lower_32_bits(cpu_addr));
dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
upper_32_bits(cpu_addr));
switch (as_type) {
case DW_PCIE_AS_MEM:
type = PCIE_ATU_TYPE_MEM;
break;
case DW_PCIE_AS_IO:
type = PCIE_ATU_TYPE_IO;
break;
default:
return -EINVAL;
}
dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type);
dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
PCIE_ATU_ENABLE |
PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
/*
* Make sure ATU enable takes effect before any subsequent config
* and I/O accesses.
*/
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
val = dw_pcie_readl_ib_unroll(pci, index,
PCIE_ATU_UNR_REGION_CTRL2);
if (val & PCIE_ATU_ENABLE)
return 0;
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
}
dev_err(pci->dev, "inbound iATU is not being enabled\n");
return -EBUSY;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 172 | 99.42% | 1 | 50.00% |
Carlos Palminha | 1 | 0.58% | 1 | 50.00% |
Total | 173 | 100.00% | 2 | 100.00% |
int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
u64 cpu_addr, enum dw_pcie_as_type as_type)
{
int type;
u32 retries, val;
if (pci->iatu_unroll_enabled)
return dw_pcie_prog_inbound_atu_unroll(pci, index, bar,
cpu_addr, as_type);
dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND |
index);
dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, lower_32_bits(cpu_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, upper_32_bits(cpu_addr));
switch (as_type) {
case DW_PCIE_AS_MEM:
type = PCIE_ATU_TYPE_MEM;
break;
case DW_PCIE_AS_IO:
type = PCIE_ATU_TYPE_IO;
break;
default:
return -EINVAL;
}
dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE
| PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
/*
* Make sure ATU enable takes effect before any subsequent config
* and I/O accesses.
*/
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
if (val & PCIE_ATU_ENABLE)
return 0;
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
}
dev_err(pci->dev, "inbound iATU is not being enabled\n");
return -EBUSY;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 193 | 100.00% | 1 | 100.00% |
Total | 193 | 100.00% | 1 | 100.00% |
void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
enum dw_pcie_region_type type)
{
int region;
switch (type) {
case DW_PCIE_REGION_INBOUND:
region = PCIE_ATU_REGION_INBOUND;
break;
case DW_PCIE_REGION_OUTBOUND:
region = PCIE_ATU_REGION_OUTBOUND;
break;
default:
return;
}
dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index);
dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, ~PCIE_ATU_ENABLE);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 65 | 100.00% | 1 | 100.00% |
Total | 65 | 100.00% | 1 | 100.00% |
int dw_pcie_wait_for_link(struct dw_pcie *pci)
{
int retries;
/* check if the link is up or not */
for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
if (dw_pcie_link_up(pci)) {
dev_info(pci->dev, "link up\n");
return 0;
}
usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
}
dev_err(pci->dev, "phy link never came up\n");
return -ETIMEDOUT;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jingoo Han | 33 | 47.14% | 2 | 22.22% |
Kishon Vijay Abraham I | 30 | 42.86% | 2 | 22.22% |
Harro Haan | 3 | 4.29% | 1 | 11.11% |
Pratyush Anand | 2 | 2.86% | 2 | 22.22% |
Lucas Stach | 1 | 1.43% | 1 | 11.11% |
JiSheng Zhang | 1 | 1.43% | 1 | 11.11% |
Total | 70 | 100.00% | 9 | 100.00% |
int dw_pcie_link_up(struct dw_pcie *pci)
{
u32 val;
if (pci->ops->link_up)
return pci->ops->link_up(pci);
val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1);
return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) &&
(!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 44 | 73.33% | 2 | 33.33% |
Jingoo Han | 12 | 20.00% | 2 | 33.33% |
Björn Helgaas | 2 | 3.33% | 1 | 16.67% |
Murali Karicheri | 2 | 3.33% | 1 | 16.67% |
Total | 60 | 100.00% | 6 | 100.00% |
void dw_pcie_setup(struct dw_pcie *pci)
{
int ret;
u32 val;
u32 lanes;
struct device *dev = pci->dev;
struct device_node *np = dev->of_node;
ret = of_property_read_u32(np, "num-lanes", &lanes);
if (ret)
lanes = 0;
/* set the number of lanes */
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
val &= ~PORT_LINK_MODE_MASK;
switch (lanes) {
case 1:
val |= PORT_LINK_MODE_1_LANES;
break;
case 2:
val |= PORT_LINK_MODE_2_LANES;
break;
case 4:
val |= PORT_LINK_MODE_4_LANES;
break;
case 8:
val |= PORT_LINK_MODE_8_LANES;
break;
default:
dev_err(pci->dev, "num-lanes %u: invalid value\n", lanes);
return;
}
dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
/* set link width speed control register */
val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
switch (lanes) {
case 1:
val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
break;
case 2:
val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
break;
case 4:
val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
break;
case 8:
val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
break;
}
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jingoo Han | 100 | 51.55% | 2 | 20.00% |
Kishon Vijay Abraham I | 57 | 29.38% | 3 | 30.00% |
Zhou Wang | 16 | 8.25% | 1 | 10.00% |
Gabriele Paoloni | 12 | 6.19% | 1 | 10.00% |
Björn Helgaas | 8 | 4.12% | 2 | 20.00% |
Mohit Kumar | 1 | 0.52% | 1 | 10.00% |
Total | 194 | 100.00% | 10 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kishon Vijay Abraham I | 913 | 54.57% | 10 | 26.32% |
Jingoo Han | 335 | 20.02% | 3 | 7.89% |
Joao Pinto | 149 | 8.91% | 3 | 7.89% |
JiSheng Zhang | 91 | 5.44% | 3 | 7.89% |
Gabriele Paoloni | 76 | 4.54% | 3 | 7.89% |
Björn Helgaas | 56 | 3.35% | 5 | 13.16% |
Zhou Wang | 16 | 0.96% | 1 | 2.63% |
Stanimir Varbanov | 12 | 0.72% | 1 | 2.63% |
Seungwon Jeon | 12 | 0.72% | 1 | 2.63% |
Harro Haan | 3 | 0.18% | 1 | 2.63% |
Pratyush Anand | 2 | 0.12% | 2 | 5.26% |
Niklas Cassel | 2 | 0.12% | 1 | 2.63% |
Carlos Palminha | 2 | 0.12% | 1 | 2.63% |
Murali Karicheri | 2 | 0.12% | 1 | 2.63% |
Mohit Kumar | 1 | 0.06% | 1 | 2.63% |
Lucas Stach | 1 | 0.06% | 1 | 2.63% |
Total | 1673 | 100.00% | 38 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.