Merge branches 'pci/host-aardvark', 'pci/host-altera', 'pci/host-artpec', 'pci/host-designware', 'pci/host-hv', 'pci/host-keystone', 'pci/host-rcar', 'pci/host-rockchip', 'pci/host-tegra' and 'pci/host-xilinx' into next

* pci/host-aardvark:
  PCI: aardvark: Remove redundant dev_err call in advk_pcie_probe()

* pci/host-altera:
  PCI: altera: Remove redundant platform_get_resource() return value check
  PCI: altera: Move retrain from fixup to altera_pcie_host_init()
  PCI: altera: Rework config accessors for use without a struct pci_bus
  PCI: altera: Poll for link training status after retraining the link

* pci/host-artpec:
  PCI: artpec6: Drop __init from artpec6_add_pcie_port()

* pci/host-designware:
  PCI: designware: Remove redundant platform_get_resource() return value check
  PCI: designware: Exchange viewport of `MEMORYs' and `CFGs/IOs'
  PCI: designware: Keep viewport fixed for IO transaction if num_viewport > 2
  PCI: designware: Check LTSSM training bit before deciding link is up
  PCI: designware: Add iATU Unroll feature
  PCI: designware: Wait for iATU enable
  PCI: designware: Move link wait definitions to .c file
  PCI: designware: Return data directly from dw_pcie_readl_rc()

* pci/host-hv:
  PCI: hv: Handle hv_pci_generic_compl() error case
  PCI: hv: Handle vmbus_sendpacket() failure in hv_compose_msi_msg()
  PCI: hv: Remove the unused 'wrk' in struct hv_pcibus_device
  PCI: hv: Use pci_function_description[0] in struct definitions
  PCI: hv: Use zero-length array in struct pci_packet
  PCI: hv: Use list_move_tail() instead of list_del() + list_add_tail()

* pci/host-keystone:
  PCI: keystone: Propagate request_irq() failure

* pci/host-rcar:
  PCI: rcar: Try increasing PCIe link speed to 5 GT/s at boot
  PCI: rcar: Fix some checkpatch warnings
  PCI: rcar: Add multi-MSI support
  PCI: rcar: Don't disable/unprepare clocks on prepare/enable failure
  PCI: rcar: Consolidate register space lookup and ioremap

* pci/host-rockchip:
  PCI: rockchip: Fix wrong transmitted FTS count
  PCI: rockchip: Improve the deassert sequence of four reset pins
  PCI: rockchip: Increase the Max Credit update interval
  PCI: rockchip: Add Rockchip PCIe controller support
  dt-bindings: PCI: rockchip: Add DT bindings for Rockchip PCIe controller

* pci/host-tegra:
  PCI: tegra: Use of_device_get_match_data()
  PCI: tegra: Remove redundant _data suffix

* pci/host-xilinx:
  microblaze/PCI: Add multidomain support for procfs
  PCI: xilinx: Dispose of MSI virtual IRQ
  PCI: xilinx: Clear correct MSI set bit
  PCI: xilinx: Clear interrupt register for invalid interrupt
  PCI: xilinx: Keep both legacy and MSI interrupt domain references
  PCI: xilinx-nwl: Enable all MSI interrupts using MSI mask
  PCI: xilinx-nwl: Expand error logging

Conflicts:
	drivers/pci/host/pcie-xilinx.c
This commit is contained in:
Bjorn Helgaas 2016-10-05 13:59:14 -05:00
21 changed files with 1924 additions and 223 deletions

View file

@ -17,6 +17,8 @@ Required properties:
- num-lanes: number of lanes to use
Optional properties:
- num-viewport: number of view ports configured in hardware. If a platform
does not specify it, the driver assumes 2.
- num-lanes: number of lanes to use (this property should be specified unless
the link is brought already up in BIOS)
- reset-gpio: gpio pin number of power good signal
@ -44,4 +46,5 @@ Example configuration:
interrupts = <25>, <24>;
#interrupt-cells = <1>;
num-lanes = <1>;
num-viewport = <3>;
};

View file

@ -0,0 +1,106 @@
* Rockchip AXI PCIe Root Port Bridge DT description
Required properties:
- #address-cells: Address representation for root ports, set to <3>
- #size-cells: Size representation for root ports, set to <2>
- #interrupt-cells: specifies the number of cells needed to encode an
interrupt source. The value must be 1.
- compatible: Should contain "rockchip,rk3399-pcie"
- reg: Two register ranges as listed in the reg-names property
- reg-names: Must include the following names
- "axi-base"
- "apb-base"
- clocks: Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names: Must include the following entries:
- "aclk"
- "aclk-perf"
- "hclk"
- "pm"
- msi-map: Maps a Requester ID to an MSI controller and associated
msi-specifier data. See ./pci-msi.txt
- phys: From PHY bindings: Phandle for the Generic PHY for PCIe.
- phy-names: MUST be "pcie-phy".
- interrupts: Three interrupt entries must be specified.
- interrupt-names: Must include the following names
- "sys"
- "legacy"
- "client"
- resets: Must contain five entries for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names: Must include the following names
- "core"
- "mgmt"
- "mgmt-sticky"
- "pipe"
- pinctrl-names : The pin control state names
- pinctrl-0: The "default" pinctrl state
- #interrupt-cells: specifies the number of cells needed to encode an
interrupt source. The value must be 1.
- interrupt-map-mask and interrupt-map: standard PCI properties
Optional Property:
- ep-gpios: contain the entry for pre-reset gpio
- num-lanes: number of lanes to use
- vpcie3v3-supply: The phandle to the 3.3v regulator to use for PCIe.
- vpcie1v8-supply: The phandle to the 1.8v regulator to use for PCIe.
- vpcie0v9-supply: The phandle to the 0.9v regulator to use for PCIe.
*Interrupt controller child node*
The core controller provides a single interrupt for legacy INTx. The PCIe node
should contain an interrupt controller node as a target for the PCI
'interrupt-map' property. This node represents the domain at which the four
INTx interrupts are decoded and routed.
Required properties for Interrupt controller child node:
- interrupt-controller: identifies the node as an interrupt controller
- #address-cells: specifies the number of cells needed to encode an
address. The value must be 0.
- #interrupt-cells: specifies the number of cells needed to encode an
interrupt source. The value must be 1.
Example:
pcie0: pcie@f8000000 {
compatible = "rockchip,rk3399-pcie";
#address-cells = <3>;
#size-cells = <2>;
clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>,
<&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>;
clock-names = "aclk", "aclk-perf",
"hclk", "pm";
bus-range = <0x0 0x1>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>,
<GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>,
<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "sys", "legacy", "client";
assigned-clocks = <&cru SCLK_PCIEPHY_REF>;
assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>;
assigned-clock-rates = <100000000>;
ep-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x600000
0x81000000 0x0 0xfa600000 0x0 0xfa600000 0x0 0x100000>;
num-lanes = <4>;
msi-map = <0x0 &its 0x0 0x1000>;
reg = <0x0 0xf8000000 0x0 0x2000000>, <0x0 0xfd000000 0x0 0x1000000>;
reg-names = "axi-base", "apb-base";
resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>;
reset-names = "core", "mgmt", "mgmt-sticky", "pipe";
phys = <&pcie_phy>;
phy-names = "pcie-phy";
pinctrl-names = "default";
pinctrl-0 = <&pcie_clkreq>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie0_intc 0>,
<0 0 0 2 &pcie0_intc 1>,
<0 0 0 3 &pcie0_intc 2>,
<0 0 0 4 &pcie0_intc 3>;
pcie0_intc: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};

