From: Honghui Zhang <honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
To: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Cc: bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
robh-+zGGX9k9yNkdnm+yROfE0A@public.gmane.org,
matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
hongkun.cao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
yong.wu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
yt.shen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
xinping.qian-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org
Subject: Re: [PATCH v3 5/6] PCI: mediatek: Add new generation controller support
Date: Mon, 7 Aug 2017 17:18:01 +0800 [thread overview]
Message-ID: <1502097481.24341.32.camel@mtksdaap41> (raw)
In-Reply-To: <1501985190.8058.20.camel@mtkswgap22>
On Sun, 2017-08-06 at 10:06 +0800, Ryder Lee wrote:
> Hi Honghui,
>
> If you plan to send next version, then I would suggest some minor
> changes.
>
> On Fri, 2017-08-04 at 20:06 +0800, honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org wrote:
> > +#define PCIE_CRSTB BIT(3)
> > +#define PCIE_PERSTB BIT(8)
> > +#define PCI_LINKDOWN_RST_EN GENMASK(15, 13)
>
> PCIE_LINKDOWN_RST_EN
Thanks, I will change it in the next version.
>
> > +#define PCIE_LINK_STATUS_V2 0x804
> > +#define PCIE_PORT_LINKUP_V2 BIT(10)
> > +
> > +
> > +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 *val)
> > +{
> > + int reg, shift = 8 * (where & 3);
>
> int reg => u32
sharp eyes, thanks.
>
> > + /* Write PCIe Configuration Transaction Header for cfgrd */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Trigger h/w to transmit Cfgrd TLP */
> > + reg = readl(port->base + PCIE_APP_TLP_REQ);
> > + writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + if (mtk_pcie_check_cfg_cpld(port))
> > + return PCIBIOS_SET_FAILED;
> > +
> > + /* Read cpld payload of Cfgrd */
> > + *val = readl(port->base + PCIE_CFG_RDATA);
> > +
> > + switch (size) {
> > + case 4:
> > + break;
> > + case 3:
> > + *val = (*val >> shift) & 0xffffff;
> > + break;
> > + case 2:
> > + *val = (*val >> shift) & 0xffff;
> > + break;
> > + case 1:
> > + *val = (*val >> shift) & 0xff;
> > + break;
> > + default:
> > + return PCIBIOS_BAD_REGISTER_NUMBER;
> > + }
>
> Do we really need case 3? I guess case 1, 2 or 4 should be enough.
>
I will change this as the following snippet:
if (size == 1)
*val = (*val >> (8 * (where & 3))) & 0xff;
else if (size == 2)
*val = (*val >> (8 * (where & 3))) & 0xffff;
thanks.
> > + return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 val)
> > +{
> > + /* Write PCIe Configuration Transaction Header for Cfgwr */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Write cfgwr data */
> > + val = val << 8 * (where & 3);
> > + writel(val, port->base + PCIE_CFG_WDATA);
> > +
> > + /* Trigger h/w to transmit Cfgwr TLP */
> > + val = readl(port->base + PCIE_APP_TLP_REQ);
> > + val |= APP_CFG_REQ;
> > + writel(val, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + return mtk_pcie_check_cfg_cpld(port);
> > +}
> > +
> > +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 *val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > + int ret;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port) {
> > + *val = ~0;
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > + }
>
> list_for_each_entry(), since you don't really remove or free something.
>
> I know you need to find port->base to write/read configuration space. I
> think it's better to move this part to another function. You can take a
> look at pci-mvebu.c mvebu_pcie_find_portmvebu().
Sure, I will add the mtk_pcie_find_port interface, then the code is a
bit more readable.
thanks.
>
> > + ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> > + if (ret)
> > + *val = ~0;
> > +
> > + return ret;
> > +}
> > +
> > +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port)
> > + return PCIBIOS_DEVICE_NOT_FOUND;
>
> Ditto.
>
> > + return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops_v2 = {
> > + .read = mtk_pcie_config_read,
> > + .write = mtk_pcie_config_write,
> > +};
> > +
> > +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> > +{
> > + struct mtk_pcie *pcie = port->pcie;
> > + struct resource *mem = &pcie->mem;
> > + u32 val;
> > + size_t size;
> > + int err;
> > +
> > + /* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> > + if (pcie->base) {
> > + val = readl(pcie->base + PCIE_SYS_CFG_V2);
> > + val |= PCIE_CSR_LTSSM_EN(port->index) |
> > + PCIE_CSR_ASPM_L1_EN(port->index);
> > + writel(val, pcie->base + PCIE_SYS_CFG_V2);
> > + }
> > +
> > + /* Assert all reset signals */
> > + writel(0, port->base + PCIE_RST_CTRL);
> > +
> > + /*
> > + * Enable PCIe link down reset, if link status changed from link up to
> > + * link down, this will reset MAC control registers and configuration
> > + * space.
> > + */
> > + writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> > +
> > + /* De-assert PHY, PE, PIPE, MAC and configuration reset */
> > + val = readl(port->base + PCIE_RST_CTRL);
> > + val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> > + PCIE_MAC_SRSTB | PCIE_CRSTB;
> > + writel(val, port->base + PCIE_RST_CTRL);
> > +
> > + /* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
>
> /* 100ms timeout value should be enough for Gen1/2 training */ for
> consistency.
>
> > + err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> > + !!(val & PCIE_PORT_LINKUP_V2), 20,
> > + 100 * USEC_PER_MSEC);
> > + if (err)
> > + return -ETIMEDOUT;
> > +
> > + /* Set INTx mask */
> > + val = readl(port->base + PCIE_INT_MASK);
> > + val &= ~INTX_MASK;
> > + writel(val, port->base + PCIE_INT_MASK);
> > +
> > + /* Set AHB to PCIe translation windows */
> > + size = mem->end - mem->start;
> > + val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> > +
> > + val = AHB2PCIE_BASEH(mem->start);
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> > +
> > + /* Set PCIe to AXI translation memory space.*/
> > + val = fls(0xffffffff) | WIN_ENABLE;
> > + writel(val, port->base + PCIE_AXI_WINDOW0);
> > +
> > + return 0;
> > +}
>
> Ryder
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: Honghui Zhang <honghui.zhang@mediatek.com>
To: Ryder Lee <ryder.lee@mediatek.com>
Cc: youlin.pei@mediatek.com, devicetree@vger.kernel.org,
hongkun.cao@mediatek.com, yt.shen@mediatek.com,
linux-pci@vger.kernel.org, sean.wang@mediatek.com,
xinping.qian@mediatek.com, linux-kernel@vger.kernel.org,
matthias.bgg@gmail.com, robh@kerenl.org,
linux-mediatek@lists.infradead.org, yong.wu@mediatek.com,
bhelgaas@google.com, yingjoe.chen@mediatek.com,
eddie.huang@mediatek.com, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v3 5/6] PCI: mediatek: Add new generation controller support
Date: Mon, 7 Aug 2017 17:18:01 +0800 [thread overview]
Message-ID: <1502097481.24341.32.camel@mtksdaap41> (raw)
In-Reply-To: <1501985190.8058.20.camel@mtkswgap22>
On Sun, 2017-08-06 at 10:06 +0800, Ryder Lee wrote:
> Hi Honghui,
>
> If you plan to send next version, then I would suggest some minor
> changes.
>
> On Fri, 2017-08-04 at 20:06 +0800, honghui.zhang@mediatek.com wrote:
> > +#define PCIE_CRSTB BIT(3)
> > +#define PCIE_PERSTB BIT(8)
> > +#define PCI_LINKDOWN_RST_EN GENMASK(15, 13)
>
> PCIE_LINKDOWN_RST_EN
Thanks, I will change it in the next version.
>
> > +#define PCIE_LINK_STATUS_V2 0x804
> > +#define PCIE_PORT_LINKUP_V2 BIT(10)
> > +
> > +
> > +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 *val)
> > +{
> > + int reg, shift = 8 * (where & 3);
>
> int reg => u32
sharp eyes, thanks.
>
> > + /* Write PCIe Configuration Transaction Header for cfgrd */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Trigger h/w to transmit Cfgrd TLP */
> > + reg = readl(port->base + PCIE_APP_TLP_REQ);
> > + writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + if (mtk_pcie_check_cfg_cpld(port))
> > + return PCIBIOS_SET_FAILED;
> > +
> > + /* Read cpld payload of Cfgrd */
> > + *val = readl(port->base + PCIE_CFG_RDATA);
> > +
> > + switch (size) {
> > + case 4:
> > + break;
> > + case 3:
> > + *val = (*val >> shift) & 0xffffff;
> > + break;
> > + case 2:
> > + *val = (*val >> shift) & 0xffff;
> > + break;
> > + case 1:
> > + *val = (*val >> shift) & 0xff;
> > + break;
> > + default:
> > + return PCIBIOS_BAD_REGISTER_NUMBER;
> > + }
>
> Do we really need case 3? I guess case 1, 2 or 4 should be enough.
>
I will change this as the following snippet:
if (size == 1)
*val = (*val >> (8 * (where & 3))) & 0xff;
else if (size == 2)
*val = (*val >> (8 * (where & 3))) & 0xffff;
thanks.
> > + return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 val)
> > +{
> > + /* Write PCIe Configuration Transaction Header for Cfgwr */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Write cfgwr data */
> > + val = val << 8 * (where & 3);
> > + writel(val, port->base + PCIE_CFG_WDATA);
> > +
> > + /* Trigger h/w to transmit Cfgwr TLP */
> > + val = readl(port->base + PCIE_APP_TLP_REQ);
> > + val |= APP_CFG_REQ;
> > + writel(val, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + return mtk_pcie_check_cfg_cpld(port);
> > +}
> > +
> > +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 *val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > + int ret;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port) {
> > + *val = ~0;
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > + }
>
> list_for_each_entry(), since you don't really remove or free something.
>
> I know you need to find port->base to write/read configuration space. I
> think it's better to move this part to another function. You can take a
> look at pci-mvebu.c mvebu_pcie_find_portmvebu().
Sure, I will add the mtk_pcie_find_port interface, then the code is a
bit more readable.
thanks.
>
> > + ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> > + if (ret)
> > + *val = ~0;
> > +
> > + return ret;
> > +}
> > +
> > +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port)
> > + return PCIBIOS_DEVICE_NOT_FOUND;
>
> Ditto.
>
> > + return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops_v2 = {
> > + .read = mtk_pcie_config_read,
> > + .write = mtk_pcie_config_write,
> > +};
> > +
> > +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> > +{
> > + struct mtk_pcie *pcie = port->pcie;
> > + struct resource *mem = &pcie->mem;
> > + u32 val;
> > + size_t size;
> > + int err;
> > +
> > + /* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> > + if (pcie->base) {
> > + val = readl(pcie->base + PCIE_SYS_CFG_V2);
> > + val |= PCIE_CSR_LTSSM_EN(port->index) |
> > + PCIE_CSR_ASPM_L1_EN(port->index);
> > + writel(val, pcie->base + PCIE_SYS_CFG_V2);
> > + }
> > +
> > + /* Assert all reset signals */
> > + writel(0, port->base + PCIE_RST_CTRL);
> > +
> > + /*
> > + * Enable PCIe link down reset, if link status changed from link up to
> > + * link down, this will reset MAC control registers and configuration
> > + * space.
> > + */
> > + writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> > +
> > + /* De-assert PHY, PE, PIPE, MAC and configuration reset */
> > + val = readl(port->base + PCIE_RST_CTRL);
> > + val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> > + PCIE_MAC_SRSTB | PCIE_CRSTB;
> > + writel(val, port->base + PCIE_RST_CTRL);
> > +
> > + /* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
>
> /* 100ms timeout value should be enough for Gen1/2 training */ for
> consistency.
>
> > + err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> > + !!(val & PCIE_PORT_LINKUP_V2), 20,
> > + 100 * USEC_PER_MSEC);
> > + if (err)
> > + return -ETIMEDOUT;
> > +
> > + /* Set INTx mask */
> > + val = readl(port->base + PCIE_INT_MASK);
> > + val &= ~INTX_MASK;
> > + writel(val, port->base + PCIE_INT_MASK);
> > +
> > + /* Set AHB to PCIe translation windows */
> > + size = mem->end - mem->start;
> > + val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> > +
> > + val = AHB2PCIE_BASEH(mem->start);
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> > +
> > + /* Set PCIe to AXI translation memory space.*/
> > + val = fls(0xffffffff) | WIN_ENABLE;
> > + writel(val, port->base + PCIE_AXI_WINDOW0);
> > +
> > + return 0;
> > +}
>
> Ryder
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: honghui.zhang@mediatek.com (Honghui Zhang)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 5/6] PCI: mediatek: Add new generation controller support
Date: Mon, 7 Aug 2017 17:18:01 +0800 [thread overview]
Message-ID: <1502097481.24341.32.camel@mtksdaap41> (raw)
In-Reply-To: <1501985190.8058.20.camel@mtkswgap22>
On Sun, 2017-08-06 at 10:06 +0800, Ryder Lee wrote:
> Hi Honghui,
>
> If you plan to send next version, then I would suggest some minor
> changes.
>
> On Fri, 2017-08-04 at 20:06 +0800, honghui.zhang at mediatek.com wrote:
> > +#define PCIE_CRSTB BIT(3)
> > +#define PCIE_PERSTB BIT(8)
> > +#define PCI_LINKDOWN_RST_EN GENMASK(15, 13)
>
> PCIE_LINKDOWN_RST_EN
Thanks, I will change it in the next version.
>
> > +#define PCIE_LINK_STATUS_V2 0x804
> > +#define PCIE_PORT_LINKUP_V2 BIT(10)
> > +
> > +
> > +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 *val)
> > +{
> > + int reg, shift = 8 * (where & 3);
>
> int reg => u32
sharp eyes, thanks.
>
> > + /* Write PCIe Configuration Transaction Header for cfgrd */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Trigger h/w to transmit Cfgrd TLP */
> > + reg = readl(port->base + PCIE_APP_TLP_REQ);
> > + writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + if (mtk_pcie_check_cfg_cpld(port))
> > + return PCIBIOS_SET_FAILED;
> > +
> > + /* Read cpld payload of Cfgrd */
> > + *val = readl(port->base + PCIE_CFG_RDATA);
> > +
> > + switch (size) {
> > + case 4:
> > + break;
> > + case 3:
> > + *val = (*val >> shift) & 0xffffff;
> > + break;
> > + case 2:
> > + *val = (*val >> shift) & 0xffff;
> > + break;
> > + case 1:
> > + *val = (*val >> shift) & 0xff;
> > + break;
> > + default:
> > + return PCIBIOS_BAD_REGISTER_NUMBER;
> > + }
>
> Do we really need case 3? I guess case 1, 2 or 4 should be enough.
>
I will change this as the following snippet:
if (size == 1)
*val = (*val >> (8 * (where & 3))) & 0xff;
else if (size == 2)
*val = (*val >> (8 * (where & 3))) & 0xffff;
thanks.
> > + return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 val)
> > +{
> > + /* Write PCIe Configuration Transaction Header for Cfgwr */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Write cfgwr data */
> > + val = val << 8 * (where & 3);
> > + writel(val, port->base + PCIE_CFG_WDATA);
> > +
> > + /* Trigger h/w to transmit Cfgwr TLP */
> > + val = readl(port->base + PCIE_APP_TLP_REQ);
> > + val |= APP_CFG_REQ;
> > + writel(val, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + return mtk_pcie_check_cfg_cpld(port);
> > +}
> > +
> > +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 *val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > + int ret;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port) {
> > + *val = ~0;
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > + }
>
> list_for_each_entry(), since you don't really remove or free something.
>
> I know you need to find port->base to write/read configuration space. I
> think it's better to move this part to another function. You can take a
> look at pci-mvebu.c mvebu_pcie_find_portmvebu().
Sure, I will add the mtk_pcie_find_port interface, then the code is a
bit more readable.
thanks.
>
> > + ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> > + if (ret)
> > + *val = ~0;
> > +
> > + return ret;
> > +}
> > +
> > +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port)
> > + return PCIBIOS_DEVICE_NOT_FOUND;
>
> Ditto.
>
> > + return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops_v2 = {
> > + .read = mtk_pcie_config_read,
> > + .write = mtk_pcie_config_write,
> > +};
> > +
> > +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> > +{
> > + struct mtk_pcie *pcie = port->pcie;
> > + struct resource *mem = &pcie->mem;
> > + u32 val;
> > + size_t size;
> > + int err;
> > +
> > + /* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> > + if (pcie->base) {
> > + val = readl(pcie->base + PCIE_SYS_CFG_V2);
> > + val |= PCIE_CSR_LTSSM_EN(port->index) |
> > + PCIE_CSR_ASPM_L1_EN(port->index);
> > + writel(val, pcie->base + PCIE_SYS_CFG_V2);
> > + }
> > +
> > + /* Assert all reset signals */
> > + writel(0, port->base + PCIE_RST_CTRL);
> > +
> > + /*
> > + * Enable PCIe link down reset, if link status changed from link up to
> > + * link down, this will reset MAC control registers and configuration
> > + * space.
> > + */
> > + writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> > +
> > + /* De-assert PHY, PE, PIPE, MAC and configuration reset */
> > + val = readl(port->base + PCIE_RST_CTRL);
> > + val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> > + PCIE_MAC_SRSTB | PCIE_CRSTB;
> > + writel(val, port->base + PCIE_RST_CTRL);
> > +
> > + /* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
>
> /* 100ms timeout value should be enough for Gen1/2 training */ for
> consistency.
>
> > + err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> > + !!(val & PCIE_PORT_LINKUP_V2), 20,
> > + 100 * USEC_PER_MSEC);
> > + if (err)
> > + return -ETIMEDOUT;
> > +
> > + /* Set INTx mask */
> > + val = readl(port->base + PCIE_INT_MASK);
> > + val &= ~INTX_MASK;
> > + writel(val, port->base + PCIE_INT_MASK);
> > +
> > + /* Set AHB to PCIe translation windows */
> > + size = mem->end - mem->start;
> > + val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> > +
> > + val = AHB2PCIE_BASEH(mem->start);
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> > +
> > + /* Set PCIe to AXI translation memory space.*/
> > + val = fls(0xffffffff) | WIN_ENABLE;
> > + writel(val, port->base + PCIE_AXI_WINDOW0);
> > +
> > + return 0;
> > +}
>
> Ryder
>
WARNING: multiple messages have this Message-ID (diff)
From: Honghui Zhang <honghui.zhang@mediatek.com>
To: Ryder Lee <ryder.lee@mediatek.com>
Cc: <bhelgaas@google.com>, <robh@kerenl.org>,
<matthias.bgg@gmail.com>, <linux-arm-kernel@lists.infradead.org>,
<linux-mediatek@lists.infradead.org>, <linux-pci@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>,
<yingjoe.chen@mediatek.com>, <eddie.huang@mediatek.com>,
<hongkun.cao@mediatek.com>, <youlin.pei@mediatek.com>,
<yong.wu@mediatek.com>, <yt.shen@mediatek.com>,
<sean.wang@mediatek.com>, <xinping.qian@mediatek.com>
Subject: Re: [PATCH v3 5/6] PCI: mediatek: Add new generation controller support
Date: Mon, 7 Aug 2017 17:18:01 +0800 [thread overview]
Message-ID: <1502097481.24341.32.camel@mtksdaap41> (raw)
In-Reply-To: <1501985190.8058.20.camel@mtkswgap22>
On Sun, 2017-08-06 at 10:06 +0800, Ryder Lee wrote:
> Hi Honghui,
>
> If you plan to send next version, then I would suggest some minor
> changes.
>
> On Fri, 2017-08-04 at 20:06 +0800, honghui.zhang@mediatek.com wrote:
> > +#define PCIE_CRSTB BIT(3)
> > +#define PCIE_PERSTB BIT(8)
> > +#define PCI_LINKDOWN_RST_EN GENMASK(15, 13)
>
> PCIE_LINKDOWN_RST_EN
Thanks, I will change it in the next version.
>
> > +#define PCIE_LINK_STATUS_V2 0x804
> > +#define PCIE_PORT_LINKUP_V2 BIT(10)
> > +
> > +
> > +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 *val)
> > +{
> > + int reg, shift = 8 * (where & 3);
>
> int reg => u32
sharp eyes, thanks.
>
> > + /* Write PCIe Configuration Transaction Header for cfgrd */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Trigger h/w to transmit Cfgrd TLP */
> > + reg = readl(port->base + PCIE_APP_TLP_REQ);
> > + writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + if (mtk_pcie_check_cfg_cpld(port))
> > + return PCIBIOS_SET_FAILED;
> > +
> > + /* Read cpld payload of Cfgrd */
> > + *val = readl(port->base + PCIE_CFG_RDATA);
> > +
> > + switch (size) {
> > + case 4:
> > + break;
> > + case 3:
> > + *val = (*val >> shift) & 0xffffff;
> > + break;
> > + case 2:
> > + *val = (*val >> shift) & 0xffff;
> > + break;
> > + case 1:
> > + *val = (*val >> shift) & 0xff;
> > + break;
> > + default:
> > + return PCIBIOS_BAD_REGISTER_NUMBER;
> > + }
>
> Do we really need case 3? I guess case 1, 2 or 4 should be enough.
>
I will change this as the following snippet:
if (size == 1)
*val = (*val >> (8 * (where & 3))) & 0xff;
else if (size == 2)
*val = (*val >> (8 * (where & 3))) & 0xffff;
thanks.
> > + return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> > + int where, int size, u32 val)
> > +{
> > + /* Write PCIe Configuration Transaction Header for Cfgwr */
> > + writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
> > + port->base + PCIE_CFG_HEADER0);
> > + writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> > + writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > + port->base + PCIE_CFG_HEADER2);
> > +
> > + /* Write cfgwr data */
> > + val = val << 8 * (where & 3);
> > + writel(val, port->base + PCIE_CFG_WDATA);
> > +
> > + /* Trigger h/w to transmit Cfgwr TLP */
> > + val = readl(port->base + PCIE_APP_TLP_REQ);
> > + val |= APP_CFG_REQ;
> > + writel(val, port->base + PCIE_APP_TLP_REQ);
> > +
> > + /* Check completion status */
> > + return mtk_pcie_check_cfg_cpld(port);
> > +}
> > +
> > +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 *val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > + int ret;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port) {
> > + *val = ~0;
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > + }
>
> list_for_each_entry(), since you don't really remove or free something.
>
> I know you need to find port->base to write/read configuration space. I
> think it's better to move this part to another function. You can take a
> look at pci-mvebu.c mvebu_pcie_find_portmvebu().
Sure, I will add the mtk_pcie_find_port interface, then the code is a
bit more readable.
thanks.
>
> > + ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> > + if (ret)
> > + *val = ~0;
> > +
> > + return ret;
> > +}
> > +
> > +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 val)
> > +{
> > + struct mtk_pcie_port *port = NULL, *iter, *tmp;
> > + struct mtk_pcie *pcie = bus->sysdata;
> > + u32 bn = bus->number;
> > +
> > + list_for_each_entry_safe(iter, tmp, &pcie->ports, list)
> > + if (iter->index == PCI_SLOT(devfn)) {
> > + port = iter;
> > + break;
> > + }
> > +
> > + if (!port)
> > + return PCIBIOS_DEVICE_NOT_FOUND;
>
> Ditto.
>
> > + return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops_v2 = {
> > + .read = mtk_pcie_config_read,
> > + .write = mtk_pcie_config_write,
> > +};
> > +
> > +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> > +{
> > + struct mtk_pcie *pcie = port->pcie;
> > + struct resource *mem = &pcie->mem;
> > + u32 val;
> > + size_t size;
> > + int err;
> > +
> > + /* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> > + if (pcie->base) {
> > + val = readl(pcie->base + PCIE_SYS_CFG_V2);
> > + val |= PCIE_CSR_LTSSM_EN(port->index) |
> > + PCIE_CSR_ASPM_L1_EN(port->index);
> > + writel(val, pcie->base + PCIE_SYS_CFG_V2);
> > + }
> > +
> > + /* Assert all reset signals */
> > + writel(0, port->base + PCIE_RST_CTRL);
> > +
> > + /*
> > + * Enable PCIe link down reset, if link status changed from link up to
> > + * link down, this will reset MAC control registers and configuration
> > + * space.
> > + */
> > + writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> > +
> > + /* De-assert PHY, PE, PIPE, MAC and configuration reset */
> > + val = readl(port->base + PCIE_RST_CTRL);
> > + val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> > + PCIE_MAC_SRSTB | PCIE_CRSTB;
> > + writel(val, port->base + PCIE_RST_CTRL);
> > +
> > + /* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
>
> /* 100ms timeout value should be enough for Gen1/2 training */ for
> consistency.
>
> > + err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> > + !!(val & PCIE_PORT_LINKUP_V2), 20,
> > + 100 * USEC_PER_MSEC);
> > + if (err)
> > + return -ETIMEDOUT;
> > +
> > + /* Set INTx mask */
> > + val = readl(port->base + PCIE_INT_MASK);
> > + val &= ~INTX_MASK;
> > + writel(val, port->base + PCIE_INT_MASK);
> > +
> > + /* Set AHB to PCIe translation windows */
> > + size = mem->end - mem->start;
> > + val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> > +
> > + val = AHB2PCIE_BASEH(mem->start);
> > + writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> > +
> > + /* Set PCIe to AXI translation memory space.*/
> > + val = fls(0xffffffff) | WIN_ENABLE;
> > + writel(val, port->base + PCIE_AXI_WINDOW0);
> > +
> > + return 0;
> > +}
>
> Ryder
>
next prev parent reply other threads:[~2017-08-07 9:18 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-04 12:06 [PATCH v3 0/6] PCI: MediaTek: Add support for new generation host controller honghui.zhang
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` honghui.zhang at mediatek.com
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` [PATCH v3 1/6] PCI: mediatek: Using readl_poll_timeout to wait Gen2 training honghui.zhang
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` honghui.zhang at mediatek.com
2017-08-04 12:06 ` honghui.zhang
[not found] ` <cover.1501846816.git.honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2017-08-04 12:06 ` [PATCH v3 2/6] PCI: mediatek: Add a structure to abstract the controller generations honghui.zhang-NuS5LvNUpcJWk0Htik3J/w
2017-08-04 12:06 ` honghui.zhang at mediatek.com
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` [PATCH v3 6/6] dt-bindings: PCI: add support for new generation controller honghui.zhang-NuS5LvNUpcJWk0Htik3J/w
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` honghui.zhang at mediatek.com
2017-08-04 12:06 ` honghui.zhang
2017-08-08 20:04 ` Bjorn Helgaas
2017-08-08 20:04 ` Bjorn Helgaas
2017-08-08 20:04 ` Bjorn Helgaas
2017-08-04 12:06 ` [PATCH v3 3/6] PCI: mediatek: switch to use platform_get_resource_byname() honghui.zhang
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` honghui.zhang at mediatek.com
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` [PATCH v3 4/6] dt-bindings: PCI: rename and cleanup MediaTek binding text honghui.zhang
2017-08-04 12:06 ` honghui.zhang at mediatek.com
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` [PATCH v3 5/6] PCI: mediatek: Add new generation controller support honghui.zhang
2017-08-04 12:06 ` honghui.zhang
2017-08-04 12:06 ` honghui.zhang at mediatek.com
2017-08-04 12:06 ` honghui.zhang
[not found] ` <2adcb5f915eb8bd5817592ea32974eb25da02e4f.1501846816.git.honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2017-08-06 2:06 ` Ryder Lee
2017-08-06 2:06 ` Ryder Lee
2017-08-06 2:06 ` Ryder Lee
2017-08-07 9:18 ` Honghui Zhang [this message]
2017-08-07 9:18 ` Honghui Zhang
2017-08-07 9:18 ` Honghui Zhang
2017-08-07 9:18 ` Honghui Zhang
2017-08-08 20:20 ` Bjorn Helgaas
2017-08-08 20:20 ` Bjorn Helgaas
2017-08-08 20:20 ` Bjorn Helgaas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1502097481.24341.32.camel@mtksdaap41 \
--to=honghui.zhang-nus5lvnupcjwk0htik3j/w@public.gmane.org \
--cc=bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=hongkun.cao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=robh-+zGGX9k9yNkdnm+yROfE0A@public.gmane.org \
--cc=ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=xinping.qian-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=yong.wu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
--cc=yt.shen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.