aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/mt7621-pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/mt7621-pci')
-rw-r--r--drivers/staging/mt7621-pci/Kconfig1
-rw-r--r--drivers/staging/mt7621-pci/Makefile1
-rw-r--r--drivers/staging/mt7621-pci/mediatek,mt7621-pci.txt2
-rw-r--r--drivers/staging/mt7621-pci/pci-mt7621.c122
4 files changed, 74 insertions, 52 deletions
diff --git a/drivers/staging/mt7621-pci/Kconfig b/drivers/staging/mt7621-pci/Kconfig
index c8fa17cfa807..af928b75a940 100644
--- a/drivers/staging/mt7621-pci/Kconfig
+++ b/drivers/staging/mt7621-pci/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
config PCI_MT7621
tristate "MediaTek MT7621 PCI Controller"
depends on RALINK
diff --git a/drivers/staging/mt7621-pci/Makefile b/drivers/staging/mt7621-pci/Makefile
index d4655a726b61..f4e651cf7ce3 100644
--- a/drivers/staging/mt7621-pci/Makefile
+++ b/drivers/staging/mt7621-pci/Makefile
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PCI_MT7621) += pci-mt7621.o
diff --git a/drivers/staging/mt7621-pci/mediatek,mt7621-pci.txt b/drivers/staging/mt7621-pci/mediatek,mt7621-pci.txt
index 5a6ee4103cd5..604ec813bd45 100644
--- a/drivers/staging/mt7621-pci/mediatek,mt7621-pci.txt
+++ b/drivers/staging/mt7621-pci/mediatek,mt7621-pci.txt
@@ -6,6 +6,7 @@ Required properties:
- reg: Base addresses and lengths of the PCIe subsys and root ports.
- bus-range: Range of bus numbers associated with this controller.
- #address-cells: Address representation for root ports (must be 3)
+- perst-gpio: PCIe reset signal line.
- pinctrl-names : The pin control state names.
- pinctrl-0: The "default" pinctrl state.
- #size-cells: Size representation for root ports (must be 2)
@@ -48,6 +49,7 @@ Example for MT7621:
#address-cells = <3>;
#size-cells = <2>;
+ perst-gpio = <&gpio 19 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pcie_pins>;
diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c
index 379ae780c691..89fa813142ab 100644
--- a/drivers/staging/mt7621-pci/pci-mt7621.c
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
@@ -17,6 +17,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -35,14 +36,16 @@
/* sysctl */
#define MT7621_CHIP_REV_ID 0x0c
+#define MT7621_GPIO_MODE 0x60
#define CHIP_REV_MT7621_E2 0x0101
/* 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) (((x) & 0xff) << 8)
/* rt_sysc_membase relative registers */
+#define RALINK_CLKCFG1 0x30
#define RALINK_PCIE_CLK_GEN 0x7c
#define RALINK_PCIE_CLK_GEN1 0x80
@@ -81,7 +84,6 @@
#define PCIE_BAR_ENABLE BIT(0)
#define PCIE_PORT_INT_EN(x) BIT(20 + (x))
#define PCIE_PORT_CLK_EN(x) BIT(24 + (x))
-#define PCIE_PORT_PERST(x) BIT(1 + (x))
#define PCIE_PORT_LINKUP BIT(0)
#define PCIE_CLK_GEN_EN BIT(31)
@@ -89,6 +91,9 @@
#define PCIE_CLK_GEN1_DIS GENMASK(30, 24)
#define PCIE_CLK_GEN1_EN (BIT(27) | BIT(25))
#define MEMORY_BASE 0x0
+#define PERST_MODE_MASK GENMASK(11, 10)
+#define PERST_MODE_GPIO BIT(10)
+#define PERST_DELAY_US 1000
/**
* struct mt7621_pcie_port - PCIe port information
@@ -119,6 +124,7 @@ struct mt7621_pcie_port {
* @offset: IO / Memory offset
* @dev: Pointer to PCIe device
* @ports: pointer to PCIe port information
+ * @perst: gpio reset
* @rst: pointer to pcie reset
*/
struct mt7621_pcie {
@@ -132,6 +138,7 @@ struct mt7621_pcie {
resource_size_t io;
} offset;
struct list_head ports;
+ struct gpio_desc *perst;
struct reset_control *rst;
};
@@ -198,6 +205,28 @@ static void write_config(struct mt7621_pcie *pcie, unsigned int dev,
pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA);
}
+static inline void mt7621_perst_gpio_pcie_assert(struct mt7621_pcie *pcie)
+{
+ gpiod_set_value(pcie->perst, 0);
+ mdelay(PERST_DELAY_US);
+}
+
+static inline void mt7621_perst_gpio_pcie_deassert(struct mt7621_pcie *pcie)
+{
+ gpiod_set_value(pcie->perst, 1);
+ mdelay(PERST_DELAY_US);
+}
+
+static inline bool mt7621_pcie_port_is_linkup(struct mt7621_pcie_port *port)
+{
+ return (pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) != 0;
+}
+
+static inline void mt7621_pcie_port_clk_disable(struct mt7621_pcie_port *port)
+{
+ rt_sysc_m32(PCIE_PORT_CLK_EN(port->slot), 0, RALINK_CLKCFG1);
+}
+
static inline void mt7621_control_assert(struct mt7621_pcie_port *port)
{
u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
@@ -275,7 +304,7 @@ static int mt7621_pci_parse_request_of_pci_ranges(struct mt7621_pcie *pcie)
break;
}
- if (res != NULL)
+ if (res)
of_pci_range_to_resource(&range, node, res);
}
@@ -344,6 +373,12 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie)
struct resource regs;
int err;
+ pcie->perst = devm_gpiod_get(dev, "perst", GPIOD_OUT_HIGH);
+ if (IS_ERR(pcie->perst)) {
+ dev_err(dev, "failed to get gpio perst\n");
+ return PTR_ERR(pcie->perst);
+ }
+
err = of_address_to_resource(node, 0, &regs);
if (err) {
dev_err(dev, "missing \"reg\" property\n");
@@ -384,7 +419,6 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port)
struct mt7621_pcie *pcie = port->pcie;
struct device *dev = pcie->dev;
u32 slot = port->slot;
- u32 val = 0;
int err;
/*
@@ -393,47 +427,35 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port)
*/
mt7621_reset_port(port);
- val = read_config(pcie, slot, PCIE_FTS_NUM);
- dev_info(dev, "Port %d N_FTS = %x\n", (unsigned int)val, slot);
-
err = phy_init(port->phy);
if (err) {
dev_err(dev, "failed to initialize port%d phy\n", slot);
- goto err_phy_init;
+ return err;
}
err = phy_power_on(port->phy);
if (err) {
dev_err(dev, "failed to power on port%d phy\n", slot);
- goto err_phy_on;
- }
-
- if ((pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) == 0) {
- dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", slot);
- mt7621_control_assert(port);
- port->enabled = false;
- err = -ENODEV;
- goto err_no_link_up;
+ phy_exit(port->phy);
+ return err;
}
port->enabled = true;
return 0;
-
-err_no_link_up:
- phy_power_off(port->phy);
-err_phy_on:
- phy_exit(port->phy);
-err_phy_init:
- return err;
}
static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
struct mt7621_pcie_port *port, *tmp;
+ u32 val = 0;
int err;
+ rt_sysc_m32(PERST_MODE_MASK, PERST_MODE_GPIO, MT7621_GPIO_MODE);
+
+ mt7621_perst_gpio_pcie_assert(pcie);
+
list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
u32 slot = port->slot;
@@ -441,10 +463,30 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
if (err) {
dev_err(dev, "Initiating port %d failed\n", slot);
list_del(&port->list);
+ } else {
+ val = read_config(pcie, slot, PCIE_FTS_NUM);
+ dev_info(dev, "Port %d N_FTS = %x\n", slot,
+ (unsigned int)val);
}
}
reset_control_assert(pcie->rst);
+
+ mt7621_perst_gpio_pcie_deassert(pcie);
+
+ list_for_each_entry(port, &pcie->ports, list) {
+ u32 slot = port->slot;
+
+ if (!mt7621_pcie_port_is_linkup(port)) {
+ dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n",
+ slot);
+ phy_power_off(port->phy);
+ mt7621_control_assert(port);
+ mt7621_pcie_port_clk_disable(port);
+ port->enabled = false;
+ }
+ }
+
rt_sysc_m32(0x30, 2 << 4, SYSC_REG_SYSTEM_CONFIG1);
rt_sysc_m32(PCIE_CLK_GEN_EN, PCIE_CLK_GEN_DIS, RALINK_PCIE_CLK_GEN);
rt_sysc_m32(PCIE_CLK_GEN1_DIS, PCIE_CLK_GEN1_EN, RALINK_PCIE_CLK_GEN1);
@@ -453,30 +495,12 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
reset_control_deassert(pcie->rst);
}
-static int mt7621_pcie_enable_port(struct mt7621_pcie_port *port)
+static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port)
{
struct mt7621_pcie *pcie = port->pcie;
u32 slot = port->slot;
u32 offset = MT7621_PCIE_OFFSET + (slot * MT7621_NEXT_PORT);
u32 val;
- int err;
-
- /* assert port PERST_N */
- val = pcie_read(pcie, RALINK_PCI_PCICFG_ADDR);
- val |= PCIE_PORT_PERST(slot);
- pcie_write(pcie, val, RALINK_PCI_PCICFG_ADDR);
-
- /* de-assert port PERST_N */
- val = pcie_read(pcie, RALINK_PCI_PCICFG_ADDR);
- val &= ~PCIE_PORT_PERST(slot);
- pcie_write(pcie, val, RALINK_PCI_PCICFG_ADDR);
-
- /* 100ms timeout value should be enough for Gen1 training */
- err = readl_poll_timeout(port->base + RALINK_PCI_STATUS,
- val, !!(val & PCIE_PORT_LINKUP),
- 20, 100 * USEC_PER_MSEC);
- if (err)
- return -ETIMEDOUT;
/* enable pcie interrupt */
val = pcie_read(pcie, RALINK_PCI_PCIMSK_ADDR);
@@ -492,8 +516,6 @@ static int mt7621_pcie_enable_port(struct mt7621_pcie_port *port)
/* configure class code and revision ID */
pcie_write(pcie, PCIE_CLASS_CODE | PCIE_REVISION_ID,
offset + RALINK_PCI_CLASS);
-
- return 0;
}
static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie)
@@ -506,12 +528,8 @@ static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie)
list_for_each_entry(port, &pcie->ports, list) {
if (port->enabled) {
- if (mt7621_pcie_enable_port(port)) {
- dev_err(dev, "de-assert port %d PERST_N\n",
- port->slot);
- continue;
- }
- dev_info(dev, "PCIE%d enabled\n", slot);
+ mt7621_pcie_enable_port(port);
+ dev_info(dev, "PCIE%d enabled\n", num_slots_enabled);
num_slots_enabled++;
}
}
@@ -709,4 +727,4 @@ static int __init mt7621_pci_init(void)
return platform_driver_register(&mt7621_pci_driver);
}
-arch_initcall(mt7621_pci_init);
+module_init(mt7621_pci_init);