Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07420a02 authored by Sergio Paracuellos's avatar Sergio Paracuellos Committed by Greg Kroah-Hartman
Browse files

staging: mt7621-pci: use gpio perst instead of builtin behaviour



Some boards seems to ignore the PERST builtin behaviour to properly
perform a pcie line reset. Use gpio PERST behaviour instead which
seems to be more common.

Fixes: bd1a05bd ("staging: mt7621-pci: use PERST_N instead of gpio control")
Signed-off-by: default avatarSergio Paracuellos <sergio.paracuellos@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fdd228cd
Loading
Loading
Loading
Loading
+58 −48
Original line number Diff line number Diff line
@@ -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,6 +36,7 @@

/* sysctl */
#define MT7621_CHIP_REV_ID		0x0c
#define MT7621_GPIO_MODE		0x60
#define CHIP_REV_MT7621_E2		0x0101

/* MediaTek specific configuration registers */
@@ -81,7 +83,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 +90,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 +123,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 +137,7 @@ struct mt7621_pcie {
		resource_size_t io;
	} offset;
	struct list_head ports;
	struct gpio_desc *perst;
	struct reset_control *rst;
};

@@ -198,6 +204,23 @@ 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_control_assert(struct mt7621_pcie_port *port)
{
	u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
@@ -344,6 +367,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 +413,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 +421,34 @@ 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", slot, (unsigned int)val);

	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;
		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 +456,29 @@ 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);
			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 +487,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 +508,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,11 +520,7 @@ 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;
			}
			mt7621_pcie_enable_port(port);
			dev_info(dev, "PCIE%d enabled\n", num_slots_enabled);
			num_slots_enabled++;
		}