[PATCH V6 02/17] ST SPEAr13xx: Added PCIe host controller base driver support.
pratyush
pratyush.anand at st.com
Thu Mar 10 07:56:46 EST 2011
Hello Arnd,
On 3/1/2011 8:40 PM, Arnd Bergmann wrote:
> On Tuesday 01 March 2011, Viresh Kumar wrote:
>> From: Pratyush Anand <pratyush.anand at st.com>
>
> Hi Viresh and Pratyush,
>
> The code looks really nice, I have just a few comments, mostly
> about pointer type conversion.
>
>> SPEAr13xx family contains Synopsys designware PCIe version 3.30a. This
>> patch adds support for this PCIe module for spear platform.
>
> If this is a standard PCIe controller, why add it to the platform
> code instead of a common place like arch/arch/common or arch/arm/kernel ?
>
Yes, It is for Synopsys IP , but there are ST specific changes for accessing
HW resources.
>> diff --git a/arch/arm/mach-spear13xx/include/mach/hardware.h b/arch/arm/mach-spear13xx/include/mach/hardware.h
>> index fd8c2dc..c3fb454 100644
>> --- a/arch/arm/mach-spear13xx/include/mach/hardware.h
>> +++ b/arch/arm/mach-spear13xx/include/mach/hardware.h
>> @@ -28,4 +28,11 @@
>> /* typesafe io address */
>> #define __io_address(n) __io(IO_ADDRESS(n))
>
> I could not find the definition for __io() here, but I suspect this is
> wrong. If __io_address() is what you use for accessing the direct-mapped
> MMIO registers, it cannot also be what you use to access the PCIe PIO
> ports, so most likely one of the two is broken. Can you explain?
>
>> +#if defined(CONFIG_PCI)
>> +#define PCIBIOS_MIN_IO 0
>> +#define PCIBIOS_MIN_MEM 0
>> +#define pcibios_assign_all_busses() 0
>> +#endif
>> +
>
> No need for the #ifdef here, if you have no PCI, there won't be a conflict.
>
> Better make PCIBIOS_MIN_IO 0x1000, in order to avoid stepping over
> ISA port ranges.
>
In fact , I do not need these defines. I will remove them.
>> +static u32 spr_pcie_base[NUM_PCIE_PORTS] = {
>> + SPEAR13XX_PCIE0_BASE,
>> + SPEAR13XX_PCIE1_BASE,
>> + SPEAR13XX_PCIE2_BASE,
>> +};
>> +static u32 spr_pcie_app_base[NUM_PCIE_PORTS] = {
>> + SPEAR13XX_PCIE0_APP_BASE,
>> + SPEAR13XX_PCIE1_APP_BASE,
>> + SPEAR13XX_PCIE2_APP_BASE,
>> +};
>
> I think these should be __iomem pointers, not u32 tokens, since you
> are listing virtual addresses. If you unroll the loop in
> spear13xx_pcie_init() that uses these, you can actually get rid
> of the two arrays, and simplify the code used there at the
> same time.
>
will do it.
>> +#ifdef CONFIG_PCI_MSI
>> +static DECLARE_BITMAP(msi_irq_in_use[NUM_PCIE_PORTS], SPEAR_NUM_MSI_IRQS);
>> +static unsigned int spear_msi_data[NUM_PCIE_PORTS];
>> +
>> +static void spear13xx_msi_init(struct pcie_port *pp);
>> +#endif
>> +
>> +static void spear_pcie_int_handler(unsigned int irq, struct irq_desc *desc);
>
> It would be nice if you could avoid the forward declarations by reordering
> the functions if possible.
>
will do it.
>> +static int __init spear13xx_pcie_setup(int nr, struct pci_sys_data *sys)
>> +{
>> + struct pcie_port *pp;
>> + u32 val = 0;
>> +
>> + if (nr >= NUM_PCIE_PORTS)
>> + return 0;
>> +
>> + if ((*pcie_port_is_host)(nr) != 1)
>> + return 0;
>> +
>> + pp = &pcie_port[nr];
>> + if (!spear13xx_pcie_link_up((void __iomem *)pp->va_app_base))
>> + return 0;
>
> No need for the cast, va_app_base is already (void __iomem *).
>
ok.
>> +static void __init add_pcie_port(int port, u32 base, u32 app_base)
>> +{
>> + struct pcie_port *pp = &pcie_port[port];
>> + struct pcie_app_reg *app_reg;
>> +
>> + pp->port = port;
>> + pp->root_bus_nr = -1;
>> + pp->base = (void __iomem *)base;
>> + pp->app_base = (void __iomem *)app_base;
>> + pp->va_app_base = (void __iomem *) ioremap(app_base, 0x200);
>> + if (!pp->va_app_base) {
>> + pr_err("error with ioremap in function %s\n", __func__);
>> + return;
>> + }
>> + pp->va_dbi_base = (void __iomem *) ioremap(base, 0x2000);
>> + if (!pp->va_dbi_base) {
>> + pr_err("error with ioremap in function %s\n", __func__);
>> + return;
>> + }
>
> Please remove all these casts. Some are unneeded, some can go away
> after the things I mention above.
>
ok.
>> + spin_lock_init(&pp->conf_lock);
>> + memset(pp->res, 0, sizeof(pp->res));
>> + pr_info("spear13xx PCIe port %d\n", port);
>> + if (spear13xx_pcie_link_up((void __iomem *)pp->va_app_base)) {
>> + pr_info("link up in bios\n");
>> + } else {
>> + pr_info("link down in bios\n");
>> + spear13xx_pcie_host_init(pp);
>> + spear13xx_int_init(pp);
>> + app_reg = (struct pcie_app_reg *)pp->va_app_base;
>
> This cast looks invalid, you cast from __iomem to a regular pointer,
>
will typecast it with (struct pcie_app_reg __iomem*)
>> + pp->va_cfg0_base = (void __iomem *)
>> + ioremap(app_reg->in_cfg0_addr_start, IN_CFG0_SIZE);
>
> which breaks here when you pass the value to ioremap without doing a readl.
>
will modify.
>> +#ifdef CONFIG_PCI_MSI
>> +/* MSI int handler
>> + */
>> +static void handle_msi(struct pcie_port *pp)
>> +{
>> + unsigned long val;
>> + int i, pos;
>> +
>> + for (i = 0; i < 8; i++) {
>> + spear_dbi_read_reg(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
>> + (u32 *)&val);
>> + if (val) {
>> + pos = 0;
>> + while ((pos = find_next_bit(&val, 32, pos)) != 32) {
>> + generic_handle_irq(SPEAR_MSI0_INT_BASE
>> + + pp->port * SPEAR_NUM_MSI_IRQS
>> + + (i * 32) + pos);
>> + pos++;
>> + }
>> + }
>> + spear_dbi_write_reg(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, val);
>> + }
>> +}
>> +#else
>> +static void handle_msi(struct pcie_port *pp)
>> +{
>> +}
>> +#endif
>
> The MSI code is not big, but I'd still recommend moving it to a separate
> file, which gets compiled only when CONFIG_PCI_MSI is set. You can have
> the #ifdef and inline NOP alternative in a header for this.
>
will put it in a separate file.
Regards
Pratyush
> Arnd
> .
>
More information about the linux-arm-kernel
mailing list