答复: [PATCH 2/2] PCI: Layerscape: Add Layerscape PCIe driver
Arnd Bergmann
arnd at arndb.de
Fri Sep 5 01:44:10 PDT 2014
On Friday 05 September 2014 07:22:08 Minghuan.Lian at freescale.com wrote:
> Hi Arnd,
>
> Please see my comments inline.
Please use the usual reply style in the future, using '>' characters to
properly give attribution. I'm fixing this up manually in my reply
here, so others can follow the discussion.
> > On Thursday 04 September 2014 18:45:38 Minghuan Lian wrote:
> > > +
> > > +#define PCIE_LS1021A_BASE 0x3400000
> > > +#define PCIE_LS1021A_REG_SIZE 0x0100000
> >
> > This does not belong here. All addresses must come from DT,
> > and you should not do the calculation below based on the address.
> [Minghuan] LS1021A contains two PCI controllers. I use them to
> calculation the PCI controller index.
> There are several separate registers for PEX1 and PEX2 in SCFG
> register space. It is hard to get them address from DTS. Could
> you tell me a way to get PCI controller index?
The easiest way would be to put the index as a property in the
device tree itself.
> > +struct ls_pcie {
> > + struct list_head node;
> > + struct device *dev;
> > + struct pci_bus *bus;
> > + void __iomem *dbi;
> > + void __iomem *scfg;
> > + struct pcie_port pp;
> > + int id;
> > + int index;
> > + int irq;
> > + int msi_irq;
> > + int pme_irq;
> > +};
>
> irq and pme_irq seem to be completely unused, so better
> not add them until they are actually used.
> [Minghuan] Ok, I will remove them.
>
> The scfg registers seem to belong to another device that
> is responsible for multiple instances. Unfortunately,
> this "fsl,ls1021a-scfg" device is not documented anywhere
> that I can see.
>
> Is this some sort of syscon node, or is it specific to the
> pcie controller(s)?
>
> [Minghaun] SCFG provides SoC specific configuration and status
> registers for the device including PCI USB eTSEC SATA ...
> The platform patches that contains SCFG code are being upstream.
This sounds like it should be a syscon node, and you should use
syscon_regmap_lookup_by_phandle() to find the scfg node from each
of those drivers, rather than scanning the DT yourself in each
of the drivers using it.
This can also be a place to put the index, such as
scfg = <&scfg 0>;
for the first PCIe node. The probe function then extracts both
the phandle for the syscon and the index from that property.
> > +static int ls_pcie_link_up(struct pcie_port *pp)
> > +{
> > + u32 rc, tmp;
> > + struct ls_pcie *pcie = to_ls_pcie(pp);
> > +
> > + tmp = ioread32(pcie->scfg + SCFG_SCFGREVCR_OFF);
> > + iowrite32(SCFG_NO_BIT_REVERSE, pcie->scfg + SCFG_SCFGREVCR_OFF);
> > +
> > + rc = (ioread32(pcie->scfg + PEXMSCPORTSR(pcie->index)) >>
> > + LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
> > +
> > + iowrite32(tmp, pcie->scfg + SCFG_SCFGREVCR_OFF);
> > +
> > + if (rc < LTSSM_PCIE_L0)
> > + return 0;
> > +
> > + return 1;
> > +}
>
> This looks like it is really a phy driver, although a pretty minimal
> one.
>
> [Minghuan] I read SCFG register. SCFG provides SoC specific configuration
> and status registers for the device including PCI USB eTSEC SATA ...
I'm guessing that a lot of that is phy related information though.
A nicer way to deal with this, compared to using syscon directly is
to have a phy driver for your chip, and have that deal with all
the phy related setup. In this case you would have a reference in
the client driver like
phys = <&scfgphy LS1021A_PHY_PCIE0>;
phy-names = "pcie";
And in the pcie driver you just call devm_phy_get(dev, "pcie") to get a reference
to that phy node, and then you can use the phy API to perform actions on
it (init, power_on, power_off, exit).
This keeps all knowledge about the phy registers inside of the scfg area
in one place, and you only have to add a new phy driver for a future SoC
that has the same PCIe core but different scfg.
> > +static u32 ls_pcie_get_msi_addr(struct pcie_port *pp)
> > +{
> > + return SCFG_SPIMSICR_ADDR;
> > +}
> > +
> > +static u32 ls_pcie_get_msi_data(struct pcie_port *pp, int pos)
> > +{
> > + struct ls_pcie *pcie = to_ls_pcie(pp);
> > +
> > + if (pcie->id == PCI_DEVICE_ID_LS1021A)
> > + return MSI_LS1021A_DATA(pcie->index);
> > +
> > + return pos;
> > +}
>
> My impression is that you have two distinct MSI controller
> implementations, one for LS1021A and the other one for everything
> else. How about using separate pcie_host_ops for them, possibly
> also moving them into separate files?
>
> A good way to deal with this is to put the pointers to the two
> pcie_host_ops into the data fields of the ls_pcie_of_match table.
>
> [Minghuan] LS1021 contains the same two PCI controllers PEX1 and PEX2.
> both PEX1 and PEX use the same MSI address, but different MSI message data.
I mean LS1021 is different from other chips here, since you compare
the pcie->id value.
Arnd
More information about the linux-arm-kernel
mailing list