mbox series

[v3,0/3] soc: add NPCM BPC driver support

Message ID 20231213190528.3751583-1-tmaimon77@gmail.com
Headers show
Series soc: add NPCM BPC driver support | expand

Message

Tomer Maimon Dec. 13, 2023, 7:05 p.m. UTC
This patch set adds BIOS Post code (BPC) support for the Nuvoton 
NPCM Baseboard Management Controller (BMC).

Nuvoton BMC NPCM BIOS Post Code (BPC) monitoring two configurable 
I/O addresses written by the host on the bus, the capture data 
stored in 128-word FIFO.

NPCM BPC can support capture double words.

The NPCM BPC driver tested on NPCM750 Olympus board.

Addressed comments from:
 - Krzysztof Kozlowski : https://www.spinics.net/lists/kernel/msg5035188.html
 - Conor Dooley : https://www.spinics.net/lists/kernel/msg5034239.html
 - kernel test robot : https://www.spinics.net/lists/kernel/msg5034970.html

Changes since version 2:
 - Modify compatible bindings.
 - Add more details to nuvoton,bpc-en-dwcapture parameter. 
 - Using _is_visible() function to support NPCM8XX.
 - add __poll_t custom.

Changes since version 1:
 - Remove LPC present from the BPC driver.
 - Modify dt-bindings message header.
 - Add vendor to the file name.
 - Modify incorrect spelling.
 
Tomer Maimon (3):
  dt-bindings: soc: nuvoton: Add NPCM BPC
  soc: nuvoton: add configuration menu
  soc: nuvoton: add NPCM BPC driver

 .../soc/nuvoton/nuvoton,npcm-bpc.yaml         |  65 +++
 drivers/soc/nuvoton/Kconfig                   |  16 +-
 drivers/soc/nuvoton/Makefile                  |   1 +
 drivers/soc/nuvoton/npcm-bpc.c                | 387 ++++++++++++++++++
 4 files changed, 468 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/soc/nuvoton/nuvoton,npcm-bpc.yaml
 create mode 100644 drivers/soc/nuvoton/npcm-bpc.c

Comments

Krzysztof Kozlowski Dec. 14, 2023, 7:59 a.m. UTC | #1
On 13/12/2023 20:05, Tomer Maimon wrote:
> Add Nuvoton BMC NPCM BIOS post code (BPC) driver.
> 
> The NPCM BPC monitoring two configurable I/O address written by the host
> on the bus.
> 
> Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
> ---
>  drivers/soc/nuvoton/Kconfig    |   9 +
>  drivers/soc/nuvoton/Makefile   |   1 +
>  drivers/soc/nuvoton/npcm-bpc.c | 387 +++++++++++++++++++++++++++++++++
>  3 files changed, 397 insertions(+)
>  create mode 100644 drivers/soc/nuvoton/npcm-bpc.c
> 
> diff --git a/drivers/soc/nuvoton/Kconfig b/drivers/soc/nuvoton/Kconfig
> index d5102f5f0c28..ebd162633942 100644
> --- a/drivers/soc/nuvoton/Kconfig
> +++ b/drivers/soc/nuvoton/Kconfig
> @@ -2,6 +2,15 @@
>  
>  menu "NUVOTON SoC drivers"

...