View file

@ -9083,6 +9083,15 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
F: drivers/pci/host/pcie-hisi.c
PCIE DRIVER FOR ROCKCHIP
M: Shawn Lin <shawn.lin@rock-chips.com>
M: Wenrui Li <wenrui.li@rock-chips.com>
L: linux-pci@vger.kernel.org
L: linux-rockchip@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/pci/rockchip-pcie.txt
F: drivers/pci/host/pcie-rockchip.c
PCIE DRIVER FOR QUALCOMM MSM
M: Stanimir Varbanov <svarbanov@mm-sol.com>
L: linux-pci@vger.kernel.org

View file

@ -632,10 +632,10 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
}
}
/* Decide whether to display the domain number in /proc */
/* Display the domain number in /proc */
int pci_proc_domain(struct pci_bus *bus)
{
return 0;
return pci_domain_nr(bus);
}
/* This header fixup will do the resource fixup for all devices as they are

View file

@ -274,4 +274,15 @@ config PCIE_ARTPEC6
Say Y here to enable PCIe controller support on Axis ARTPEC-6
SoCs. This PCIe controller uses the DesignWare core.
config PCIE_ROCKCHIP
bool "Rockchip PCIe controller"
depends on ARCH_ROCKCHIP
depends on OF
depends on PCI_MSI_IRQ_DOMAIN
select MFD_SYSCON
help
Say Y here if you want internal PCI support on Rockchip SoC.
There is 1 internal PCIe port available to support GEN2 with
4 slots.
endmenu

View file

@ -31,3 +31,4 @@ obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o
obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o

View file

@ -927,10 +927,8 @@ static int advk_pcie_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pcie->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pcie->base)) {
dev_err(&pdev->dev, "Failed to map registers\n");
if (IS_ERR(pcie->base))
return PTR_ERR(pcie->base);
}
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(&pdev->dev, irq, advk_pcie_irq_handler,

View file

@ -425,12 +425,15 @@ static void exynos_pcie_enable_interrupts(struct pcie_port *pp)
exynos_pcie_msi_init(pp);
}
static inline void exynos_pcie_readl_rc(struct pcie_port *pp,
void __iomem *dbi_base, u32 *val)
static inline u32 exynos_pcie_readl_rc(struct pcie_port *pp,
void __iomem *dbi_base)
{
u32 val;
exynos_pcie_sideband_dbi_r_mode(pp, true);
*val = readl(dbi_base);
val = readl(dbi_base);
exynos_pcie_sideband_dbi_r_mode(pp, false);
return val;
}
static inline void exynos_pcie_writel_rc(struct pcie_port *pp,

View file

@ -200,11 +200,11 @@ struct tran_int_desc {
*/
struct pci_message {
u32 message_type;
u32 type;
} __packed;
struct pci_child_message {
u32 message_type;
struct pci_message message_type;
union win_slot_encoding wslot;
} __packed;
@ -222,7 +222,8 @@ struct pci_packet {
void (*completion_func)(void *context, struct pci_response *resp,
int resp_packet_size);
void *compl_ctxt;
struct pci_message message;
struct pci_message message[0];
};
/*
@ -258,7 +259,7 @@ struct pci_bus_d0_entry {
struct pci_bus_relations {
struct pci_incoming_message incoming;
u32 device_count;
struct pci_function_description func[1];
struct pci_function_description func[0];
} __packed;
struct pci_q_res_req_response {
@ -314,7 +315,7 @@ struct pci_dev_incoming {
} __packed;
struct pci_eject_response {
u32 message_type;
struct pci_message message_type;
union win_slot_encoding wslot;
u32 status;
} __packed;
@ -373,7 +374,6 @@ struct hv_pcibus_device {
struct list_head children;
struct list_head dr_list;
struct work_struct wrk;
struct msi_domain_info msi_info;
struct msi_controller msi_chip;
@ -393,7 +393,7 @@ struct hv_dr_work {
struct hv_dr_state {
struct list_head list_entry;
u32 device_count;
struct pci_function_description func[1];
struct pci_function_description func[0];
};
enum hv_pcichild_state {
@ -447,15 +447,16 @@ struct hv_pci_compl {
* for any message for which the completion packet contains a
* status and nothing else.
*/
static
void
hv_pci_generic_compl(void *context, struct pci_response *resp,
int resp_packet_size)
static void hv_pci_generic_compl(void *context, struct pci_response *resp,
int resp_packet_size)
{
struct hv_pci_compl *comp_pkt = context;
if (resp_packet_size >= offsetofend(struct pci_response, status))
comp_pkt->completion_status = resp->status;
else
comp_pkt->completion_status = -1;
complete(&comp_pkt->host_event);
}
@ -694,13 +695,12 @@ static void hv_int_desc_free(struct hv_pci_dev *hpdev,
struct pci_delete_interrupt *int_pkt;
struct {
struct pci_packet pkt;
u8 buffer[sizeof(struct pci_delete_interrupt) -
sizeof(struct pci_message)];
u8 buffer[sizeof(struct pci_delete_interrupt)];
} ctxt;
memset(&ctxt, 0, sizeof(ctxt));
int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message;
int_pkt->message_type.message_type =
int_pkt->message_type.type =
PCI_DELETE_INTERRUPT_MESSAGE;
int_pkt->wslot.slot = hpdev->desc.win_slot.slot;
int_pkt->int_desc = *int_desc;
@ -847,8 +847,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
struct cpumask *affinity;
struct {
struct pci_packet pkt;
u8 buffer[sizeof(struct pci_create_interrupt) -
sizeof(struct pci_message)];
u8 buffer[sizeof(struct pci_create_interrupt)];
} ctxt;
int cpu;
int ret;
@ -876,7 +875,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
ctxt.pkt.completion_func = hv_pci_compose_compl;
ctxt.pkt.compl_ctxt = &comp;
int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message;
int_pkt->message_type.message_type = PCI_CREATE_INTERRUPT_MESSAGE;
int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE;
int_pkt->wslot.slot = hpdev->desc.win_slot.slot;
int_pkt->int_desc.vector = cfg->vector;
int_pkt->int_desc.vector_count = 1;
@ -897,8 +896,10 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
sizeof(*int_pkt), (unsigned long)&ctxt.pkt,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (!ret)
wait_for_completion(&comp.comp_pkt.host_event);
if (ret)
goto free_int_desc;
wait_for_completion(&comp.comp_pkt.host_event);
if (comp.comp_pkt.completion_status < 0) {
dev_err(&hbus->hdev->device,
@ -1289,7 +1290,7 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
pkt.init_packet.compl_ctxt = &comp_pkt;
pkt.init_packet.completion_func = q_resource_requirements;
res_req = (struct pci_child_message *)&pkt.init_packet.message;
res_req->message_type = PCI_QUERY_RESOURCE_REQUIREMENTS;
res_req->message_type.type = PCI_QUERY_RESOURCE_REQUIREMENTS;
res_req->wslot.slot = desc->win_slot.slot;
ret = vmbus_sendpacket(hbus->hdev->channel, res_req,
@ -1466,8 +1467,7 @@ static void pci_devices_present_work(struct work_struct *work)
if (hpdev->reported_missing) {
found = true;
put_pcichild(hpdev, hv_pcidev_ref_childlist);
list_del(&hpdev->list_entry);
list_add_tail(&hpdev->list_entry, &removed);
list_move_tail(&hpdev->list_entry, &removed);
break;
}
}
@ -1558,8 +1558,7 @@ static void hv_eject_device_work(struct work_struct *work)
int wslot;
struct {
struct pci_packet pkt;
u8 buffer[sizeof(struct pci_eject_response) -
sizeof(struct pci_message)];
u8 buffer[sizeof(struct pci_eject_response)];
} ctxt;
hpdev = container_of(work, struct hv_pci_dev, wrk);
@ -1585,7 +1584,7 @@ static void hv_eject_device_work(struct work_struct *work)
memset(&ctxt, 0, sizeof(ctxt));
ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message;
ejct_pkt->message_type = PCI_EJECTION_COMPLETE;
ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE;
ejct_pkt->wslot.slot = hpdev->desc.win_slot.slot;
vmbus_sendpacket(hpdev->hbus->hdev->channel, ejct_pkt,
sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt,
@ -1688,7 +1687,7 @@ static void hv_pci_onchannelcallback(void *context)
case VM_PKT_DATA_INBAND:
new_message = (struct pci_incoming_message *)buffer;
switch (new_message->message_type.message_type) {
switch (new_message->message_type.type) {
case PCI_BUS_RELATIONS:
bus_rel = (struct pci_bus_relations *)buffer;
@ -1719,7 +1718,7 @@ static void hv_pci_onchannelcallback(void *context)
default:
dev_warn(&hbus->hdev->device,
"Unimplemented protocol message %x\n",
new_message->message_type.message_type);
new_message->message_type.type);
break;
}
break;
@ -1772,7 +1771,7 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev)
pkt->completion_func = hv_pci_generic_compl;
pkt->compl_ctxt = &comp_pkt;
version_req = (struct pci_version_request *)&pkt->message;
version_req->message_type.message_type = PCI_QUERY_PROTOCOL_VERSION;
version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION;
version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT;
ret = vmbus_sendpacket(hdev->channel, version_req,
@ -1973,7 +1972,7 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
pkt->completion_func = hv_pci_generic_compl;
pkt->compl_ctxt = &comp_pkt;
d0_entry = (struct pci_bus_d0_entry *)&pkt->message;
d0_entry->message_type.message_type = PCI_BUS_D0ENTRY;
d0_entry->message_type.type = PCI_BUS_D0ENTRY;
d0_entry->mmio_base = hbus->mem_config->start;
ret = vmbus_sendpacket(hdev->channel, d0_entry, sizeof(*d0_entry),
@ -2019,7 +2018,7 @@ static int hv_pci_query_relations(struct hv_device *hdev)
return -ENOTEMPTY;
memset(&message, 0, sizeof(message));
message.message_type = PCI_QUERY_BUS_RELATIONS;
message.type = PCI_QUERY_BUS_RELATIONS;
ret = vmbus_sendpacket(hdev->channel, &message, sizeof(message),
0, VM_PKT_DATA_INBAND, 0);
@ -2072,8 +2071,8 @@ static int hv_send_resources_allocated(struct hv_device *hdev)
init_completion(&comp_pkt.host_event);
pkt->completion_func = hv_pci_generic_compl;
pkt->compl_ctxt = &comp_pkt;
pkt->message.message_type = PCI_RESOURCES_ASSIGNED;
res_assigned = (struct pci_resources_assigned *)&pkt->message;
res_assigned->message_type.type = PCI_RESOURCES_ASSIGNED;
res_assigned->wslot.slot = hpdev->desc.win_slot.slot;
put_pcichild(hpdev, hv_pcidev_ref_by_slot);
@ -2123,7 +2122,7 @@ static int hv_send_resources_released(struct hv_device *hdev)
continue;
memset(&pkt, 0, sizeof(pkt));
pkt.message_type = PCI_RESOURCES_RELEASED;
pkt.message_type.type = PCI_RESOURCES_RELEASED;
pkt.wslot.slot = hpdev->desc.win_slot.slot;
put_pcichild(hpdev, hv_pcidev_ref_by_slot);
@ -2290,7 +2289,7 @@ static int hv_pci_remove(struct hv_device *hdev)
init_completion(&comp_pkt.host_event);
pkt.teardown_packet.completion_func = hv_pci_generic_compl;
pkt.teardown_packet.compl_ctxt = &comp_pkt;
pkt.teardown_packet.message.message_type = PCI_BUS_D0EXIT;
pkt.teardown_packet.message[0].type = PCI_BUS_D0EXIT;
ret = vmbus_sendpacket(hdev->channel, &pkt.teardown_packet.message,
sizeof(struct pci_message),

View file

@ -334,8 +334,9 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
if (ks_pcie->error_irq <= 0)
dev_info(&pdev->dev, "no error IRQ defined\n");
else {
if (request_irq(ks_pcie->error_irq, pcie_err_irq_handler,
IRQF_SHARED, "pcie-error-irq", ks_pcie) < 0) {
ret = request_irq(ks_pcie->error_irq, pcie_err_irq_handler,
IRQF_SHARED, "pcie-error-irq", ks_pcie);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request error IRQ %d\n",
ks_pcie->error_irq);
return ret;

View file

@ -240,7 +240,7 @@ struct tegra_msi {
};
/* used to differentiate between Tegra SoC generations */
struct tegra_pcie_soc_data {
struct tegra_pcie_soc {
unsigned int num_ports;
unsigned int msi_base_shift;
u32 pads_pll_ctl;
@ -300,7 +300,7 @@ struct tegra_pcie {
struct regulator_bulk_data *supplies;
unsigned int num_supplies;
const struct tegra_pcie_soc_data *soc_data;
const struct tegra_pcie_soc *soc;
struct dentry *debugfs;
};
@ -542,8 +542,8 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
{
const struct tegra_pcie_soc_data *soc = port->pcie->soc_data;
unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
const struct tegra_pcie_soc *soc = port->pcie->soc;
unsigned long value;
/* enable reference clock */
@ -562,8 +562,8 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
static void tegra_pcie_port_disable(struct tegra_pcie_port *port)
{
const struct tegra_pcie_soc_data *soc = port->pcie->soc_data;
unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
const struct tegra_pcie_soc *soc = port->pcie->soc;
unsigned long value;
/* assert port reset */
@ -777,7 +777,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
u32 value;
timeout = jiffies + msecs_to_jiffies(timeout);
@ -793,7 +793,7 @@ static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout)
static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
u32 value;
int err;
@ -848,7 +848,7 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
static int tegra_pcie_phy_disable(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
u32 value;
/* disable TX/RX data */
@ -909,7 +909,7 @@ static int tegra_pcie_port_phy_power_off(struct tegra_pcie_port *port)
static int tegra_pcie_phy_power_on(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
struct tegra_pcie_port *port;
int err;
@ -977,7 +977,7 @@ static int tegra_pcie_phy_power_off(struct tegra_pcie *pcie)
static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
struct tegra_pcie_port *port;
unsigned long value;
int err;
@ -1070,7 +1070,7 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
static int tegra_pcie_power_on(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
int err;
reset_control_assert(pcie->pcie_xrst);
@ -1120,7 +1120,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
pcie->pex_clk = devm_clk_get(pcie->dev, "pex");
if (IS_ERR(pcie->pex_clk))
@ -1237,7 +1237,7 @@ static int tegra_pcie_port_get_phys(struct tegra_pcie_port *port)
static int tegra_pcie_phys_get(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
struct device_node *np = pcie->dev->of_node;
struct tegra_pcie_port *port;
int err;
@ -1489,7 +1489,7 @@ static const struct irq_domain_ops msi_domain_ops = {
static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
{
struct platform_device *pdev = to_platform_device(pcie->dev);
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
const struct tegra_pcie_soc *soc = pcie->soc;
struct tegra_msi *msi = &pcie->msi;
unsigned long base;
int err;
@ -1802,8 +1802,8 @@ static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
struct device_node *np = pcie->dev->of_node, *port;
const struct tegra_pcie_soc *soc = pcie->soc;
struct of_pci_range_parser parser;
struct of_pci_range range;
u32 lanes = 0, mask = 0;
@ -2046,7 +2046,7 @@ static int tegra_pcie_enable(struct tegra_pcie *pcie)
return 0;
}
static const struct tegra_pcie_soc_data tegra20_pcie_data = {
static const struct tegra_pcie_soc tegra20_pcie = {
.num_ports = 2,
.msi_base_shift = 0,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA20,
@ -2059,7 +2059,7 @@ static const struct tegra_pcie_soc_data tegra20_pcie_data = {
.has_gen2 = false,
};
static const struct tegra_pcie_soc_data tegra30_pcie_data = {
static const struct tegra_pcie_soc tegra30_pcie = {
.num_ports = 3,
.msi_base_shift = 8,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
@ -2073,7 +2073,7 @@ static const struct tegra_pcie_soc_data tegra30_pcie_data = {
.has_gen2 = false,
};
static const struct tegra_pcie_soc_data tegra124_pcie_data = {
static const struct tegra_pcie_soc tegra124_pcie = {
.num_ports = 2,
.msi_base_shift = 8,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
@ -2087,9 +2087,9 @@ static const struct tegra_pcie_soc_data tegra124_pcie_data = {
};
static const struct of_device_id tegra_pcie_of_match[] = {
{ .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie_data },
{ .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie_data },
{ .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie_data },
{ .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie },
{ .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie },
{ .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie },
{ },
};
@ -2204,21 +2204,16 @@ remove:
static int tegra_pcie_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct tegra_pcie *pcie;
int err;
match = of_match_device(tegra_pcie_of_match, &pdev->dev);
if (!match)
return -ENODEV;
pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
return -ENOMEM;
pcie->soc = of_device_get_match_data(&pdev->dev);
INIT_LIST_HEAD(&pcie->buses);
INIT_LIST_HEAD(&pcie->ports);
pcie->soc_data = match->data;
pcie->dev = &pdev->dev;
err = tegra_pcie_parse_dt(pcie);

View file

@ -241,11 +241,6 @@ static int altera_msi_probe(struct platform_device *pdev)
msi->pdev = pdev;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr");
if (!res) {
dev_err(&pdev->dev, "no csr memory resource defined\n");
return -ENODEV;
}
msi->csr_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(msi->csr_base)) {
dev_err(&pdev->dev, "failed to map csr memory\n");
@ -254,11 +249,6 @@ static int altera_msi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"vector_slave");
if (!res) {
dev_err(&pdev->dev, "no vector_slave memory resource defined\n");
return -ENODEV;
}
msi->vector_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(msi->vector_base)) {
dev_err(&pdev->dev, "failed to map vector_slave memory\n");

View file

@ -46,6 +46,7 @@
#define RP_LTSSM_MASK 0x1f
#define LTSSM_L0 0xf
#define PCIE_CAP_OFFSET 0x80
/* TLP configuration type 0 and 1 */
#define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */
#define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */
@ -64,7 +65,8 @@
#define TLP_LOOP 500
#define RP_DEVFN 0
#define LINK_UP_TIMEOUT 5000
#define LINK_UP_TIMEOUT HZ
#define LINK_RETRAIN_TIMEOUT HZ
#define INTX_NUM 4
@ -102,38 +104,6 @@ static bool altera_pcie_link_is_up(struct altera_pcie *pcie)
return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0);
}
static void altera_pcie_retrain(struct pci_dev *dev)
{
u16 linkcap, linkstat;
struct altera_pcie *pcie = dev->bus->sysdata;
int timeout = 0;
if (!altera_pcie_link_is_up(pcie))
return;
/*
* Set the retrain bit if the PCIe rootport support > 2.5GB/s, but
* current speed is 2.5 GB/s.
*/
pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap);
if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
return;
pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat);
if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) {
pcie_capability_set_word(dev, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_RL);
while (!altera_pcie_link_is_up(pcie)) {
timeout++;
if (timeout > LINK_UP_TIMEOUT)
break;
udelay(5);
}
}
}
DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain);
/*
* Altera PCIe port uses BAR0 of RC's configuration space as the translation
* from PCI bus to native BUS. Entire DDR region is mapped into PCIe space
@ -297,22 +267,14 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn,
return PCIBIOS_SUCCESSFUL;
}
static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *value)
static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno,
unsigned int devfn, int where, int size,
u32 *value)
{
struct altera_pcie *pcie = bus->sysdata;
int ret;
u32 data;
u8 byte_en;
if (altera_pcie_hide_rc_bar(bus, devfn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) {
*value = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
switch (size) {
case 1:
byte_en = 1 << (where & 3);
@ -325,7 +287,7 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
break;
}
ret = tlp_cfg_dword_read(pcie, bus->number, devfn,
ret = tlp_cfg_dword_read(pcie, busno, devfn,
(where & ~DWORD_MASK), byte_en, &data);
if (ret != PCIBIOS_SUCCESSFUL)
return ret;
@ -345,20 +307,14 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_SUCCESSFUL;
}
static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 value)
static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno,
unsigned int devfn, int where, int size,
u32 value)
{
struct altera_pcie *pcie = bus->sysdata;
u32 data32;
u32 shift = 8 * (where & 3);
u8 byte_en;
if (altera_pcie_hide_rc_bar(bus, devfn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn)))
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
case 1:
data32 = (value & 0xff) << shift;
@ -374,8 +330,40 @@ static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
break;
}
return tlp_cfg_dword_write(pcie, bus->number, devfn,
(where & ~DWORD_MASK), byte_en, data32);
return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK),
byte_en, data32);
}
static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *value)
{
struct altera_pcie *pcie = bus->sysdata;
if (altera_pcie_hide_rc_bar(bus, devfn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) {
*value = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
return _altera_pcie_cfg_read(pcie, bus->number, devfn, where, size,
value);
}
static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 value)
{
struct altera_pcie *pcie = bus->sysdata;
if (altera_pcie_hide_rc_bar(bus, devfn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn)))
return PCIBIOS_DEVICE_NOT_FOUND;
return _altera_pcie_cfg_write(pcie, bus->number, devfn, where, size,
value);
}
static struct pci_ops altera_pcie_ops = {
@ -383,6 +371,90 @@ static struct pci_ops altera_pcie_ops = {
.write = altera_pcie_cfg_write,
};
static int altera_read_cap_word(struct altera_pcie *pcie, u8 busno,
unsigned int devfn, int offset, u16 *value)
{
u32 data;
int ret;
ret = _altera_pcie_cfg_read(pcie, busno, devfn,
PCIE_CAP_OFFSET + offset, sizeof(*value),
&data);
*value = data;
return ret;
}
static int altera_write_cap_word(struct altera_pcie *pcie, u8 busno,
unsigned int devfn, int offset, u16 value)
{
return _altera_pcie_cfg_write(pcie, busno, devfn,
PCIE_CAP_OFFSET + offset, sizeof(value),
value);
}
static void altera_wait_link_retrain(struct altera_pcie *pcie)
{
u16 reg16;
unsigned long start_jiffies;
/* Wait for link training end. */
start_jiffies = jiffies;
for (;;) {
altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
PCI_EXP_LNKSTA, &reg16);
if (!(reg16 & PCI_EXP_LNKSTA_LT))
break;
if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) {
dev_err(&pcie->pdev->dev, "link retrain timeout\n");
break;
}
udelay(100);
}
/* Wait for link is up */
start_jiffies = jiffies;
for (;;) {
if (altera_pcie_link_is_up(pcie))
break;
if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) {
dev_err(&pcie->pdev->dev, "link up timeout\n");
break;
}
udelay(100);
}
}
static void altera_pcie_retrain(struct altera_pcie *pcie)
{
u16 linkcap, linkstat, linkctl;
if (!altera_pcie_link_is_up(pcie))
return;
/*
* Set the retrain bit if the PCIe rootport support > 2.5GB/s, but
* current speed is 2.5 GB/s.
*/
altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKCAP,
&linkcap);
if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
return;
altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKSTA,
&linkstat);
if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) {
altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
PCI_EXP_LNKCTL, &linkctl);
linkctl |= PCI_EXP_LNKCTL_RL;
altera_write_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
PCI_EXP_LNKCTL, linkctl);
altera_wait_link_retrain(pcie);
}
}
static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq)
{
@ -504,6 +576,11 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie)
return 0;
}
static void altera_pcie_host_init(struct altera_pcie *pcie)
{
altera_pcie_retrain(pcie);
}
static int altera_pcie_probe(struct platform_device *pdev)
{
struct altera_pcie *pcie;
@ -541,6 +618,7 @@ static int altera_pcie_probe(struct platform_device *pdev)
cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS);
/* enable all interrupts */
cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE);
altera_pcie_host_init(pcie);
bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops,
pcie, &pcie->resources);

View file

@ -191,8 +191,8 @@ static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg)
return dw_handle_msi_irq(pp);
}
static int __init artpec6_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev)
static int artpec6_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev)
{
int ret;

View file

@ -100,9 +100,6 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
pp->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
dw_plat_pcie->mem_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dw_plat_pcie->mem_base))
return PTR_ERR(dw_plat_pcie->mem_base);

