Re: [PATCH v2 2/4] mfd: ioc3: Add driver for SGI IOC3 chip
From: Thomas Bogendoerfer
Date: Thu May 09 2019 - 10:03:36 EST
On Wed, 8 May 2019 11:23:13 +0100
Lee Jones <lee.jones@xxxxxxxxxx> wrote:
> On Tue, 09 Apr 2019, Thomas Bogendoerfer wrote:
>
> > +static u32 crc8_addr(u64 addr)
> > +{
> > + u32 crc = 0;
> > + int i;
> > +
> > + for (i = 0; i < 64; i += 8)
> > + crc8_byte(&crc, addr >> i);
> > + return crc;
> > +}
>
> Not looked into these in any detail, but are you not able to use the
> CRC functions already provided by the kernel?
they are using a different polynomial, so I can't use it.
> > + }
> > + pr_err("ioc3: CRC error in NIC address\n");
> > +}
>
> This all looks like networking code. If this is the case, it should
> be moved to drivers/networking or similar.
no it's not. nic stands for number in a can produced by Dallas Semi also
known under the name 1-Wire (https://en.wikipedia.org/wiki/1-Wire).
SGI used them to provide partnumber, serialnumber and mac addresses.
By placing the code to read the NiCs inside ioc3 driver there is no need
for locking and adding library code for accessing these informations.
> > +static struct resource ioc3_uarta_resources[] = {
> > + DEFINE_RES_MEM(offsetof(struct ioc3, sregs.uarta),
>
> You are the first user of offsetof() in MFD. Could you tell me why
> it's required please?
to get the offsets of different chip functions out of a struct.
> Please drop all of these and statically create the MFD cells like
> almost all other MFD drivers do.
I started that way and it blew up the driver and create a bigger mess
than I wanted to have. What's your concern with my approach ?
I could use static mfd_cell arrays, if there would be a init/startup
method per cell, which is called before setting up the platform device.
That way I could do the dynamic setup for ethernet and serial devices.
> > +static void ioc3_create_devices(struct ioc3_priv_data *ipd)
> > +{
> > + struct mfd_cell *cell;
> > +
> > + memset(ioc3_mfd_cells, 0, sizeof(ioc3_mfd_cells));
> > + cell = ioc3_mfd_cells;
> > +
> > + if (ipd->info->funcs & IOC3_ETH) {
> > + memcpy(ioc3_eth_platform_data.mac_addr, ipd->nic_mac,
> > + sizeof(ioc3_eth_platform_data.mac_addr));
>
> Better to pull the MAC address from within the Ethernet driver.
the NiC where the MAC address is provided is connected to the ioc3
chip outside of the ethernet register set. And there is another
NiC connected to the same 1-W bus. So moving reading of the MAC
address to the ethernet driver duplicates code and adds complexity
(locking). Again what's your concern here ?
> > + if (ipd->info->funcs & IOC3_SER) {
> > + writel(GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL,
> > + &ipd->regs->gpcr_s);
> > + writel(0, &ipd->regs->gppr[6]);
> > + writel(0, &ipd->regs->gppr[7]);
> > + udelay(100);
> > + writel(readl(&ipd->regs->port_a.sscr) & ~SSCR_DMA_EN,
> > + &ipd->regs->port_a.sscr);
> > + writel(readl(&ipd->regs->port_b.sscr) & ~SSCR_DMA_EN,
> > + &ipd->regs->port_b.sscr);
> > + udelay(1000);
>
> No idea what any of this does.
>
> It looks like it belongs in the serial driver (and needs comments).
it configures the IOC3 chip for serial usage. This is not part of
the serial register set, so it IMHO belongs in the MFD driver.
> > + }
> > +#if defined(CONFIG_SGI_IP27)
>
> What is this? Can't you obtain this dynamically by probing the H/W?
that's the machine type and the #ifdef CONFIG_xxx are just for saving space,
when compiled for other machines and it's easy to remove.
> > + if (ipd->info->irq_offset) {
>
> What does this really signify?
IOC3 ASICs are most of the time connected to a SGI bridge chip. IOC3 can
provide two interrupt lines, which are wired to the bridge chip. The first
interrupt is assigned via the PCI core, but since IOC3 is not a PCI multi
function device the second interrupt must be treated here. And the used
interrupt line on the bridge chip differs between boards.
Thank you for your review. I'll address all other comments not cited in
my mail.
Thomas.
--
SUSE Linux GmbH
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)