All of lore.kernel.org
 help / color / mirror / Atom feed
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
> 

  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.