Re: [PATCH V2 1/4] ARM64 LPC: Indirect ISA port IO introduced

From: Arnd Bergmann
Date: Wed Sep 07 2016 - 11:06:58 EST


On Wednesday, September 7, 2016 9:33:50 PM CEST Zhichang Yuan wrote:
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +
> +typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
> + size_t dlen, unsigned int count);
> +typedef void (*outhook)(void *devobj, unsigned long ptaddr,
> + const void *outbuf, size_t dlen,
> + unsigned int count);
> +
> +struct extio_ops {
> + inhook pfin;
> + outhook pfout;
> + void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_simops __refdata;
> +
> +/*Up to now, only applied to Hip06 LPC. Define as static here.*/
> +static inline void arm64_set_simops(struct extio_ops *ops)
> +{
> + if (ops)
> + WRITE_ONCE(arm64_simops, ops);
> +}
> +
> +
> +#define BUILDIO(bw, type) \
> +static inline type in##bw(unsigned long addr) \
> +{ \
> + if (addr >= PCIBIOS_MIN_IO) \
> + return read##bw(PCI_IOBASE + addr); \
> + return (arm64_simops && arm64_simops->pfin) ? \
> + arm64_simops->pfin(arm64_simops->devpara, addr, NULL, \
> + sizeof(type), 1) : -1; \
> +} \
>

Hmm, the way this is done, enabling CONFIG_ARM64_INDIRECT_PIO at
compile time means that only the dynamically registered PIO support
is possible for I/O port ranges 0-0xfff.

I think the runtime check should better test if simops was defined
first and fall back to normal PIO otherwise, in order to allow
LPC implementations on a PCI-LPC bridge.

How about allowing an I/O port range to be defined along with
the operations and check against that?

u8 intb(unsigned long port)
{
if (arm64_simops &&
(port >= arm64_simops->min) &&
(port <= arm64_simops->max))
return arm64_simops->pfin(arm64_simops, port, 1);
else
return readb(PCI_IOBASE + addr);
}

The other advantage of that is that you can dynamically register
a translation for the LPC port range into the Linux I/O port range
like PCI hosts do.

We may also want to move the inb/outb definitions into a .c file
as they are getting rather big.

Arnd