View file

@ -25,7 +25,17 @@
#include "pcie-designware.h"
/* Synopsis specific PCIE configuration registers */
/* Parameters for the waiting for link up routine */
#define LINK_WAIT_MAX_RETRIES 10
#define LINK_WAIT_USLEEP_MIN 90000
#define LINK_WAIT_USLEEP_MAX 100000
/* Parameters for the waiting for iATU enabled routine */
#define LINK_WAIT_MAX_IATU_RETRIES 5
#define LINK_WAIT_IATU_MIN 9000
#define LINK_WAIT_IATU_MAX 10000
/* Synopsys-specific PCIe configuration registers */
#define PCIE_PORT_LINK_CONTROL 0x710
#define PORT_LINK_MODE_MASK (0x3f << 16)
#define PORT_LINK_MODE_1_LANES (0x1 << 16)
@ -50,6 +60,7 @@
#define PCIE_ATU_VIEWPORT 0x900
#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
#define PCIE_ATU_REGION_INDEX2 (0x2 << 0)
#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
#define PCIE_ATU_CR1 0x904
@ -69,10 +80,26 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
/*
* iATU Unroll-specific register definitions
* From 4.80 core version the address translation will be made by unroll
*/
#define PCIE_ATU_UNR_REGION_CTRL1 0x00
#define PCIE_ATU_UNR_REGION_CTRL2 0x04
#define PCIE_ATU_UNR_LOWER_BASE 0x08
#define PCIE_ATU_UNR_UPPER_BASE 0x0C
#define PCIE_ATU_UNR_LIMIT 0x10
#define PCIE_ATU_UNR_LOWER_TARGET 0x14
#define PCIE_ATU_UNR_UPPER_TARGET 0x18
/* Register address builder */
#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((0x3 << 20) | (region << 9))
/* PCIe Port Logic registers */
#define PLR_OFFSET 0x700
#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
#define PCIE_PHY_DEBUG_R1_LINK_UP 0x00000010
#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4)
#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
static struct pci_ops dw_pcie_ops;
@ -114,12 +141,12 @@ int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val)
return PCIBIOS_SUCCESSFUL;
}
static inline void dw_pcie_readl_rc(struct pcie_port *pp, u32 reg, u32 *val)
static inline u32 dw_pcie_readl_rc(struct pcie_port *pp, u32 reg)
{
if (pp->ops->readl_rc)
pp->ops->readl_rc(pp, pp->dbi_base + reg, val);
else
*val = readl(pp->dbi_base + reg);
return pp->ops->readl_rc(pp, pp->dbi_base + reg);
return readl(pp->dbi_base + reg);
}
static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg)
@ -130,6 +157,27 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg)
writel(val, pp->dbi_base + reg);
}
static inline u32 dw_pcie_readl_unroll(struct pcie_port *pp, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
if (pp->ops->readl_rc)
return pp->ops->readl_rc(pp, pp->dbi_base + offset + reg);
return readl(pp->dbi_base + offset + reg);
}
static inline void dw_pcie_writel_unroll(struct pcie_port *pp, u32 index,
u32 val, u32 reg)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
if (pp->ops->writel_rc)
pp->ops->writel_rc(pp, val, pp->dbi_base + offset + reg);
else
writel(val, pp->dbi_base + offset + reg);
}
static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
u32 *val)
{
@ -151,24 +199,57 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
int type, u64 cpu_addr, u64 pci_addr, u32 size)
{
u32 val;
u32 retries, val;
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
PCIE_ATU_VIEWPORT);
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE);
dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr), PCIE_ATU_UPPER_BASE);
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1),
PCIE_ATU_LIMIT);
dw_pcie_writel_rc(pp, lower_32_bits(pci_addr), PCIE_ATU_LOWER_TARGET);
dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET);
dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
if (pp->iatu_unroll_enabled) {
dw_pcie_writel_unroll(pp, index,
lower_32_bits(cpu_addr), PCIE_ATU_UNR_LOWER_BASE);
dw_pcie_writel_unroll(pp, index,
upper_32_bits(cpu_addr), PCIE_ATU_UNR_UPPER_BASE);
dw_pcie_writel_unroll(pp, index,
lower_32_bits(cpu_addr + size - 1), PCIE_ATU_UNR_LIMIT);
dw_pcie_writel_unroll(pp, index,
lower_32_bits(pci_addr), PCIE_ATU_UNR_LOWER_TARGET);
dw_pcie_writel_unroll(pp, index,
upper_32_bits(pci_addr), PCIE_ATU_UNR_UPPER_TARGET);
dw_pcie_writel_unroll(pp, index,
type, PCIE_ATU_UNR_REGION_CTRL1);
dw_pcie_writel_unroll(pp, index,
PCIE_ATU_ENABLE, PCIE_ATU_UNR_REGION_CTRL2);
} else {
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
PCIE_ATU_VIEWPORT);
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr),
PCIE_ATU_LOWER_BASE);
dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr),
PCIE_ATU_UPPER_BASE);
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1),
PCIE_ATU_LIMIT);
dw_pcie_writel_rc(pp, lower_32_bits(pci_addr),
PCIE_ATU_LOWER_TARGET);
dw_pcie_writel_rc(pp, upper_32_bits(pci_addr),
PCIE_ATU_UPPER_TARGET);
dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
}
/*
* Make sure ATU enable takes effect before any subsequent config
* and I/O accesses.
*/
dw_pcie_readl_rc(pp, PCIE_ATU_CR2, &val);
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
if (pp->iatu_unroll_enabled)
val = dw_pcie_readl_unroll(pp, index,
PCIE_ATU_UNR_REGION_CTRL2);
else
val = dw_pcie_readl_rc(pp, PCIE_ATU_CR2);
if (val == PCIE_ATU_ENABLE)
return;
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
}
dev_err(pp->dev, "iATU is not being enabled\n");
}
static struct irq_chip dw_msi_irq_chip = {
@ -411,7 +492,8 @@ int dw_pcie_link_up(struct pcie_port *pp)
return pp->ops->link_up(pp);
val = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
return val & PCIE_PHY_DEBUG_R1_LINK_UP;
return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) &&
(!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)));
}
static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
@ -427,6 +509,17 @@ static const struct irq_domain_ops msi_domain_ops = {
.map = dw_pcie_msi_map,
};
static u8 dw_pcie_iatu_unroll_enabled(struct pcie_port *pp)
{
u32 val;
val = dw_pcie_readl_rc(pp, PCIE_ATU_VIEWPORT);
if (val == 0xffffffff)
return 1;
return 0;
}
int dw_pcie_host_init(struct pcie_port *pp)
{
struct device_node *np = pp->dev->of_node;
@ -526,6 +619,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (ret)
pp->lanes = 0;
ret = of_property_read_u32(np, "num-viewport", &pp->num_viewport);
if (ret)
pp->num_viewport = 2;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
if (!pp->ops->msi_host_init) {
pp->irq_domain = irq_domain_add_linear(pp->dev->of_node,
@ -546,6 +643,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
}
}
pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp);
if (pp->ops->host_init)
pp->ops->host_init(pp);
@ -611,13 +710,14 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
va_cfg_base = pp->va_cfg1_base;
}
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
type, cpu_addr,
busdev, cfg_size);
ret = dw_pcie_cfg_read(va_cfg_base + where, size, val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
if (pp->num_viewport <= 2)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
return ret;
}
@ -648,13 +748,14 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
va_cfg_base = pp->va_cfg1_base;
}
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
type, cpu_addr,
busdev, cfg_size);
ret = dw_pcie_cfg_write(va_cfg_base + where, size, val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
if (pp->num_viewport <= 2)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
return ret;
}
@ -715,7 +816,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
u32 val;
/* set the number of lanes */
dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val);
val = dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL);
val &= ~PORT_LINK_MODE_MASK;
switch (pp->lanes) {
case 1:
@ -737,7 +838,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
/* set link width speed control register */
dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, &val);
val = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL);
val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
switch (pp->lanes) {
case 1:
@ -760,19 +861,19 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1);
/* setup interrupt pins */
dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE, &val);
val = dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE);
val &= 0xffff00ff;
val |= 0x00000100;
dw_pcie_writel_rc(pp, val, PCI_INTERRUPT_LINE);
/* setup bus numbers */
dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS, &val);
val = dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS);
val &= 0xff000000;
val |= 0x00010100;
dw_pcie_writel_rc(pp, val, PCI_PRIMARY_BUS);
/* setup command register */
dw_pcie_readl_rc(pp, PCI_COMMAND, &val);
val = dw_pcie_readl_rc(pp, PCI_COMMAND);
val &= 0xffff0000;
val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
@ -783,10 +884,15 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
* uses its own address translation component rather than ATU, so
* we should not program the ATU here.
*/
if (!pp->ops->rd_other_conf)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
if (!pp->ops->rd_other_conf) {
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_MEM, pp->mem_base,
pp->mem_bus_addr, pp->mem_size);
if (pp->num_viewport > 2)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX2,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
}
dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);

View file

@ -22,11 +22,6 @@
#define MAX_MSI_IRQS 32
#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32)
/* Parameters for the waiting for link up routine */
#define LINK_WAIT_MAX_RETRIES 10
#define LINK_WAIT_USLEEP_MIN 90000
#define LINK_WAIT_USLEEP_MAX 100000
struct pcie_port {
struct device *dev;
u8 root_bus_nr;
@ -49,16 +44,17 @@ struct pcie_port {
struct resource *busn;
int irq;
u32 lanes;
u32 num_viewport;
struct pcie_host_ops *ops;
int msi_irq;
struct irq_domain *irq_domain;
unsigned long msi_data;
u8 iatu_unroll_enabled;
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
};
struct pcie_host_ops {
void (*readl_rc)(struct pcie_port *pp,
void __iomem *dbi_base, u32 *val);
u32 (*readl_rc)(struct pcie_port *pp, void __iomem *dbi_base);
void (*writel_rc)(struct pcie_port *pp,
u32 val, void __iomem *dbi_base);
int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);

View file

@ -84,8 +84,18 @@
#define IDSETR1 0x011004
#define TLCTLR 0x011048
#define MACSR 0x011054
#define SPCHGFIN (1 << 4)
#define SPCHGFAIL (1 << 6)
#define SPCHGSUC (1 << 7)
#define LINK_SPEED (0xf << 16)
#define LINK_SPEED_2_5GTS (1 << 16)
#define LINK_SPEED_5_0GTS (2 << 16)
#define MACCTLR 0x011058
#define SPEED_CHANGE (1 << 24)
#define SCRAMBLE_DISABLE (1 << 27)
#define MACS2R 0x011078
#define MACCGSPSETR 0x011084
#define SPCNGRSN (1 << 31)
/* R-Car H1 PHY */
#define H1_PCIEPHYADRR 0x04000c
@ -385,11 +395,67 @@ static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
return 1;
}
static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
{
unsigned int timeout = 1000;
u32 macsr;
if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) != LINK_SPEED_5_0GTS)
return;
if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) {
dev_err(pcie->dev, "Speed change already in progress\n");
return;
}
macsr = rcar_pci_read_reg(pcie, MACSR);
if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS)
goto done;
/* Set target link speed to 5.0 GT/s */
rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
PCI_EXP_LNKSTA_CLS_5_0GB);
/* Set speed change reason as intentional factor */
rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0);
/* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */
if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL))
rcar_pci_write_reg(pcie, macsr, MACSR);
/* Start link speed change */
rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);
while (timeout--) {
macsr = rcar_pci_read_reg(pcie, MACSR);
if (macsr & SPCHGFIN) {
/* Clear the interrupt bits */
rcar_pci_write_reg(pcie, macsr, MACSR);
if (macsr & SPCHGFAIL)
dev_err(pcie->dev, "Speed change failed\n");
goto done;
}
msleep(1);
};
dev_err(pcie->dev, "Speed change timed out\n");
done:
dev_info(pcie->dev, "Current link speed is %s GT/s\n",
(macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5");
}
static int rcar_pcie_enable(struct rcar_pcie *pcie)
{
struct pci_bus *bus, *child;
LIST_HEAD(res);
/* Try setting 5 GT/s link speed */
rcar_pcie_force_speedup(pcie);
rcar_pcie_setup(&res, pcie);
pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
@ -608,6 +674,18 @@ static int rcar_msi_alloc(struct rcar_msi *chip)
return msi;
}
static int rcar_msi_alloc_region(struct rcar_msi *chip, int no_irqs)
{
int msi;
mutex_lock(&chip->lock);
msi = bitmap_find_free_region(chip->used, INT_PCI_MSI_NR,
order_base_2(no_irqs));
mutex_unlock(&chip->lock);
return msi;
}
static void rcar_msi_free(struct rcar_msi *chip, unsigned long irq)
{
mutex_lock(&chip->lock);
@ -665,7 +743,7 @@ static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
if (hwirq < 0)
return hwirq;
irq = irq_create_mapping(msi->domain, hwirq);
irq = irq_find_mapping(msi->domain, hwirq);
if (!irq) {
rcar_msi_free(msi, hwirq);
return -EINVAL;
@ -682,6 +760,58 @@ static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
return 0;
}
static int rcar_msi_setup_irqs(struct msi_controller *chip,
struct pci_dev *pdev, int nvec, int type)
{
struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip);
struct rcar_msi *msi = to_rcar_msi(chip);
struct msi_desc *desc;
struct msi_msg msg;
unsigned int irq;
int hwirq;
int i;
/* MSI-X interrupts are not supported */
if (type == PCI_CAP_ID_MSIX)
return -EINVAL;
WARN_ON(!list_is_singular(&pdev->dev.msi_list));
desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list);
hwirq = rcar_msi_alloc_region(msi, nvec);
if (hwirq < 0)
return -ENOSPC;
irq = irq_find_mapping(msi->domain, hwirq);
if (!irq)
return -ENOSPC;
for (i = 0; i < nvec; i++) {
/*
* irq_create_mapping() called from rcar_pcie_probe() pre-
* allocates descs, so there is no need to allocate descs here.
* We can therefore assume that if irq_find_mapping() above
* returns non-zero, then the descs are also successfully
* allocated.
*/
if (irq_set_msi_desc_off(irq, i, desc)) {
/* TODO: clear */
return -EINVAL;
}
}
desc->nvec_used = nvec;
desc->msi_attrib.multiple = order_base_2(nvec);
msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
msg.data = hwirq;
pci_write_msi_msg(irq, &msg);
return 0;
}
static void rcar_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
{
struct rcar_msi *msi = to_rcar_msi(chip);
@ -716,12 +846,13 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
struct platform_device *pdev = to_platform_device(pcie->dev);
struct rcar_msi *msi = &pcie->msi;
unsigned long base;
int err;
int err, i;
mutex_init(&msi->lock);
msi->chip.dev = pcie->dev;
msi->chip.setup_irq = rcar_msi_setup_irq;
msi->chip.setup_irqs = rcar_msi_setup_irqs;
msi->chip.teardown_irq = rcar_msi_teardown_irq;
msi->domain = irq_domain_add_linear(pcie->dev->of_node, INT_PCI_MSI_NR,
@ -731,6 +862,9 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
return -ENOMEM;
}
for (i = 0; i < INT_PCI_MSI_NR; i++)
irq_create_mapping(msi->domain, i);
/* Two irqs are for MSI, but they are also used for non-MSI irqs */
err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq,
IRQF_SHARED | IRQF_NO_THREAD,
@ -775,6 +909,10 @@ static int rcar_pcie_get_resources(struct platform_device *pdev,
if (err)
return err;
pcie->base = devm_ioremap_resource(&pdev->dev, &res);
if (IS_ERR(pcie->base))
return PTR_ERR(pcie->base);
pcie->clk = devm_clk_get(&pdev->dev, "pcie");
if (IS_ERR(pcie->clk)) {
dev_err(pcie->dev, "cannot get platform clock\n");
@ -782,7 +920,7 @@ static int rcar_pcie_get_resources(struct platform_device *pdev,
}
err = clk_prepare_enable(pcie->clk);
if (err)
goto fail_clk;
return err;
pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus");
if (IS_ERR(pcie->bus_clk)) {
@ -792,7 +930,7 @@ static int rcar_pcie_get_resources(struct platform_device *pdev,
}
err = clk_prepare_enable(pcie->bus_clk);
if (err)
goto err_map_reg;
goto fail_clk;
i = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (!i) {
@ -810,12 +948,6 @@ static int rcar_pcie_get_resources(struct platform_device *pdev,
}
pcie->msi.irq2 = i;
pcie->base = devm_ioremap_resource(&pdev->dev, &res);
if (IS_ERR(pcie->base)) {
err = PTR_ERR(pcie->base);
goto err_map_reg;
}
return 0;
err_map_reg:
@ -865,12 +997,16 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
* Set up 64-bit inbound regions as the range parser doesn't
* distinguish between 32 and 64-bit types.
*/
rcar_pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx));
rcar_pci_write_reg(pcie, lower_32_bits(pci_addr),
PCIEPRAR(idx));
rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx));
rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags,
PCIELAMR(idx));
rcar_pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1));
rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1));
rcar_pci_write_reg(pcie, upper_32_bits(pci_addr),
PCIEPRAR(idx + 1));
rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr),
PCIELAR(idx + 1));
rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
pci_addr += size;
@ -919,6 +1055,7 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie,
/* Get the dma-ranges from DT */
for_each_of_pci_range(&parser, &range) {
u64 end = range.cpu_addr + range.size - 1;
dev_dbg(pcie->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n",
range.flags, range.cpu_addr, end, range.pci_addr);
@ -932,9 +1069,12 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie,
static const struct of_device_id rcar_pcie_of_match[] = {
{ .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 },
{ .compatible = "renesas,pcie-rcar-gen2", .data = rcar_pcie_hw_init_gen2 },
{ .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init_gen2 },
{ .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init_gen2 },
{ .compatible = "renesas,pcie-rcar-gen2",
.data = rcar_pcie_hw_init_gen2 },
{ .compatible = "renesas,pcie-r8a7790",
.data = rcar_pcie_hw_init_gen2 },
{ .compatible = "renesas,pcie-r8a7791",
.data = rcar_pcie_hw_init_gen2 },
{ .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init },
{},
};
@ -947,7 +1087,8 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci)
resource_size_t iobase;
struct resource_entry *win, *tmp;
err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase);
err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
&iobase);
if (err)
return err;
@ -1001,8 +1142,8 @@ static int rcar_pcie_probe(struct platform_device *pdev)
return err;
}
err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node);
if (err)
err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node);
if (err)
return err;
of_id = of_match_device(rcar_pcie_of_match, pcie->dev);

