Re: [PATCH v3 3/3] soc: nuvoton: add NPCM BPC driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
> ---
>  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





[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux