mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'pci/controller/mediatek'
- Use FIELD_PREP() to fix incorrect operator precedence in PCIE_FTS_NUM_L0 (Li RongQing) - Fix IRQ domain leak when port fails to enable (Manivannan Sadhasivam) - Use actual physical address for MSI message address instead of virt_to_phys() (Manivannan Sadhasivam) - Add EcoNet EN7528 to DT binding (Caleb James DeLisle) * pci/controller/mediatek: dt-bindings: PCI: mediatek: Add support for EcoNet EN7528 PCI: mediatek: Use actual physical address instead of virt_to_phys() PCI: mediatek: Fix IRQ domain leak when port fails to enable PCI: mediatek: Fix operator precedence in PCIE_FTS_NUM_L0 macro
This commit is contained in:
commit
7b90019012
|
|
@ -14,6 +14,7 @@ properties:
|
|||
oneOf:
|
||||
- enum:
|
||||
- airoha,an7583-pcie
|
||||
- econet,en7528-pcie
|
||||
- mediatek,mt2712-pcie
|
||||
- mediatek,mt7622-pcie
|
||||
- mediatek,mt7629-pcie
|
||||
|
|
@ -226,6 +227,31 @@ allOf:
|
|||
|
||||
mediatek,pbus-csr: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: econet,en7528-pcie
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
maxItems: 1
|
||||
|
||||
resets: false
|
||||
|
||||
reset-names: false
|
||||
|
||||
power-domains: false
|
||||
|
||||
mediatek,pbus-csr: false
|
||||
|
||||
required:
|
||||
- phys
|
||||
- phy-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
* Honghui Zhang <honghui.zhang@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
|
@ -61,7 +62,7 @@
|
|||
/* MediaTek specific configuration registers */
|
||||
#define PCIE_FTS_NUM 0x70c
|
||||
#define PCIE_FTS_NUM_MASK GENMASK(15, 8)
|
||||
#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8)
|
||||
#define PCIE_FTS_NUM_L0(x) FIELD_PREP(PCIE_FTS_NUM_MASK, x)
|
||||
|
||||
#define PCIE_FC_CREDIT 0x73c
|
||||
#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16))
|
||||
|
|
@ -175,6 +176,7 @@ struct mtk_pcie_soc {
|
|||
/**
|
||||
* struct mtk_pcie_port - PCIe port information
|
||||
* @base: IO mapped register base
|
||||
* @phys_base: Physical address of the I/O register base region
|
||||
* @list: port list
|
||||
* @pcie: pointer to PCIe host info
|
||||
* @reset: pointer to port reset control
|
||||
|
|
@ -196,6 +198,7 @@ struct mtk_pcie_soc {
|
|||
*/
|
||||
struct mtk_pcie_port {
|
||||
void __iomem *base;
|
||||
phys_addr_t phys_base;
|
||||
struct list_head list;
|
||||
struct mtk_pcie *pcie;
|
||||
struct reset_control *reset;
|
||||
|
|
@ -405,7 +408,7 @@ static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
|||
phys_addr_t addr;
|
||||
|
||||
/* MT2712/MT7622 only support 32-bit MSI addresses */
|
||||
addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
|
||||
addr = port->phys_base + PCIE_MSI_VECTOR;
|
||||
msg->address_hi = 0;
|
||||
msg->address_lo = lower_32_bits(addr);
|
||||
|
||||
|
|
@ -520,7 +523,7 @@ static void mtk_pcie_enable_msi(struct mtk_pcie_port *port)
|
|||
u32 val;
|
||||
phys_addr_t msg_addr;
|
||||
|
||||
msg_addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
|
||||
msg_addr = port->phys_base + PCIE_MSI_VECTOR;
|
||||
val = lower_32_bits(msg_addr);
|
||||
writel(val, port->base + PCIE_IMSI_ADDR);
|
||||
|
||||
|
|
@ -529,23 +532,27 @@ static void mtk_pcie_enable_msi(struct mtk_pcie_port *port)
|
|||
writel(val, port->base + PCIE_INT_MASK);
|
||||
}
|
||||
|
||||
static void mtk_pcie_irq_teardown_port(struct mtk_pcie_port *port)
|
||||
{
|
||||
irq_set_chained_handler_and_data(port->irq, NULL, NULL);
|
||||
|
||||
if (port->irq_domain)
|
||||
irq_domain_remove(port->irq_domain);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
if (port->inner_domain)
|
||||
irq_domain_remove(port->inner_domain);
|
||||
}
|
||||
|
||||
irq_dispose_mapping(port->irq);
|
||||
}
|
||||
|
||||
static void mtk_pcie_irq_teardown(struct mtk_pcie *pcie)
|
||||
{
|
||||
struct mtk_pcie_port *port, *tmp;
|
||||
|
||||
list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
|
||||
irq_set_chained_handler_and_data(port->irq, NULL, NULL);
|
||||
|
||||
if (port->irq_domain)
|
||||
irq_domain_remove(port->irq_domain);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
if (port->inner_domain)
|
||||
irq_domain_remove(port->inner_domain);
|
||||
}
|
||||
|
||||
irq_dispose_mapping(port->irq);
|
||||
}
|
||||
list_for_each_entry_safe(port, tmp, &pcie->ports, list)
|
||||
mtk_pcie_irq_teardown_port(port);
|
||||
}
|
||||
|
||||
static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
|
||||
|
|
@ -865,7 +872,7 @@ static int mtk_pcie_startup_port_an7583(struct mtk_pcie_port *port)
|
|||
return mtk_pcie_startup_port_v2(port);
|
||||
}
|
||||
|
||||
static void mtk_pcie_enable_port(struct mtk_pcie_port *port)
|
||||
static int mtk_pcie_enable_port(struct mtk_pcie_port *port)
|
||||
{
|
||||
struct mtk_pcie *pcie = port->pcie;
|
||||
struct device *dev = pcie->dev;
|
||||
|
|
@ -874,7 +881,7 @@ static void mtk_pcie_enable_port(struct mtk_pcie_port *port)
|
|||
err = clk_prepare_enable(port->sys_ck);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to enable sys_ck%d clock\n", port->slot);
|
||||
goto err_sys_clk;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = clk_prepare_enable(port->ahb_ck);
|
||||
|
|
@ -922,11 +929,15 @@ static void mtk_pcie_enable_port(struct mtk_pcie_port *port)
|
|||
goto err_phy_on;
|
||||
}
|
||||
|
||||
if (!pcie->soc->startup(port))
|
||||
return;
|
||||
err = pcie->soc->startup(port);
|
||||
if (err) {
|
||||
dev_info(dev, "Port%d link down\n", port->slot);
|
||||
goto err_soc_startup;
|
||||
}
|
||||
|
||||
dev_info(dev, "Port%d link down\n", port->slot);
|
||||
return 0;
|
||||
|
||||
err_soc_startup:
|
||||
phy_power_off(port->phy);
|
||||
err_phy_on:
|
||||
phy_exit(port->phy);
|
||||
|
|
@ -942,8 +953,8 @@ static void mtk_pcie_enable_port(struct mtk_pcie_port *port)
|
|||
clk_disable_unprepare(port->ahb_ck);
|
||||
err_ahb_clk:
|
||||
clk_disable_unprepare(port->sys_ck);
|
||||
err_sys_clk:
|
||||
mtk_pcie_port_free(port);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mtk_pcie_parse_port(struct mtk_pcie *pcie,
|
||||
|
|
@ -953,6 +964,7 @@ static int mtk_pcie_parse_port(struct mtk_pcie *pcie,
|
|||
struct mtk_pcie_port *port;
|
||||
struct device *dev = pcie->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct resource *res;
|
||||
char name[20];
|
||||
int err;
|
||||
|
||||
|
|
@ -961,7 +973,14 @@ static int mtk_pcie_parse_port(struct mtk_pcie *pcie,
|
|||
return -ENOMEM;
|
||||
|
||||
snprintf(name, sizeof(name), "port%d", slot);
|
||||
port->base = devm_platform_ioremap_resource_byname(pdev, name);
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
|
||||
if (!res) {
|
||||
dev_err(dev, "failed to get port%d base\n", slot);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
port->phys_base = res->start;
|
||||
port->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(port->base)) {
|
||||
dev_err(dev, "failed to map port%d base\n", slot);
|
||||
return PTR_ERR(port->base);
|
||||
|
|
@ -1109,8 +1128,13 @@ static int mtk_pcie_setup(struct mtk_pcie *pcie)
|
|||
return err;
|
||||
|
||||
/* enable each port, and then check link status */
|
||||
list_for_each_entry_safe(port, tmp, &pcie->ports, list)
|
||||
mtk_pcie_enable_port(port);
|
||||
list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
|
||||
err = mtk_pcie_enable_port(port);
|
||||
if (err) {
|
||||
mtk_pcie_irq_teardown_port(port);
|
||||
mtk_pcie_port_free(port);
|
||||
}
|
||||
}
|
||||
|
||||
/* power down PCIe subsys if slots are all empty (link down) */
|
||||
if (list_empty(&pcie->ports))
|
||||
|
|
@ -1209,14 +1233,18 @@ static int mtk_pcie_resume_noirq(struct device *dev)
|
|||
{
|
||||
struct mtk_pcie *pcie = dev_get_drvdata(dev);
|
||||
struct mtk_pcie_port *port, *tmp;
|
||||
int err;
|
||||
|
||||
if (list_empty(&pcie->ports))
|
||||
return 0;
|
||||
|
||||
clk_prepare_enable(pcie->free_ck);
|
||||
|
||||
list_for_each_entry_safe(port, tmp, &pcie->ports, list)
|
||||
mtk_pcie_enable_port(port);
|
||||
list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
|
||||
err = mtk_pcie_enable_port(port);
|
||||
if (err)
|
||||
mtk_pcie_port_free(port);
|
||||
}
|
||||
|
||||
/* In case of EP was removed while system suspend. */
|
||||
if (list_empty(&pcie->ports))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user