File diff suppressed because it is too large Load diff

View file

@ -85,10 +85,15 @@
#define MSGF_MISC_SR_MASTER_ERR BIT(5)
#define MSGF_MISC_SR_I_ADDR_ERR BIT(6)
#define MSGF_MISC_SR_E_ADDR_ERR BIT(7)
#define MSGF_MISC_SR_UR_DETECT BIT(20)
#define MSGF_MISC_SR_PCIE_CORE GENMASK(18, 16)
#define MSGF_MISC_SR_PCIE_CORE_ERR GENMASK(31, 22)
#define MSGF_MISC_SR_FATAL_AER BIT(16)
#define MSGF_MISC_SR_NON_FATAL_AER BIT(17)
#define MSGF_MISC_SR_CORR_AER BIT(18)
#define MSGF_MISC_SR_UR_DETECT BIT(20)
#define MSGF_MISC_SR_NON_FATAL_DEV BIT(22)
#define MSGF_MISC_SR_FATAL_DEV BIT(23)
#define MSGF_MISC_SR_LINK_DOWN BIT(24)
#define MSGF_MSIC_SR_LINK_AUTO_BWIDTH BIT(25)
#define MSGF_MSIC_SR_LINK_BWIDTH BIT(26)
#define MSGF_MISC_SR_MASKALL (MSGF_MISC_SR_RXMSG_AVAIL | \
MSGF_MISC_SR_RXMSG_OVER | \
@ -96,9 +101,15 @@
MSGF_MISC_SR_MASTER_ERR | \
MSGF_MISC_SR_I_ADDR_ERR | \
MSGF_MISC_SR_E_ADDR_ERR | \
MSGF_MISC_SR_FATAL_AER | \
MSGF_MISC_SR_NON_FATAL_AER | \
MSGF_MISC_SR_CORR_AER | \
MSGF_MISC_SR_UR_DETECT | \
MSGF_MISC_SR_PCIE_CORE | \
MSGF_MISC_SR_PCIE_CORE_ERR)
MSGF_MISC_SR_NON_FATAL_DEV | \
MSGF_MISC_SR_FATAL_DEV | \
MSGF_MISC_SR_LINK_DOWN | \
MSGF_MSIC_SR_LINK_AUTO_BWIDTH | \
MSGF_MSIC_SR_LINK_BWIDTH)
/* Legacy interrupt status mask bits */
#define MSGF_LEG_SR_INTA BIT(0)
@ -109,8 +120,8 @@
MSGF_LEG_SR_INTC | MSGF_LEG_SR_INTD)
/* MSI interrupt status mask bits */
#define MSGF_MSI_SR_LO_MASK BIT(0)
#define MSGF_MSI_SR_HI_MASK BIT(0)
#define MSGF_MSI_SR_LO_MASK GENMASK(31, 0)
#define MSGF_MSI_SR_HI_MASK GENMASK(31, 0)
#define MSII_PRESENT BIT(0)
#define MSII_ENABLE BIT(0)
@ -291,8 +302,29 @@ static irqreturn_t nwl_pcie_misc_handler(int irq, void *data)
dev_err(pcie->dev,
"In Misc Egress address translation error\n");
if (misc_stat & MSGF_MISC_SR_PCIE_CORE_ERR)
dev_err(pcie->dev, "PCIe Core error\n");
if (misc_stat & MSGF_MISC_SR_FATAL_AER)
dev_err(pcie->dev, "Fatal Error in AER Capability\n");
if (misc_stat & MSGF_MISC_SR_NON_FATAL_AER)
dev_err(pcie->dev, "Non-Fatal Error in AER Capability\n");
if (misc_stat & MSGF_MISC_SR_CORR_AER)
dev_err(pcie->dev, "Correctable Error in AER Capability\n");
if (misc_stat & MSGF_MISC_SR_UR_DETECT)
dev_err(pcie->dev, "Unsupported request Detected\n");
if (misc_stat & MSGF_MISC_SR_NON_FATAL_DEV)
dev_err(pcie->dev, "Non-Fatal Error Detected\n");
if (misc_stat & MSGF_MISC_SR_FATAL_DEV)
dev_err(pcie->dev, "Fatal Error Detected\n");
if (misc_stat & MSGF_MSIC_SR_LINK_AUTO_BWIDTH)
dev_info(pcie->dev, "Link Autonomous Bandwidth Management Status bit set\n");
if (misc_stat & MSGF_MSIC_SR_LINK_BWIDTH)
dev_info(pcie->dev, "Link Bandwidth Management Status bit set\n");
/* Clear misc interrupt status */
nwl_bridge_writel(pcie, misc_stat, MSGF_MISC_STATUS);

View file

@ -101,7 +101,8 @@
* @msi_pages: MSI pages
* @root_busno: Root Bus number
* @dev: Device pointer
* @irq_domain: IRQ domain pointer
* @msi_domain: MSI IRQ domain pointer
* @leg_domain: Legacy IRQ domain pointer
* @resources: Bus Resources
*/
struct xilinx_pcie_port {
@ -110,7 +111,8 @@ struct xilinx_pcie_port {
unsigned long msi_pages;
u8 root_busno;
struct device *dev;
struct irq_domain *irq_domain;
struct irq_domain *msi_domain;
struct irq_domain *leg_domain;
struct list_head resources;
};
@ -212,13 +214,15 @@ static void xilinx_pcie_destroy_msi(unsigned int irq)
{
struct msi_desc *msi;
struct xilinx_pcie_port *port;
struct irq_data *d = irq_get_irq_data(irq);
irq_hw_number_t hwirq = irqd_to_hwirq(d);
if (!test_bit(irq, msi_irq_in_use)) {
if (!test_bit(hwirq, msi_irq_in_use)) {
msi = irq_get_msi_desc(irq);
port = msi_desc_to_pci_sysdata(msi);
dev_err(port->dev, "Trying to free unused MSI#%d\n", irq);
} else {
clear_bit(irq, msi_irq_in_use);
clear_bit(hwirq, msi_irq_in_use);
}
}
@ -250,6 +254,7 @@ static void xilinx_msi_teardown_irq(struct msi_controller *chip,
unsigned int irq)
{
xilinx_pcie_destroy_msi(irq);
irq_dispose_mapping(irq);
}
/**
@ -274,7 +279,7 @@ static int xilinx_pcie_msi_setup_irq(struct msi_controller *chip,
if (hwirq < 0)
return hwirq;
irq = irq_create_mapping(port->irq_domain, hwirq);
irq = irq_create_mapping(port->msi_domain, hwirq);
if (!irq)
return -EINVAL;
@ -425,7 +430,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
/* Check whether interrupt valid */
if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) {
dev_warn(port->dev, "RP Intr FIFO1 read error\n");
return IRQ_HANDLED;
goto error;
}
if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) {
@ -436,7 +441,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
/* Handle INTx Interrupt */
val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1;
generic_handle_irq(irq_find_mapping(port->irq_domain,
generic_handle_irq(irq_find_mapping(port->leg_domain,
val));
}
}
@ -447,7 +452,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) {
dev_warn(port->dev, "RP Intr FIFO1 read error\n");
return IRQ_HANDLED;
goto error;
}
if (val & XILINX_PCIE_RPIFR1_MSI_INTR) {
@ -492,6 +497,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
if (status & XILINX_PCIE_INTR_MST_ERRP)
dev_warn(port->dev, "Master error poison\n");
error:
/* Clear the Interrupt Decode register */
pcie_write(port, status, XILINX_PCIE_REG_IDR);
@ -517,21 +523,21 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
return -ENODEV;
}
port->irq_domain = irq_domain_add_linear(pcie_intc_node, 4,
port->leg_domain = irq_domain_add_linear(pcie_intc_node, 4,
&intx_domain_ops,
port);
if (!port->irq_domain) {
if (!port->leg_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n");
return -ENODEV;
}
/* Setup MSI */
if (IS_ENABLED(CONFIG_PCI_MSI)) {
port->irq_domain = irq_domain_add_linear(node,
port->msi_domain = irq_domain_add_linear(node,
XILINX_NUM_MSI_IRQS,
&msi_domain_ops,
&xilinx_pcie_msi_chip);
if (!port->irq_domain) {
if (!port->msi_domain) {
dev_err(dev, "Failed to get a MSI IRQ domain\n");
return -ENODEV;
}