From: Arnd Bergmann <arnd@arndb.de>
To: Jingoo Han <jg1.han@samsung.com>
Cc: 'Kukjin Kim' <kgene.kim@samsung.com>,
'Bjorn Helgaas' <bhelgaas@google.com>,
linux-samsung-soc@vger.kernel.org, linux-pci@vger.kernel.org,
devicetree-discuss@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org,
'Grant Likely' <grant.likely@secretlab.ca>,
'Andrew Murray' <andrew.murray@arm.com>,
'Thomas Petazzoni' <thomas.petazzoni@free-electrons.com>,
'Thierry Reding' <thierry.reding@avionic-design.de>,
'Jason Gunthorpe' <jgunthorpe@obsidianresearch.com>,
'Surendranath Gurivireddy Balla' <suren.reddy@samsung.com>,
'Siva Reddy Kallam' <siva.kallam@samsung.com>,
'Thomas Abraham' <thomas.abraham@linaro.org>
Subject: Re: [PATCH V4 1/3] pci: Add PCIe driver for Samsung Exynos
Date: Wed, 12 Jun 2013 13:23:03 +0200 [thread overview]
Message-ID: <2061566.hRLrhtBK6z@wuerfel> (raw)
In-Reply-To: <003601ce6756$444e8cd0$cceba670$@samsung.com>
On Wednesday 12 June 2013 19:19:05 Jingoo Han wrote:
> +
> +struct pcie_port {
> + struct device *dev;
> + u8 controller;
> + u8 root_bus_nr;
> + void __iomem *dbi_base;
> + void __iomem *elbi_base;
> + void __iomem *phy_base;
> + void __iomem *purple_base;
> + phys_addr_t cfg0_base;
> + void __iomem *va_cfg0_base;
> + phys_addr_t cfg1_base;
> + void __iomem *va_cfg1_base;
> + phys_addr_t io_base;
> + phys_addr_t mem_base;
> + spinlock_t conf_lock;
> + struct resource cfg;
> + struct resource io;
> + struct resource mem;
> + struct pcie_port_info config;
> + struct clk *clk;
> + struct clk *bus_clk;
> + int irq;
> + int reset_gpio;
> +};
This looks much better now.
> +
> +/* synopsis specific PCIE configuration registers*/
> +#define PCIE_PORT_LINK_CONTROL 0x710
> +#define PORT_LINK_MODE_MASK (0x3f << 16)
> +#define PORT_LINK_MODE_4_LANES (0x7 << 16)
Do you mean this is a "Synopsys" designware part? In that case it
should really not be called "exynos-pcie" but "designware-pcie"
and you should make sure that the driver makes no assumptions about
the platform. A lot of other platforms also use designware
parts and should be able to reuse this driver.
> +static void exynos_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
> +{
> + u32 val;
> + void __iomem *dbi_base = pp->dbi_base;
> +
> + /* Program viewport 0 : OUTBOUND : CFG0 */
> + val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT);
> + writel_rc(pp, (u32)pp->cfg0_base, dbi_base + PCIE_ATU_LOWER_BASE);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_BASE);
> + writel_rc(pp, (u32)pp->cfg0_base + pp->config.cfg0_size - 1,
> + dbi_base + PCIE_ATU_LIMIT);
> + writel_rc(pp, busdev, dbi_base + PCIE_ATU_LOWER_TARGET);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET);
> + writel_rc(pp, PCIE_ATU_TYPE_CFG0, dbi_base + PCIE_ATU_CR1);
> + val = PCIE_ATU_ENABLE;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_CR2);
> +}
I think you should not assume that the physical base address is a 32
bit value. The hardware clearly supports "lower" and "upper" halves
for the address window, so when resource_size_t is 64 bit, you should
set the upper half accordingly. Since the hardware is always 64 bit,
you can use a "u64" type rather than resource_size_t to simplify the
code here.
> +static void exynos_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
> +{
> + u32 val;
> + void __iomem *dbi_base = pp->dbi_base;
> +
> + /* Program viewport 0 : OUTBOUND : MEM */
> + val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT);
> + writel_rc(pp, PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1);
> + val = PCIE_ATU_ENABLE;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_CR2);
> + writel_rc(pp, (u32)pp->mem_base, dbi_base + PCIE_ATU_LOWER_BASE);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_BASE);
> + writel_rc(pp, (u32)(pp->mem_base + pp->config.mem_size - 1),
> + dbi_base + PCIE_ATU_LIMIT);
> + writel_rc(pp, (u32)pp->mem_base, dbi_base + PCIE_ATU_LOWER_TARGET);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET);
> +}
You probably should not assume that there is a 1:1 mapping between
bus addresses and host physical addresses, but rather read both
values from the DT individually. With the ranges defined as
0x82000000 0 0x40210000 0x40210000 0 0x10000000>; /* non-prefetchable memory */
the second and third cell should go into
PCIE_ATU_UPPER_TARGET/PCIE_ATU_LOWER_TARGET, while the translated address
(from the third cell) should go into PCIE_ATU_LOWER_BASE/PCIE_ATU_UPPER_BASE
The PCIE_ATU_LIMIT seems to correctly get translated from the last
cell.
> +static void exynos_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
> +{
> + u32 val;
> + void __iomem *dbi_base = pp->dbi_base;
> +
> + /* Program viewport 1 : OUTBOUND : IO */
> + val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT);
> + writel_rc(pp, PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1);
> + val = PCIE_ATU_ENABLE;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_CR2);
> + writel_rc(pp, (u32)pp->io_base, dbi_base + PCIE_ATU_LOWER_BASE);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_BASE);
> + writel_rc(pp, (u32)(pp->io_base + pp->config.io_size - 1),
> + dbi_base + PCIE_ATU_LIMIT);
> + writel_rc(pp, (u32)pp->io_base, dbi_base + PCIE_ATU_LOWER_TARGET);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET);
> +}
You don't actually map the I/O space anywhere into virtual memory.
I think you need to call pci_ioremap_io with the pp->io_base at
boot time.
I think you mixed up the PCIE_ATU_LOWER_TARGET, it should really be 0,
since all I/O port numbers have to be smaller than IO_SPACE_LIMIT.
The first argument to pci_ioremap_io needs to be unique for each
domain and you need to use it to calculate the io_offset you
set in pci_sys_data->io_offset.
> +static void exynos_pcie_prog_viewport_mem_inbound(struct pcie_port *pp)
> +{
> + u32 val;
> + void __iomem *dbi_base = pp->dbi_base;
> + struct pcie_port_info *config = &pp->config;
> +
> + /* Program viewport 0 : INBOUND : MEMORY */
> + val = PCIE_ATU_REGION_INBOUND | PCIE_ATU_REGION_INDEX0;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT);
> + writel_rc(pp, PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1);
> + val = PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_CR2);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_LOWER_BASE);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_BASE);
> + writel_rc(pp, config->in_mem_size - 1, dbi_base + PCIE_ATU_LIMIT);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_LOWER_TARGET);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET);
> +}
You hardcode the in_mem_size to 256 MB. Does that mean you only allow
PCI bus master DMA on the first part of RAM? Shouldn't it get
computed from the actual location and size of RAM?
> +static void exynos_pcie_prog_viewport_io_inbound(struct pcie_port *pp)
> +{
> + u32 val;
> + void __iomem *dbi_base = pp->dbi_base;
> + struct pcie_port_info *config = &pp->config;
> +
> + /* Program viewport 1 : INBOUND : IO */
> + val = PCIE_ATU_REGION_INBOUND | PCIE_ATU_REGION_INDEX1;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT);
> + writel_rc(pp, PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1);
> + val = PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE;
> + writel_rc(pp, val, dbi_base + PCIE_ATU_CR2);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_LOWER_BASE);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_BASE);
> + writel_rc(pp, config->in_mem_size - 1, dbi_base + PCIE_ATU_LIMIT);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_LOWER_TARGET);
> + writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET);
> +}
I don't understand what in inbound I/O access actually means. What
does this do, is it for PCI target emulation?
> +
> +static int exynos_pcie_setup(int nr, struct pci_sys_data *sys)
> +{
> + struct pcie_port *pp;
> +
> + pp = sys_to_pcie(sys);
> +
> + if (!pp)
> + return 0;
> +
> + pci_add_resource_offset(&sys->resources, &pp->io, sys->io_offset);
> + pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> +
> + return 1;
> +}
You don't actually set up io_offset and mem_offset, right?
Arnd
next prev parent reply other threads:[~2013-06-12 11:23 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-12 10:19 [PATCH V4 1/3] pci: Add PCIe driver for Samsung Exynos Jingoo Han
2013-06-12 11:23 ` Arnd Bergmann [this message]
2013-06-13 13:18 ` Jingoo Han
2013-06-13 14:18 ` Arnd Bergmann
2013-06-20 9:58 ` Pratyush Anand
2013-06-20 10:58 ` Jingoo Han
2013-06-20 11:26 ` Pratyush Anand
2013-06-20 11:36 ` Jingoo Han
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=2061566.hRLrhtBK6z@wuerfel \
--to=arnd@arndb.de \
--cc=andrew.murray@arm.com \
--cc=bhelgaas@google.com \
--cc=devicetree-discuss@lists.ozlabs.org \
--cc=grant.likely@secretlab.ca \
--cc=jg1.han@samsung.com \
--cc=jgunthorpe@obsidianresearch.com \
--cc=kgene.kim@samsung.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=siva.kallam@samsung.com \
--cc=suren.reddy@samsung.com \
--cc=thierry.reding@avionic-design.de \
--cc=thomas.abraham@linaro.org \
--cc=thomas.petazzoni@free-electrons.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).