Original driver code was using three gpio's for reset asserts and deasserts the pcis. Instead of using that a general reset control with a perst gpio was introduced and it seems it is partially working but sometimes there are some unexpected hangs on boot. This commit make use of the three original gpios using 'reset-gpios' property of the device tree and removes the reset line and perst gpio. After this changes the order to make all assert and deassert in the 'probe' process makes more sense: * Parse device tree. * make assert of the RC's and EP's before doing anything else. * make deassert of the RC's before initializing the phy. * Init the phy. * make deassert of the EP's before initialize pci ports. * Normal PCI initialization. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@xxxxxxxxx> --- drivers/staging/mt7621-pci/pci-mt7621.c | 82 +++++++++++++++---------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 770dabd3a70d..45ebd880ef6c 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -95,6 +95,7 @@ * @pcie: pointer to PCIe host info * @phy: pointer to PHY control block * @pcie_rst: pointer to port reset control + * @gpio_rst: gpio reset * @slot: port slot * @enabled: indicates if port is enabled */ @@ -104,6 +105,7 @@ struct mt7621_pcie_port { struct mt7621_pcie *pcie; struct phy *phy; struct reset_control *pcie_rst; + struct gpio_desc *gpio_rst; u32 slot; bool enabled; }; @@ -117,8 +119,6 @@ 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 * @resets_inverted: depends on chip revision * reset lines are inverted. */ @@ -133,8 +133,6 @@ struct mt7621_pcie { resource_size_t io; } offset; struct list_head ports; - struct gpio_desc *perst; - struct reset_control *rst; bool resets_inverted; }; @@ -210,16 +208,14 @@ 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) +static inline void mt7621_rst_gpio_pcie_assert(struct mt7621_pcie_port *port) { - gpiod_set_value(pcie->perst, 0); - mdelay(PERST_DELAY_US); + gpiod_set_value(port->gpio_rst, 0); } -static inline void mt7621_perst_gpio_pcie_deassert(struct mt7621_pcie *pcie) +static inline void mt7621_rst_gpio_pcie_deassert(struct mt7621_pcie_port *port) { - gpiod_set_value(pcie->perst, 1); - mdelay(PERST_DELAY_US); + gpiod_set_value(port->gpio_rst, 1); } static inline bool mt7621_pcie_port_is_linkup(struct mt7621_pcie_port *port) @@ -367,6 +363,13 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, if (IS_ERR(port->phy)) return PTR_ERR(port->phy); + port->gpio_rst = devm_gpiod_get_index(dev, "reset", slot, + GPIOD_OUT_HIGH); + if (IS_ERR(port->gpio_rst)) { + dev_err(dev, "Unable to request GPIO reset in slot %d\n", slot); + return PTR_ERR(port->gpio_rst); + } + port->slot = slot; port->pcie = pcie; @@ -383,12 +386,6 @@ 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, ®s); if (err) { dev_err(dev, "missing \"reg\" property\n"); @@ -399,12 +396,6 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) if (IS_ERR(pcie->base)) return PTR_ERR(pcie->base); - pcie->rst = devm_reset_control_get_exclusive(dev, "pcie"); - if (PTR_ERR(pcie->rst) == -EPROBE_DEFER) { - dev_err(dev, "failed to get pcie reset control\n"); - return PTR_ERR(pcie->rst); - } - for_each_available_child_of_node(node, child) { int slot; @@ -458,16 +449,49 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port) return 0; } +static void mt7621_pcie_reset_assert(struct mt7621_pcie *pcie) +{ + struct mt7621_pcie_port *port; + + list_for_each_entry(port, &pcie->ports, list) { + /* PCIe RC reset assert */ + mt7621_control_assert(port); + + /* PCIe EP reset assert */ + mt7621_rst_gpio_pcie_assert(port); + } + + mdelay(PERST_DELAY_US); +} + +static void mt7621_pcie_reset_rc_deassert(struct mt7621_pcie *pcie) +{ + struct mt7621_pcie_port *port; + + list_for_each_entry(port, &pcie->ports, list) + mt7621_control_deassert(port); +} + +static void mt7621_pcie_reset_ep_deassert(struct mt7621_pcie *pcie) +{ + struct mt7621_pcie_port *port; + + list_for_each_entry(port, &pcie->ports, list) + mt7621_rst_gpio_pcie_deassert(port); + + mdelay(PERST_DELAY_US); +} + 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); + mt7621_pcie_reset_assert(pcie); + mt7621_pcie_reset_rc_deassert(pcie); list_for_each_entry_safe(port, tmp, &pcie->ports, list) { u32 slot = port->slot; @@ -476,16 +500,10 @@ 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); + mt7621_pcie_reset_ep_deassert(pcie); list_for_each_entry(port, &pcie->ports, list) { u32 slot = port->slot; @@ -499,8 +517,6 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) port->enabled = false; } } - - reset_control_deassert(pcie->rst); } static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port) -- 2.25.1 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel