linux-stable/drivers/staging/mt7621-pci/pci-mt7621.c

747 lines
18 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0+
/*
* BRIEF MODULE DESCRIPTION
* PCI init for Ralink RT2880 solution
*
* Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
*
* May 2007 Bruce Chang
* Initial Release
*
* May 2009 Bruce Chang
* support RT2880/RT3883 PCIe
*
* May 2011 Bruce Chang
* support RT6855/MT7620 PCIe
*/
#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>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/sys_soc.h>
#include <mt7621.h>
#include <ralink_regs.h>
#include "../../pci/pci.h"
/* sysctl */
#define MT7621_GPIO_MODE 0x60
/* 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)
/* rt_sysc_membase relative registers */
#define RALINK_CLKCFG1 0x30
/* Host-PCI bridge registers */
#define RALINK_PCI_PCICFG_ADDR 0x0000
#define RALINK_PCI_PCIMSK_ADDR 0x000C
#define RALINK_PCI_CONFIG_ADDR 0x0020
#define RALINK_PCI_CONFIG_DATA 0x0024
#define RALINK_PCI_MEMBASE 0x0028
#define RALINK_PCI_IOBASE 0x002C
/* PCICFG virtual bridges */
#define PCIE_P2P_CNT 3
#define PCIE_P2P_BR_DEVNUM_SHIFT(p) (16 + (p) * 4)
#define PCIE_P2P_BR_DEVNUM0_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(0)
#define PCIE_P2P_BR_DEVNUM1_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(1)
#define PCIE_P2P_BR_DEVNUM2_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(2)
#define PCIE_P2P_BR_DEVNUM_MASK 0xf
#define PCIE_P2P_BR_DEVNUM_MASK_FULL (0xfff << PCIE_P2P_BR_DEVNUM0_SHIFT)
/* PCIe RC control registers */
#define MT7621_PCIE_OFFSET 0x2000
#define MT7621_NEXT_PORT 0x1000
#define RALINK_PCI_BAR0SETUP_ADDR 0x0010
#define RALINK_PCI_IMBASEBAR0_ADDR 0x0018
#define RALINK_PCI_ID 0x0030
#define RALINK_PCI_CLASS 0x0034
#define RALINK_PCI_SUBID 0x0038
#define RALINK_PCI_STATUS 0x0050
/* Some definition values */
#define PCIE_REVISION_ID BIT(0)
#define PCIE_CLASS_CODE (0x60400 << 8)
#define PCIE_BAR_MAP_MAX GENMASK(30, 16)
#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_LINKUP BIT(0)
#define MEMORY_BASE 0x0
#define PERST_MODE_MASK GENMASK(11, 10)
#define PERST_MODE_GPIO BIT(10)
#define PERST_DELAY_MS 100
/**
* struct mt7621_pcie_port - PCIe port information
* @base: I/O mapped register base
* @list: port list
* @pcie: pointer to PCIe host info
* @phy: pointer to PHY control block
* @pcie_rst: pointer to port reset control
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
* @gpio_rst: gpio reset
* @slot: port slot
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
* @irq: GIC irq
* @enabled: indicates if port is enabled
*/
struct mt7621_pcie_port {
void __iomem *base;
struct list_head list;
struct mt7621_pcie *pcie;
struct phy *phy;
struct reset_control *pcie_rst;
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
struct gpio_desc *gpio_rst;
u32 slot;
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
int irq;
bool enabled;
};
/**
* struct mt7621_pcie - PCIe host information
* @base: IO Mapped Register Base
* @io: IO resource
* @mem: non-prefetchable memory resource
* @dev: Pointer to PCIe device
* @io_map_base: virtual memory base address for io
* @ports: pointer to PCIe port information
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
* @irq_map: irq mapping info according pcie link status
* @resets_inverted: depends on chip revision
* reset lines are inverted.
*/
struct mt7621_pcie {
void __iomem *base;
struct device *dev;
struct resource io;
struct resource mem;
unsigned long io_map_base;
struct list_head ports;
int irq_map[PCIE_P2P_CNT];
bool resets_inverted;
};
static inline u32 pcie_read(struct mt7621_pcie *pcie, u32 reg)
{
return readl(pcie->base + reg);
}
static inline void pcie_write(struct mt7621_pcie *pcie, u32 val, u32 reg)
{
writel(val, pcie->base + reg);
}
static inline void pcie_rmw(struct mt7621_pcie *pcie, u32 reg, u32 clr, u32 set)
{
u32 val = readl(pcie->base + reg);
val &= ~clr;
val |= set;
writel(val, pcie->base + reg);
}
static inline u32 pcie_port_read(struct mt7621_pcie_port *port, u32 reg)
{
return readl(port->base + reg);
}
static inline void pcie_port_write(struct mt7621_pcie_port *port,
u32 val, u32 reg)
{
writel(val, port->base + reg);
}
static inline u32 mt7621_pci_get_cfgaddr(unsigned int bus, unsigned int slot,
unsigned int func, unsigned int where)
{
return (((where & 0xF00) >> 8) << 24) | (bus << 16) | (slot << 11) |
(func << 8) | (where & 0xfc) | 0x80000000;
}
static void __iomem *mt7621_pcie_map_bus(struct pci_bus *bus,
unsigned int devfn, int where)
{
struct mt7621_pcie *pcie = bus->sysdata;
u32 address = mt7621_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
PCI_FUNC(devfn), where);
writel(address, pcie->base + RALINK_PCI_CONFIG_ADDR);
return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3);
}
struct pci_ops mt7621_pci_ops = {
.map_bus = mt7621_pcie_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
};
static u32 read_config(struct mt7621_pcie *pcie, unsigned int dev, u32 reg)
{
u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg);
pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR);
return pcie_read(pcie, RALINK_PCI_CONFIG_DATA);
}
static void write_config(struct mt7621_pcie *pcie, unsigned int dev,
u32 reg, u32 val)
{
u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg);
pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR);
pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA);
}
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
static inline void mt7621_rst_gpio_pcie_assert(struct mt7621_pcie_port *port)
{
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
if (port->gpio_rst)
gpiod_set_value(port->gpio_rst, 1);
}
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
static inline void mt7621_rst_gpio_pcie_deassert(struct mt7621_pcie_port *port)
{
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
if (port->gpio_rst)
gpiod_set_value(port->gpio_rst, 0);
}
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_enable(struct mt7621_pcie_port *port)
{
rt_sysc_m32(0, PCIE_PORT_CLK_EN(port->slot), RALINK_CLKCFG1);
}
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)
{
struct mt7621_pcie *pcie = port->pcie;
if (pcie->resets_inverted)
reset_control_assert(port->pcie_rst);
else
reset_control_deassert(port->pcie_rst);
}
static inline void mt7621_control_deassert(struct mt7621_pcie_port *port)
{
struct mt7621_pcie *pcie = port->pcie;
if (pcie->resets_inverted)
reset_control_deassert(port->pcie_rst);
else
reset_control_assert(port->pcie_rst);
}
static void setup_cm_memory_region(struct mt7621_pcie *pcie)
{
struct resource *mem_resource = &pcie->mem;
struct device *dev = pcie->dev;
resource_size_t mask;
if (mips_cps_numiocu(0)) {
/*
* FIXME: hardware doesn't accept mask values with 1s after
* 0s (e.g. 0xffef), so it would be great to warn if that's
* about to happen
*/
mask = ~(mem_resource->end - mem_resource->start);
write_gcr_reg1_base(mem_resource->start);
write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0);
dev_info(dev, "PCI coherence region base: 0x%08llx, mask/settings: 0x%08llx\n",
(unsigned long long)read_gcr_reg1_base(),
(unsigned long long)read_gcr_reg1_mask());
}
}
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
static int mt7621_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
struct mt7621_pcie *pcie = pdev->bus->sysdata;
struct device *dev = pcie->dev;
int irq = pcie->irq_map[slot];
dev_info(dev, "bus=%d slot=%d irq=%d\n", pdev->bus->number, slot, irq);
return irq;
}
static int mt7621_pci_parse_request_of_pci_ranges(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
struct device_node *node = dev->of_node;
struct of_pci_range_parser parser;
struct of_pci_range range;
if (of_pci_range_parser_init(&parser, node)) {
dev_err(dev, "missing \"ranges\" property\n");
return -EINVAL;
}
/*
* IO_SPACE_LIMIT for MIPS is 0xffff but this platform uses IO at
* upper address 0x001e160000 so we have to get the resource from
* the DT because when it has been requested it failed and has been
* removed from bridge->dma_ranges and bridge->windows. So parse it
* and remap it manually to make things work.
*/
for_each_of_pci_range(&parser, &range) {
switch (range.flags & IORESOURCE_TYPE_BITS) {
case IORESOURCE_IO:
pcie->io_map_base =
(unsigned long)ioremap(range.cpu_addr,
range.size);
of_pci_range_to_resource(&range, node, &pcie->io);
pcie->io.start = range.cpu_addr;
pcie->io.end = range.cpu_addr + range.size - 1;
break;
case IORESOURCE_MEM:
of_pci_range_to_resource(&range, node, &pcie->mem);
break;
}
}
set_io_port_base(pcie->io_map_base);
return 0;
}
static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
struct device_node *node,
int slot)
{
struct mt7621_pcie_port *port;
struct device *dev = pcie->dev;
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
struct platform_device *pdev = to_platform_device(dev);
struct device_node *pnode = dev->of_node;
struct resource regs;
char name[10];
int err;
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
err = of_address_to_resource(pnode, slot + 1, &regs);
if (err) {
dev_err(dev, "missing \"reg\" property\n");
return err;
}
port->base = devm_ioremap_resource(dev, &regs);
if (IS_ERR(port->base))
return PTR_ERR(port->base);
snprintf(name, sizeof(name), "pcie%d", slot);
port->pcie_rst = devm_reset_control_get_exclusive(dev, name);
if (PTR_ERR(port->pcie_rst) == -EPROBE_DEFER) {
dev_err(dev, "failed to get pcie%d reset control\n", slot);
return PTR_ERR(port->pcie_rst);
}
snprintf(name, sizeof(name), "pcie-phy%d", slot);
port->phy = devm_phy_get(dev, name);
if (IS_ERR(port->phy) && slot != 1)
return PTR_ERR(port->phy);
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot,
GPIOD_OUT_LOW);
if (IS_ERR(port->gpio_rst)) {
dev_err(dev, "Failed to get GPIO for PCIe%d\n", slot);
return PTR_ERR(port->gpio_rst);
}
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
port->slot = slot;
port->pcie = pcie;
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
port->irq = platform_get_irq(pdev, slot);
if (port->irq < 0) {
dev_err(dev, "Failed to get IRQ for PCIe%d\n", slot);
return -ENXIO;
}
INIT_LIST_HEAD(&port->list);
list_add_tail(&port->list, &pcie->ports);
return 0;
}
static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
struct device_node *node = dev->of_node, *child;
struct resource regs;
int err;
err = of_address_to_resource(node, 0, &regs);
if (err) {
dev_err(dev, "missing \"reg\" property\n");
return err;
}
pcie->base = devm_ioremap_resource(dev, &regs);
if (IS_ERR(pcie->base))
return PTR_ERR(pcie->base);
for_each_available_child_of_node(node, child) {
int slot;
err = of_pci_get_devfn(child);
if (err < 0) {
of_node_put(child);
dev_err(dev, "failed to parse devfn: %d\n", err);
return err;
}
slot = PCI_SLOT(err);
err = mt7621_pcie_parse_port(pcie, child, slot);
if (err) {
of_node_put(child);
return err;
}
}
return 0;
}
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;
int err;
err = phy_init(port->phy);
if (err) {
dev_err(dev, "failed to initialize port%d phy\n", slot);
return err;
}
err = phy_power_on(port->phy);
if (err) {
dev_err(dev, "failed to power on port%d phy\n", slot);
phy_exit(port->phy);
return err;
}
port->enabled = true;
return 0;
}
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
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_MS);
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
}
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_MS);
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
}
static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
struct mt7621_pcie_port *port, *tmp;
int err;
rt_sysc_m32(PERST_MODE_MASK, PERST_MODE_GPIO, MT7621_GPIO_MODE);
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
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;
if (slot == 1) {
port->enabled = true;
continue;
}
err = mt7621_pcie_init_port(port);
if (err) {
dev_err(dev, "Initiating port %d failed\n", slot);
list_del(&port->list);
}
}
staging: mt7621-pci: use gpios for properly reset 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. According to the mediatek aplication note v0.1 there are three gpios used for pcie ports reset control: gpio#19, gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. This schema can be used separately for mt7621A but in some boards due to pin share issue, if the PCM and I2S function are enable at the same time, there are no enough GPIO to control per-port PCIe reset. In those cases gpio#19 is enought for reset the three ports together. Because of this we just try to get the three gpios but if some of them fail we are not failing in boot process, just prints a kernel notice and take after into account if the descriptor is or not valid in order to use it. All of them are set as GPIO output low configuration. The gpio descriptor's API takes device tree property into account and invert value if the pin is configured as active low. So we also have to properly request pins from device tree and set values correct in assert and deassert functions. 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@gmail.com> Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-03-13 20:09:08 +00:00
mt7621_pcie_reset_ep_deassert(pcie);
tmp = NULL;
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);
mt7621_control_assert(port);
mt7621_pcie_port_clk_disable(port);
port->enabled = false;
if (slot == 0) {
tmp = port;
continue;
}
if (slot == 1 && tmp && !tmp->enabled)
phy_power_off(tmp->phy);
}
}
}
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;
/* enable pcie interrupt */
val = pcie_read(pcie, RALINK_PCI_PCIMSK_ADDR);
val |= PCIE_PORT_INT_EN(slot);
pcie_write(pcie, val, RALINK_PCI_PCIMSK_ADDR);
/* map 2G DDR region */
pcie_write(pcie, PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE,
offset + RALINK_PCI_BAR0SETUP_ADDR);
pcie_write(pcie, MEMORY_BASE,
offset + RALINK_PCI_IMBASEBAR0_ADDR);
/* configure class code and revision ID */
pcie_write(pcie, PCIE_CLASS_CODE | PCIE_REVISION_ID,
offset + RALINK_PCI_CLASS);
}
static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
struct mt7621_pcie_port *port;
u8 num_slots_enabled = 0;
u32 slot;
u32 val;
/* Setup MEMWIN and IOWIN */
pcie_write(pcie, 0xffffffff, RALINK_PCI_MEMBASE);
pcie_write(pcie, pcie->io.start, RALINK_PCI_IOBASE);
list_for_each_entry(port, &pcie->ports, list) {
if (port->enabled) {
mt7621_pcie_port_clk_enable(port);
mt7621_pcie_enable_port(port);
dev_info(dev, "PCIE%d enabled\n", port->slot);
num_slots_enabled++;
}
}
for (slot = 0; slot < num_slots_enabled; slot++) {
val = read_config(pcie, slot, PCI_COMMAND);
val |= PCI_COMMAND_MASTER;
write_config(pcie, slot, PCI_COMMAND, val);
/* configure RC FTS number to 250 when it leaves L0s */
val = read_config(pcie, slot, PCIE_FTS_NUM);
val &= ~PCIE_FTS_NUM_MASK;
val |= PCIE_FTS_NUM_L0(0x50);
write_config(pcie, slot, PCIE_FTS_NUM, val);
}
}
static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie)
{
u32 pcie_link_status = 0;
u32 n = 0;
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
int i = 0;
u32 p2p_br_devnum[PCIE_P2P_CNT];
int irqs[PCIE_P2P_CNT];
struct mt7621_pcie_port *port;
list_for_each_entry(port, &pcie->ports, list) {
u32 slot = port->slot;
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
irqs[i++] = port->irq;
if (port->enabled)
pcie_link_status |= BIT(slot);
}
if (pcie_link_status == 0)
return -1;
/*
* Assign device numbers from zero to the enabled ports,
* then assigning remaining device numbers to any disabled
* ports.
*/
for (i = 0; i < PCIE_P2P_CNT; i++)
if (pcie_link_status & BIT(i))
p2p_br_devnum[i] = n++;
for (i = 0; i < PCIE_P2P_CNT; i++)
if ((pcie_link_status & BIT(i)) == 0)
p2p_br_devnum[i] = n++;
pcie_rmw(pcie, RALINK_PCI_PCICFG_ADDR,
PCIE_P2P_BR_DEVNUM_MASK_FULL,
(p2p_br_devnum[0] << PCIE_P2P_BR_DEVNUM0_SHIFT) |
(p2p_br_devnum[1] << PCIE_P2P_BR_DEVNUM1_SHIFT) |
(p2p_br_devnum[2] << PCIE_P2P_BR_DEVNUM2_SHIFT));
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
/* Assign IRQs */
n = 0;
for (i = 0; i < PCIE_P2P_CNT; i++)
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
if (pcie_link_status & BIT(i))
pcie->irq_map[n++] = irqs[i];
for (i = n; i < PCIE_P2P_CNT; i++)
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
pcie->irq_map[i] = -1;
return 0;
}
staging: mt7621-pci: avoid to request pci bus resources After upgrading kernel to version 5.9.x the driver was not working anymore showing the following kernel trace: ... mt7621-pci 1e140000.pcie: resource collision: [mem 0x60000000-0x6fffffff] conflicts with pcie@1e140000 [mem 0x60000000-0x6fffffff] ------------[ cut here ]------------ WARNING: CPU: 2 PID: 73 at kernel/resource.c:1400 devm_request_resource+0xfc/0x10c Modules linked in: CPU: 2 PID: 73 Comm: kworker/2:1 Not tainted 5.9.2 #0 Workqueue: events deferred_probe_work_func Stack : 00000000 81590000 807d0a1c 808a0000 8fd49080 807d0000 00000009 808ac820 00000001 808338d0 7fff0001 800839dc 00000049 00000001 8fe51b00 367204ab 00000000 00000000 807d0a1c 807c0000 00000001 80082358 8fe50000 00559000 00000000 8fe519f1 ffffffff 00000005 00000000 00000001 00000000 807d0000 00000009 808ac820 00000001 808338d0 00000001 803bf1b0 00000008 81390008 Call Trace: [<8000d018>] show_stack+0x30/0x100 [<8032e66c>] dump_stack+0xa4/0xd4 [<8002db1c>] __warn+0xc0/0x134 [<8002dbec>] warn_slowpath_fmt+0x5c/0xac [<80033b34>] devm_request_resource+0xfc/0x10c [<80365ff8>] devm_request_pci_bus_resources+0x58/0xdc [<8048e13c>] mt7621_pci_probe+0x8dc/0xe48 [<803d2140>] platform_drv_probe+0x40/0x94 [<803cfd94>] really_probe+0x108/0x4ec [<803cd958>] bus_for_each_drv+0x70/0xb0 [<803d0388>] __device_attach+0xec/0x164 [<803cec8c>] bus_probe_device+0xa4/0xc0 [<803cf1c4>] deferred_probe_work_func+0x80/0xc4 [<80048444>] process_one_work+0x260/0x510 [<80048a4c>] worker_thread+0x358/0x5cc [<8004f7d0>] kthread+0x134/0x13c [<80007478>] ret_from_kernel_thread+0x14/0x1c ---[ end trace a9dd2e37537510d3 ]--- mt7621-pci 1e140000.pcie: Error requesting resources mt7621-pci: probe of 1e140000.pcie failed with error -16 ... With commit 669cbc708122 ("PCI: Move DT resource setup into devm_pci_alloc_host_bridge()"), the DT 'ranges' is parsed and populated into resources when the host bridge is allocated. The resources are requested as well, but that happens a 2nd time for this driver in mt7621_pcie_request_resources(). Hence we should avoid this second request. Also, the bus ranges was also populated by default, so we can remove it from mt7621_pcie_request_resources() to avoid the following trace if we don't avoid it: pci_bus 0000:00: busn_res: can not insert [bus 00-ff] under domain [bus 00-ff] (conflicts with (null) [bus 00-ff]) Function 'mt7621_pcie_request_resources' has been renamed into 'mt7621_pcie_add_resources' which now is a more accurate name for this function. Cc: stable@vger.kernel.org #5.9.x- Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20201102202515.19073-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-11-02 20:25:15 +00:00
static void mt7621_pcie_add_resources(struct mt7621_pcie *pcie,
struct list_head *res)
{
pci_add_resource(res, &pcie->io);
pci_add_resource(res, &pcie->mem);
}
static int mt7621_pcie_register_host(struct pci_host_bridge *host,
struct list_head *res)
{
struct mt7621_pcie *pcie = pci_host_bridge_priv(host);
list_splice_init(res, &host->windows);
host->ops = &mt7621_pci_ops;
staging: mt7621-pci: fix PCIe interrupt mapping MT7621 has three assigned interrupts for the pcie. This interrupts should properly being mapped taking into account which devices are finally connected in which bus according to link status. So the irq mappings should be as follows according to link status (three bits indicating which devices are link up): * For PCIe Bus 1 slot 0: - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). - status = 0x4 => IRQ = pcie2_irq (25). - default => IRQ = pcie0_irq (23). * For PCIe Bus 2 slot 0: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 2 slot 1: - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). - default => IRQ = pcie1_irq (24). * For PCIe Bus 3 any slot: - default => IRQ = pcie2_irq (25). Because of this, the function 'of_irq_parse_and_map_pci' cannot be used and we need to change device tree information from using the 'interrupt-map' and 'interrupt-map-mask' properties into an 'interrupts' property to be able to get irq information from the ports using the 'platform_get_irq' and storing an 'irq-map' into the pcie driver data node to properly map correct irq using a new 'mt7621_map_irq' function where this map will be read and the correct irq returned. Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-13 05:59:42 +00:00
host->map_irq = mt7621_map_irq;
host->sysdata = pcie;
return pci_host_probe(host);
}
static const struct soc_device_attribute mt7621_pci_quirks_match[] = {
{ .soc_id = "mt7621", .revision = "E2" }
};
static int mt7621_pci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct soc_device_attribute *attr;
struct mt7621_pcie *pcie;
struct pci_host_bridge *bridge;
int err;
LIST_HEAD(res);
if (!dev->of_node)
return -ENODEV;
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!bridge)
return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev;
platform_set_drvdata(pdev, pcie);
INIT_LIST_HEAD(&pcie->ports);
attr = soc_device_match(mt7621_pci_quirks_match);
if (attr)
pcie->resets_inverted = true;
err = mt7621_pcie_parse_dt(pcie);
if (err) {
dev_err(dev, "Parsing DT failed\n");
return err;
}
err = mt7621_pci_parse_request_of_pci_ranges(pcie);
if (err) {
dev_err(dev, "Error requesting pci resources from ranges");
return err;
}
/* set resources limits */
ioport_resource.start = pcie->io.start;
ioport_resource.end = pcie->io.end;
mt7621_pcie_init_ports(pcie);
err = mt7621_pcie_init_virtual_bridges(pcie);
if (err) {
dev_err(dev, "Nothing is connected in virtual bridges. Exiting...");
return 0;
}
mt7621_pcie_enable_ports(pcie);
setup_cm_memory_region(pcie);
staging: mt7621-pci: avoid to request pci bus resources After upgrading kernel to version 5.9.x the driver was not working anymore showing the following kernel trace: ... mt7621-pci 1e140000.pcie: resource collision: [mem 0x60000000-0x6fffffff] conflicts with pcie@1e140000 [mem 0x60000000-0x6fffffff] ------------[ cut here ]------------ WARNING: CPU: 2 PID: 73 at kernel/resource.c:1400 devm_request_resource+0xfc/0x10c Modules linked in: CPU: 2 PID: 73 Comm: kworker/2:1 Not tainted 5.9.2 #0 Workqueue: events deferred_probe_work_func Stack : 00000000 81590000 807d0a1c 808a0000 8fd49080 807d0000 00000009 808ac820 00000001 808338d0 7fff0001 800839dc 00000049 00000001 8fe51b00 367204ab 00000000 00000000 807d0a1c 807c0000 00000001 80082358 8fe50000 00559000 00000000 8fe519f1 ffffffff 00000005 00000000 00000001 00000000 807d0000 00000009 808ac820 00000001 808338d0 00000001 803bf1b0 00000008 81390008 Call Trace: [<8000d018>] show_stack+0x30/0x100 [<8032e66c>] dump_stack+0xa4/0xd4 [<8002db1c>] __warn+0xc0/0x134 [<8002dbec>] warn_slowpath_fmt+0x5c/0xac [<80033b34>] devm_request_resource+0xfc/0x10c [<80365ff8>] devm_request_pci_bus_resources+0x58/0xdc [<8048e13c>] mt7621_pci_probe+0x8dc/0xe48 [<803d2140>] platform_drv_probe+0x40/0x94 [<803cfd94>] really_probe+0x108/0x4ec [<803cd958>] bus_for_each_drv+0x70/0xb0 [<803d0388>] __device_attach+0xec/0x164 [<803cec8c>] bus_probe_device+0xa4/0xc0 [<803cf1c4>] deferred_probe_work_func+0x80/0xc4 [<80048444>] process_one_work+0x260/0x510 [<80048a4c>] worker_thread+0x358/0x5cc [<8004f7d0>] kthread+0x134/0x13c [<80007478>] ret_from_kernel_thread+0x14/0x1c ---[ end trace a9dd2e37537510d3 ]--- mt7621-pci 1e140000.pcie: Error requesting resources mt7621-pci: probe of 1e140000.pcie failed with error -16 ... With commit 669cbc708122 ("PCI: Move DT resource setup into devm_pci_alloc_host_bridge()"), the DT 'ranges' is parsed and populated into resources when the host bridge is allocated. The resources are requested as well, but that happens a 2nd time for this driver in mt7621_pcie_request_resources(). Hence we should avoid this second request. Also, the bus ranges was also populated by default, so we can remove it from mt7621_pcie_request_resources() to avoid the following trace if we don't avoid it: pci_bus 0000:00: busn_res: can not insert [bus 00-ff] under domain [bus 00-ff] (conflicts with (null) [bus 00-ff]) Function 'mt7621_pcie_request_resources' has been renamed into 'mt7621_pcie_add_resources' which now is a more accurate name for this function. Cc: stable@vger.kernel.org #5.9.x- Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Link: https://lore.kernel.org/r/20201102202515.19073-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-11-02 20:25:15 +00:00
mt7621_pcie_add_resources(pcie, &res);
err = mt7621_pcie_register_host(bridge, &res);
if (err) {
dev_err(dev, "Error registering host\n");
return err;
}
return 0;
}
static const struct of_device_id mt7621_pci_ids[] = {
{ .compatible = "mediatek,mt7621-pci" },
{},
};
MODULE_DEVICE_TABLE(of, mt7621_pci_ids);
static struct platform_driver mt7621_pci_driver = {
.probe = mt7621_pci_probe,
.driver = {
.name = "mt7621-pci",
.of_match_table = of_match_ptr(mt7621_pci_ids),
},
};
builtin_platform_driver(mt7621_pci_driver);