> +
> +static int npcm_bpc_config_irq(struct npcm_bpc *bpc,
> +			       struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	int rc;
> +
> +	bpc->irq = platform_get_irq(pdev, 0);
> +	if (bpc->irq < 0) {
> +		dev_err(dev, "get IRQ failed\n");
> +		return bpc->irq;

return dev_err_probe

> +	}
> +
> +	rc = devm_request_irq(dev, bpc->irq,
> +			      npcm_bpc_irq, IRQF_SHARED,
> +			      DEVICE_NAME, bpc);
> +	if (rc < 0) {
> +		dev_warn(dev, "Unable to request IRQ %d\n", bpc->irq);

return dev_err_probe

> +		return rc;
> +	}
> +
> +	return 0;
> +}
> +
> +static int npcm_enable_bpc(struct npcm_bpc *bpc, struct device *dev,
> +			   int channel, u16 host_port)
> +{
> +	u8 addr_en, reg_en;
> +	int err;
> +
> +	init_waitqueue_head(&bpc->ch[channel].wq);
> +
> +	err = kfifo_alloc(&bpc->ch[channel].fifo, BPC_KFIFO_SIZE,
> +			  GFP_KERNEL);
> +	if (err)
> +		return err;
> +
> +	bpc->ch[channel].miscdev.minor = MISC_DYNAMIC_MINOR;
> +	bpc->ch[channel].miscdev.name =
> +		devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel);
> +	bpc->ch[channel].miscdev.fops = &npcm_bpc_fops;
> +	bpc->ch[channel].miscdev.parent = dev;
> +	err = misc_register(&bpc->ch[channel].miscdev);
> +	if (err)
> +		return err;
> +
> +	bpc->ch[channel].data = bpc;
> +	bpc->ch[channel].host_reset = false;
> +
> +	/* Enable host snoop channel at requested port */
> +	switch (channel) {
> +	case 0:
> +		addr_en = FIFO_IOADDR1_ENABLE;
> +		iowrite8((u8)host_port & 0xFF,
> +			 bpc->base + NPCM_BPCFA1L_REG);
> +		iowrite8((u8)(host_port >> 8),
> +			 bpc->base + NPCM_BPCFA1M_REG);
> +		break;
> +	case 1:
> +		addr_en = FIFO_IOADDR2_ENABLE;
> +		iowrite8((u8)host_port & 0xFF,
> +			 bpc->base + NPCM_BPCFA2L_REG);
> +		iowrite8((u8)(host_port >> 8),
> +			 bpc->base + NPCM_BPCFA2M_REG);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (bpc->en_dwcap)
> +		addr_en = FIFO_DWCAPTURE;
> +
> +	/*
> +	 * Enable FIFO Ready Interrupt, FIFO Capture of I/O addr,
> +	 * and Host Reset
> +	 */
> +	reg_en = ioread8(bpc->base + NPCM_BPCFEN_REG);
> +	iowrite8(reg_en | addr_en | FIFO_READY_INT_ENABLE |
> +		 HOST_RESET_INT_ENABLE, bpc->base + NPCM_BPCFEN_REG);
> +
> +	return 0;
> +}
> +
> +static void npcm_disable_bpc(struct npcm_bpc *bpc, int channel)
> +{
> +	u8 reg_en;
> +
> +	switch (channel) {
> +	case 0:
> +		reg_en = ioread8(bpc->base + NPCM_BPCFEN_REG);
> +		if (bpc->en_dwcap)
> +			iowrite8(reg_en & ~FIFO_DWCAPTURE,
> +				 bpc->base + NPCM_BPCFEN_REG);
> +		else
> +			iowrite8(reg_en & ~FIFO_IOADDR1_ENABLE,
> +				 bpc->base + NPCM_BPCFEN_REG);
> +		break;
> +	case 1:
> +		reg_en = ioread8(bpc->base + NPCM_BPCFEN_REG);
> +		iowrite8(reg_en & ~FIFO_IOADDR2_ENABLE,
> +			 bpc->base + NPCM_BPCFEN_REG);
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	if (!(reg_en & (FIFO_IOADDR1_ENABLE | FIFO_IOADDR2_ENABLE)))
> +		iowrite8(reg_en &
> +			 ~(FIFO_READY_INT_ENABLE | HOST_RESET_INT_ENABLE),
> +			 bpc->base + NPCM_BPCFEN_REG);
> +
> +	kfifo_free(&bpc->ch[channel].fifo);
> +	misc_deregister(&bpc->ch[channel].miscdev);
> +}
> +
> +static int npcm_bpc_probe(struct platform_device *pdev)
> +{
> +	struct npcm_bpc *bpc;
> +	struct device *dev;
> +	u32 port;
> +	int err;
> +
> +	dev = &pdev->dev;
> +
> +	bpc = devm_kzalloc(dev, sizeof(*bpc), GFP_KERNEL);
> +	if (!bpc)
> +		return -ENOMEM;
> +
> +	bpc->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(bpc->base))
> +		return PTR_ERR(bpc->base);
> +
> +	dev_set_drvdata(&pdev->dev, bpc);

Why do you use pdev again? Look earlier, you have local variable for this.

> +
> +	err = of_property_read_u32_index(dev->of_node, "nuvoton,monitor-ports",
> +					 0, &port);
> +	if (err) {
> +		dev_err(dev, "no monitor ports configured\n");
> +		return -ENODEV;
> +	}
> +
> +	bpc->en_dwcap =
> +		of_property_read_bool(dev->of_node, "nuvoton,bpc-en-dwcapture");
> +
> +	bpc->dev = dev;
> +
> +	err = npcm_bpc_config_irq(bpc, pdev);
> +	if (err)
> +		return err;
> +
> +	err = npcm_enable_bpc(bpc, dev, 0, port);
> +	if (err) {
> +		dev_err(dev, "Enable BIOS post code I/O port 0 failed\n");
> +		return err;
> +	}
> +
> +	/*
> +	 * Configuration of second BPC channel port is optional
> +	 * Double-Word Capture ignoring address 2
> +	 */
> +	if (!bpc->en_dwcap) {
> +		if (of_property_read_u32_index(dev->of_node,
> +					       "nuvoton,monitor-ports", 1,
> +					       &port) == 0) {
> +			err = npcm_enable_bpc(bpc, dev, 1, port);
> +			if (err) {
> +				dev_err(dev, "Enable BIOS post code I/O port 1 failed, disable I/O port 0\n");
> +				npcm_disable_bpc(bpc, 0);
> +				return err;
> +			}
> +		}
> +	}
> +
> +	pr_info("NPCM BIOS Post Code probe\n");

Drop

> +
> +	return err;
> +}
> +
> +static int npcm_bpc_remove(struct platform_device *pdev)
> +{
> +	struct npcm_bpc *bpc = dev_get_drvdata(&pdev->dev);
> +	u8 reg_en;
> +
> +	reg_en = ioread8(bpc->base + NPCM_BPCFEN_REG);
> +
> +	if (reg_en & FIFO_IOADDR1_ENABLE)
> +		npcm_disable_bpc(bpc, 0);
> +	if (reg_en & FIFO_IOADDR2_ENABLE)
> +		npcm_disable_bpc(bpc, 1);
> +

Best regards,
Krzysztof
Arnd Bergmann Dec. 14, 2023, 12:44 p.m. UTC | #2
On Wed, Dec 13, 2023, at 20:05, Tomer Maimon wrote:
> Add Nuvoton BMC NPCM BIOS post code (BPC) driver.
>
> The NPCM BPC monitoring two configurable I/O address written by the host
> on the bus.
>
> Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
> ---
>  drivers/soc/nuvoton/Kconfig    |   9 +
>  drivers/soc/nuvoton/Makefile   |   1 +
>  drivers/soc/nuvoton/npcm-bpc.c | 387 +++++++++++++++++++++++++++++++++
>  3 files changed, 397 insertions(+)
>  create mode 100644 drivers/soc/nuvoton/npcm-bpc.c

I try hard to avoid having user interfaces in drivers/soc/, that
subsystem should primarily be used for things that don't have an
existing subsystem in the kernel and are used by other in-kernel
drivers but don't export hteir own misc device.

> diff --git a/drivers/soc/nuvoton/Kconfig b/drivers/soc/nuvoton/Kconfig
> index d5102f5f0c28..ebd162633942 100644
> --- a/drivers/soc/nuvoton/Kconfig
> +++ b/drivers/soc/nuvoton/Kconfig
> @@ -2,6 +2,15 @@
> 
>  menu "NUVOTON SoC drivers"
> 
> +config NPCM_BPC
> +	tristate "NPCM BIOS Post Code support"
> +	depends on (ARCH_NPCM || COMPILE_TEST)
> +	help
> +	  Provides NPCM driver to control the BIOS Post Code
> +	  interface which allows the BMC to monitor and save
> +	  the data written by the host to an arbitrary I/O port,
> +	  the BPC is connected to the host thourgh LPC or eSPI bus.
> +

This one in particular looks like this might be implemented
by more than one BMC type, it's a fairly generic functionality.

Have you talked to the other maintainers of SoCs used in
OpenBMC about coming up with a common interface?

> +#define DEVICE_NAME	"npcm-bpc"

[nitpicking] No need for macros like this one, open-coding the
string is usually more readable.

    Arnd
Tomer Maimon Dec. 14, 2023, 2:09 p.m. UTC | #3
Hi Arnd,

Thanks for your comments.

On Thu, 14 Dec 2023 at 14:44, Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Wed, Dec 13, 2023, at 20:05, Tomer Maimon wrote:
> > Add Nuvoton BMC NPCM BIOS post code (BPC) driver.
> >
> > The NPCM BPC monitoring two configurable I/O address written by the host
> > on the bus.
> >
> > Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
> > ---
> >  drivers/soc/nuvoton/Kconfig    |   9 +
> >  drivers/soc/nuvoton/Makefile   |   1 +
> >  drivers/soc/nuvoton/npcm-bpc.c | 387 +++++++++++++++++++++++++++++++++
> >  3 files changed, 397 insertions(+)
> >  create mode 100644 drivers/soc/nuvoton/npcm-bpc.c
>
> I try hard to avoid having user interfaces in drivers/soc/, that
> subsystem should primarily be used for things that don't have an
> existing subsystem in the kernel and are used by other in-kernel
> drivers but don't export hteir own misc device.
>
> > diff --git a/drivers/soc/nuvoton/Kconfig b/drivers/soc/nuvoton/Kconfig
> > index d5102f5f0c28..ebd162633942 100644
> > --- a/drivers/soc/nuvoton/Kconfig
> > +++ b/drivers/soc/nuvoton/Kconfig
> > @@ -2,6 +2,15 @@
> >
> >  menu "NUVOTON SoC drivers"
> >
> > +config NPCM_BPC
> > +     tristate "NPCM BIOS Post Code support"
> > +     depends on (ARCH_NPCM || COMPILE_TEST)
> > +     help
> > +       Provides NPCM driver to control the BIOS Post Code
> > +       interface which allows the BMC to monitor and save
> > +       the data written by the host to an arbitrary I/O port,
> > +       the BPC is connected to the host thourgh LPC or eSPI bus.
> > +
>
> This one in particular looks like this might be implemented
> by more than one BMC type, it's a fairly generic functionality.
>
> Have you talked to the other maintainers of SoCs used in
> OpenBMC about coming up with a common interface?
Yes, Both Nuvoton and Aspeed use the same user-facing code to manage
the host snooping.
https://github.com/openbmc/phosphor-host-postd
>
> > +#define DEVICE_NAME  "npcm-bpc"
Will do.
>
> [nitpicking] No need for macros like this one, open-coding the
> string is usually more readable.
>
>     Arnd

Thanks,

Tomer
Arnd Bergmann Dec. 14, 2023, 3:48 p.m. UTC | #4
On Thu, Dec 14, 2023, at 14:09, Tomer Maimon wrote:
> On Thu, 14 Dec 2023 at 14:44, Arnd Bergmann <arnd@arndb.de> wrote:
>> >
>> > +config NPCM_BPC
>> > +     tristate "NPCM BIOS Post Code support"
>> > +     depends on (ARCH_NPCM || COMPILE_TEST)
>> > +     help
>> > +       Provides NPCM driver to control the BIOS Post Code
>> > +       interface which allows the BMC to monitor and save
>> > +       the data written by the host to an arbitrary I/O port,
>> > +       the BPC is connected to the host thourgh LPC or eSPI bus.
>> > +
>>
>> This one in particular looks like this might be implemented
>> by more than one BMC type, it's a fairly generic functionality.
>>
>> Have you talked to the other maintainers of SoCs used in
>> OpenBMC about coming up with a common interface?
> Yes, Both Nuvoton and Aspeed use the same user-facing code to manage
> the host snooping.
> https://github.com/openbmc/phosphor-host-postd

Ok, that's good. I found the driver in drivers/soc/aspeed/aspeed-lpc-snoop.c
now and see that the implementation looks very similar. 

I think we should do two things here:

 - split out the common code into a shared module that exports the
   symbols to be used by either one

 - find a better place for both drivers outside of drivers/soc.
   I would suggest drivers/misc/bmc/ but am open to other suggestions.

      Arnd
Tomer Maimon Dec. 14, 2023, 4:50 p.m. UTC | #5
Hi Arnd,

Thanks for your suggestion.

Appreciate it if Joel, OpenBMC Linux kernel maintainer,  could share
his thoughts about it.


On Thu, 14 Dec 2023 at 17:49, Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Thu, Dec 14, 2023, at 14:09, Tomer Maimon wrote:
> > On Thu, 14 Dec 2023 at 14:44, Arnd Bergmann <arnd@arndb.de> wrote:
> >> >
> >> > +config NPCM_BP
> >> > +     tristate "NPCM BIOS Post Code support"
> >> > +     depends on (ARCH_NPCM || COMPILE_TEST)
> >> > +     help
> >> > +       Provides NPCM driver to control the BIOS Post Code
> >> > +       interface which allows the BMC to monitor and save
> >> > +       the data written by the host to an arbitrary I/O port,
> >> > +       the BPC is connected to the host thourgh LPC or eSPI bus.
> >> > +
> >>
> >> This one in particular looks like this might be implemented
> >> by more than one BMC type, it's a fairly generic functionality.
> >>
> >> Have you talked to the other maintainers of SoCs used in
> >> OpenBMC about coming up with a common interface?
> > Yes, Both Nuvoton and Aspeed use the same user-facing code to manage
> > the host snooping.
> > https://github.com/openbmc/phosphor-host-postd
>
> Ok, that's good. I found the driver in drivers/soc/aspeed/aspeed-lpc-snoop.c
> now and see that the implementation looks very similar.
>
> I think we should do two things here:
>
>  - split out the common code into a shared module that exports the
>    symbols to be used by either one
>
>  - find a better place for both drivers outside of drivers/soc.
>    I would suggest drivers/misc/bmc/ but am open to other suggestions.
>
>       Arnd

Best regards,

Tomer