From nobody Wed Dec 17 20:41:33 2025 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 45AB11FDA83; Fri, 14 Mar 2025 11:21:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741951285; cv=none; b=Ezh6r/WDDIViWPZmhsGA19DDw0lXFXVvc3KoOHQ9w4C12U6P5Zc+iMvxYVNL2rrSRl64i3YfzILHULj0mVOE12p3+aItmp15OmncBJbsABWSYkKWEzoMpkyGLQf+CpHQIpO2VSMUidEFD8NZFOwUN0YhKJ/qhbp2EX9Pdjbh0Cc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741951285; c=relaxed/simple; bh=l1EVTowwyvKKgRoAY03CsjK7TX72m3a/uOj9bXlY/Ig=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SB2+UCDRiwjqTOPrrRupjd2HfMZ3FJIDOVAkC8hLd4gv34fnfCnjS+c/0vi10XYTr48y3QenJ8uftyEEIrKWi3jcJEhxlRnldJ3ZKt+tqAC0+56+8s1AZ9zEBLSBPi9HEvHB5qdXCFWVpu/lRpD1MNTmRgf5HRfCCNrcWRCyEus= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.12; Fri, 14 Mar 2025 19:21:14 +0800 Received: from aspeed-fw03.aspeedtech.com (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Fri, 14 Mar 2025 19:21:14 +0800 From: Kevin Chen To: , , , , , , , , , , , , , CC: Kevin Chen Subject: [PATCH v4 1/3] dt-binding: aspeed: Add LPC PCC controller Date: Fri, 14 Mar 2025 19:21:11 +0800 Message-ID: <20250314112113.953238-2-kevin_chen@aspeedtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250314112113.953238-1-kevin_chen@aspeedtech.com> References: <20250314112113.953238-1-kevin_chen@aspeedtech.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller. Signed-off-by: Kevin Chen --- .../devicetree/bindings/mfd/aspeed-lpc.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml b/Docume= ntation/devicetree/bindings/mfd/aspeed-lpc.yaml index 5dfe77aca167..178c151a19ba 100644 --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml @@ -149,6 +149,37 @@ patternProperties: - interrupts - snoop-ports =20 + "^lpc-pcc@[0-9a-f]+$": + type: object + additionalProperties: false + + description: + The LPC pcc interface allows the BMC to listen on and record the data + bytes written by the Host to the targeted LPC I/O pots. + + properties: + compatible: + items: + - enum: + - aspeed,ast2600-lpc-pcc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + pcc-ports: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + As a device handshake with a host using the port-mmaped I/O in x= 86 + architecture, need to handle specific which port I/O address for= use. + + required: + - compatible + - interrupts + - pcc-ports + "^uart-routing@[0-9a-f]+$": $ref: /schemas/soc/aspeed/uart-routing.yaml# description: The UART routing control under LPC register space @@ -176,6 +207,13 @@ examples: #size-cells =3D <1>; ranges =3D <0x0 0x1e789000 0x1000>; =20 + lpc_pcc: lpc-pcc@0 { + compatible =3D "aspeed,ast2600-lpc-pcc"; + reg =3D <0x0 0x140>; + interrupts =3D ; + pcc-ports =3D <0x80>; + }; + lpc_ctrl: lpc-ctrl@80 { compatible =3D "aspeed,ast2600-lpc-ctrl"; reg =3D <0x80 0x80>; --=20 2.34.1 From nobody Wed Dec 17 20:41:33 2025 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 17D281FDE2A; Fri, 14 Mar 2025 11:21:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741951287; cv=none; b=T5iGas3NoDei8LbyQrHMcb+xNXFdah4llcMxquak+yQUxhin9EbUXL7ptspoQiXzkpyCqX2+fCtRQwlTuGvflNiiMPVHeI7T2J3ud+LNgv+gLdUB9NgBLptU3PsSuMY63mvW6a5fbr4VgPIyEuGK5PQmGdC9swIBPWBSRUeal28= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741951287; c=relaxed/simple; bh=JlaPosHFcMTCduhHQ6vio5LbJwrALh+R4iVTfmW4Vwk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QVjaY1BYmUcrrZUVVLiFfK+2R9aJNKJoASY1lUwkZ1FXLa++J+bvTgwiNNVa4mXZ4CoYJSOCctcs0YYX0pWNcAkeNMBsMNWrljEV9YvEKEEigkFuWA7mAC1w+8hYrkzo7wwmx2FngBvyO9esfkvtQRWlzCEkJ5YHPkUcld5s57M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.12; Fri, 14 Mar 2025 19:21:14 +0800 Received: from aspeed-fw03.aspeedtech.com (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Fri, 14 Mar 2025 19:21:14 +0800 From: Kevin Chen To: , , , , , , , , , , , , , CC: Kevin Chen Subject: [PATCH v4 2/3] ARM: dts: aspeed-g6: Add AST2600 LPC PCC support Date: Fri, 14 Mar 2025 19:21:12 +0800 Message-ID: <20250314112113.953238-3-kevin_chen@aspeedtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250314112113.953238-1-kevin_chen@aspeedtech.com> References: <20250314112113.953238-1-kevin_chen@aspeedtech.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The AST2600 has PCC controller in LPC, placed in LPC node. Signed-off-by: Kevin Chen --- arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/as= peed/aspeed-g6.dtsi index 8ed715bd53aa..f238337e02da 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi @@ -626,6 +626,14 @@ lpc_snoop: lpc-snoop@80 { status =3D "disabled"; }; =20 + lpc_pcc: lpc-pcc@0 { + compatible =3D "aspeed,ast2600-lpc-pcc"; + reg =3D <0x0 0x140>; + interrupts =3D ; + pcc-ports =3D <0x80>; + status =3D "disabled"; + }; + lhc: lhc@a0 { compatible =3D "aspeed,ast2600-lhc"; reg =3D <0xa0 0x24 0xc8 0x8>; --=20 2.34.1 From nobody Wed Dec 17 20:41:33 2025 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2611B1FE467; Fri, 14 Mar 2025 11:21:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741951290; cv=none; b=fGseb+OdrOiEYhHvm1L7pbrvZ5QCgnBl4qpl4cPP/qNm1yc10f5d2S3zcrDPl0FOStQcdtly3HXJ7AZn/a+pCajOPqz0EHi5hfXLXkhSn2/+UM1uP26B202uYmkPiv/3ZGL+uQbUipM6oVrHQO1VsJh1kQ8g894t/LIIQb939pE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741951290; c=relaxed/simple; bh=k53ec9B0a9McaaRAWmhtmQgtdVim1GMb5OGjvj/rYak=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tpyyNez5Nn7pvSUMhI3q7jNMZxFqti8xEbyDVuaG+gjko+GDtO7AOQsMgIu+vZ5konUcphngwTM4ywNvN9/OpzuHPcIrgk62/XF2rL3XnPKPMpMxof+4xpugxRH0XHh7aG18B5qIKKQ4ZCudu6I/6Gizs0i2NM03yi1LxRfFMOo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.12; Fri, 14 Mar 2025 19:21:14 +0800 Received: from aspeed-fw03.aspeedtech.com (192.168.10.13) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Fri, 14 Mar 2025 19:21:14 +0800 From: Kevin Chen To: , , , , , , , , , , , , , CC: Kevin Chen Subject: [PATCH v4 3/3] soc: aspeed: lpc-pcc: Add PCC controller support Date: Fri, 14 Mar 2025 19:21:13 +0800 Message-ID: <20250314112113.953238-4-kevin_chen@aspeedtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250314112113.953238-1-kevin_chen@aspeedtech.com> References: <20250314112113.953238-1-kevin_chen@aspeedtech.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add LPC PCC controller driver to support POST code capture. Signed-off-by: Kevin Chen --- drivers/misc/Kconfig | 10 + drivers/misc/Makefile | 1 + drivers/misc/aspeed-lpc-pcc.c | 437 ++++++++++++++++++++++++++++++++++ 3 files changed, 448 insertions(+) create mode 100644 drivers/misc/aspeed-lpc-pcc.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 56bc72c7ce4a..35c1d2e0c271 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -50,6 +50,16 @@ config AD525X_DPOT_SPI To compile this driver as a module, choose M here: the module will be called ad525x_dpot-spi. =20 +config ASPEED_LPC_PCC + tristate "Aspeed Post Code Capture support" + select REGMAP + select MFD_SYSCON + default ARCH_ASPEED + help + Provides a driver to control the LPC PCC interface, + allowing the BMC to capture post code written by the + the host to an arbitrary LPC I/O port. + config DUMMY_IRQ tristate "Dummy IRQ handler" help diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 545aad06d088..4762da7804bf 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_IBMVMC) +=3D ibmvmc.o obj-$(CONFIG_AD525X_DPOT) +=3D ad525x_dpot.o obj-$(CONFIG_AD525X_DPOT_I2C) +=3D ad525x_dpot-i2c.o obj-$(CONFIG_AD525X_DPOT_SPI) +=3D ad525x_dpot-spi.o +obj-$(CONFIG_ASPEED_LPC_PCC) +=3D aspeed-lpc-pcc.o obj-$(CONFIG_ATMEL_SSC) +=3D atmel-ssc.o obj-$(CONFIG_DUMMY_IRQ) +=3D dummy-irq.o obj-$(CONFIG_ICS932S401) +=3D ics932s401.o diff --git a/drivers/misc/aspeed-lpc-pcc.c b/drivers/misc/aspeed-lpc-pcc.c new file mode 100644 index 000000000000..61c76cb176bc --- /dev/null +++ b/drivers/misc/aspeed-lpc-pcc.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) ASPEED Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "aspeed-lpc-pcc" + +static DEFINE_IDA(aspeed_pcc_ida); + +#define HICR5 0x80 +#define HICR5_EN_SNP0W BIT(0) +#define HICR5_EN_SNP1W BIT(2) +#define HICR6 0x084 +#define HICR6_EN2BMODE BIT(19) +#define SNPWADR 0x090 +#define PCCR6 0x0c4 +#define PCCR6_DMA_CUR_ADDR GENMASK(27, 0) +#define PCCR4 0x0d0 +#define PCCR4_DMA_ADDRL_MASK GENMASK(31, 0) +#define PCCR4_DMA_ADDRL_SHIFT 0 +#define PCCR5 0x0d4 +#define PCCR5_DMA_ADDRH_MASK GENMASK(27, 24) +#define PCCR5_DMA_ADDRH_SHIFT 24 +#define PCCR5_DMA_LEN_MASK GENMASK(23, 0) +#define PCCR5_DMA_LEN_SHIFT 0 +#define HICRB 0x100 +#define HICRB_ENSNP0D BIT(14) +#define HICRB_ENSNP1D BIT(15) +#define PCCR0 0x130 +#define PCCR0_EN_DMA_INT BIT(31) +#define PCCR0_EN_DMA_MODE BIT(14) +#define PCCR0_ADDR_SEL_MASK GENMASK(13, 12) +#define PCCR0_ADDR_SEL_SHIFT 12 +#define PCCR0_RX_TRIG_LVL_MASK GENMASK(10, 8) +#define PCCR0_RX_TRIG_LVL_SHIFT 8 +#define PCCR0_CLR_RX_FIFO BIT(7) +#define PCCR0_MODE_SEL_MASK GENMASK(5, 4) +#define PCCR0_MODE_SEL_SHIFT 4 +#define PCCR0_EN_RX_TMOUT_INT BIT(2) +#define PCCR0_EN_RX_AVAIL_INT BIT(1) +#define PCCR0_EN BIT(0) +#define PCCR1 0x134 +#define PCCR1_BASE_ADDR_MASK GENMASK(15, 0) +#define PCCR1_BASE_ADDR_SHIFT 0 +#define PCCR1_DONT_CARE_BITS_MASK GENMASK(21, 16) +#define PCCR1_DONT_CARE_BITS_SHIFT 16 +#define PCCR2 0x138 +#define PCCR2_INT_STATUS_PATTERN_B BIT(16) +#define PCCR2_INT_STATUS_PATTERN_A BIT(8) +#define PCCR2_INT_STATUS_DMA_DONE BIT(4) +#define PCCR2_INT_STATUS_DATA_RDY PCCR2_INT_STATUS_DMA_DONE +#define PCCR2_INT_STATUS_RX_OVER BIT(3) +#define PCCR2_INT_STATUS_RX_TMOUT BIT(2) +#define PCCR2_INT_STATUS_RX_AVAIL BIT(1) +#define PCCR3 0x13c +#define PCCR3_FIFO_DATA_MASK GENMASK(7, 0) + +#define PCC_DMA_BUFSZ (256 * SZ_1K) + +enum pcc_fifo_threshold { + PCC_FIFO_THR_1_BYTE, + PCC_FIFO_THR_1_EIGHTH, + PCC_FIFO_THR_2_EIGHTH, + PCC_FIFO_THR_3_EIGHTH, + PCC_FIFO_THR_4_EIGHTH, + PCC_FIFO_THR_5_EIGHTH, + PCC_FIFO_THR_6_EIGHTH, + PCC_FIFO_THR_7_EIGHTH, + PCC_FIFO_THR_8_EIGHTH, +}; + +enum pcc_record_mode { + PCC_REC_1B, + PCC_REC_2B, + PCC_REC_4B, + PCC_REC_FULL, +}; + +enum pcc_port_hbits_select { + PCC_PORT_HBITS_SEL_NONE, + PCC_PORT_HBITS_SEL_45, + PCC_PORT_HBITS_SEL_67, + PCC_PORT_HBITS_SEL_89, +}; + +struct aspeed_pcc_dma { + uint32_t rptr; + uint8_t *virt; + dma_addr_t addr; + uint32_t size; +}; + +struct aspeed_pcc_ctrl { + struct device *dev; + struct regmap *regmap; + int irq; + uint32_t port; + struct aspeed_pcc_dma dma; + struct kfifo fifo; + wait_queue_head_t wq; + struct miscdevice mdev; + int mdev_id; +}; + +static inline bool is_valid_rec_mode(uint32_t mode) +{ + return (mode > PCC_REC_FULL) ? false : true; +} + +static inline bool is_valid_high_bits_select(uint32_t sel) +{ + return (sel > PCC_PORT_HBITS_SEL_89) ? false : true; +} + +static ssize_t aspeed_pcc_file_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + int rc; + unsigned int copied; + struct aspeed_pcc_ctrl *pcc =3D container_of(file->private_data, + struct aspeed_pcc_ctrl, + mdev); + + if (kfifo_is_empty(&pcc->fifo)) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + rc =3D wait_event_interruptible(pcc->wq, + !kfifo_is_empty(&pcc->fifo)); + if (rc =3D=3D -ERESTARTSYS) + return -EINTR; + } + + rc =3D kfifo_to_user(&pcc->fifo, buffer, count, &copied); + + return rc ? rc : copied; +} + +static __poll_t aspeed_pcc_file_poll(struct file *file, + struct poll_table_struct *pt) +{ + struct aspeed_pcc_ctrl *pcc =3D container_of(file->private_data, + struct aspeed_pcc_ctrl, + mdev); + + poll_wait(file, &pcc->wq, pt); + + return !kfifo_is_empty(&pcc->fifo) ? POLLIN : 0; +} + +static const struct file_operations pcc_fops =3D { + .owner =3D THIS_MODULE, + .read =3D aspeed_pcc_file_read, + .poll =3D aspeed_pcc_file_poll, +}; + +static irqreturn_t aspeed_pcc_dma_isr(int irq, void *arg) +{ + uint32_t reg, rptr, wptr; + struct aspeed_pcc_ctrl *pcc =3D (struct aspeed_pcc_ctrl *)arg; + struct kfifo *fifo =3D &pcc->fifo; + + regmap_write_bits(pcc->regmap, PCCR2, PCCR2_INT_STATUS_DMA_DONE, PCCR2_IN= T_STATUS_DMA_DONE); + + regmap_read(pcc->regmap, PCCR6, ®); + wptr =3D (reg & PCCR6_DMA_CUR_ADDR) - (pcc->dma.addr & PCCR6_DMA_CUR_ADDR= ); + rptr =3D pcc->dma.rptr; + + do { + if (kfifo_is_full(fifo)) + kfifo_skip(fifo); + + kfifo_put(fifo, pcc->dma.virt[rptr]); + + rptr =3D (rptr + 1) % pcc->dma.size; + } while (rptr !=3D wptr); + + pcc->dma.rptr =3D rptr; + + wake_up_interruptible(&pcc->wq); + + return IRQ_HANDLED; +} + +static irqreturn_t aspeed_pcc_isr(int irq, void *arg) +{ + uint32_t sts; + struct aspeed_pcc_ctrl *pcc =3D (struct aspeed_pcc_ctrl *)arg; + + regmap_read(pcc->regmap, PCCR2, &sts); + + if (!(sts & (PCCR2_INT_STATUS_RX_TMOUT | + PCCR2_INT_STATUS_RX_AVAIL | + PCCR2_INT_STATUS_DMA_DONE))) + return IRQ_NONE; + + return aspeed_pcc_dma_isr(irq, arg); +} + +/* + * A2600-15 AP note + * + * SW workaround to prevent generating Non-Fatal-Error (NFE) + * eSPI response when PCC is used for port I/O byte snooping + * over eSPI. + */ +static int aspeed_a2600_15(struct aspeed_pcc_ctrl *pcc, struct device *dev) +{ + u32 hicr5_en, hicrb_en; + + /* abort if snoop is enabled */ + regmap_read(pcc->regmap, HICR5, &hicr5_en); + if (hicr5_en & (HICR5_EN_SNP0W | HICR5_EN_SNP1W)) { + dev_err(dev, "A2600-15 should be applied with snoop disabled\n"); + return -EPERM; + } + + /* set SNPWADR of snoop device */ + regmap_write(pcc->regmap, SNPWADR, pcc->port | ((pcc->port + 2) << 16)); + + /* set HICRB[15:14]=3D11b to enable ACCEPT response for SNPWADR */ + hicrb_en =3D HICRB_ENSNP0D | HICRB_ENSNP1D; + regmap_update_bits(pcc->regmap, HICRB, hicrb_en, hicrb_en); + + /* set HICR6[19] to extend SNPWADR to 2x range */ + regmap_update_bits(pcc->regmap, HICR6, HICR6_EN2BMODE, HICR6_EN2BMODE); + + return 0; +} + +static int aspeed_pcc_enable(struct aspeed_pcc_ctrl *pcc, struct device *d= ev) +{ + int rc; + + rc =3D aspeed_a2600_15(pcc, dev); + if (rc) + return rc; + + /* record mode: Set 2-Byte mode. */ + regmap_update_bits(pcc->regmap, PCCR0, + PCCR0_MODE_SEL_MASK, + PCC_REC_2B << PCCR0_MODE_SEL_SHIFT); + + /* port address */ + regmap_update_bits(pcc->regmap, PCCR1, + PCCR1_BASE_ADDR_MASK, + pcc->port << PCCR1_BASE_ADDR_SHIFT); + + /* Set address high bits selection to 0b01 for address bit[5:4] */ + regmap_update_bits(pcc->regmap, PCCR0, + PCCR0_ADDR_SEL_MASK, + PCC_PORT_HBITS_SEL_45 << PCCR0_ADDR_SEL_SHIFT); + + /* Set LPC don't care address to 0x3 for port 80~83h */ + regmap_update_bits(pcc->regmap, PCCR1, + PCCR1_DONT_CARE_BITS_MASK, + 0x3 << PCCR1_DONT_CARE_BITS_SHIFT); + + /* set DMA ring buffer size and enable interrupts */ + regmap_write(pcc->regmap, PCCR4, pcc->dma.addr & 0xffffffff); +#ifdef CONFIG_ARM64 + regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_ADDRH_MASK, + (pcc->dma.addr >> 32) << PCCR5_DMA_ADDRH_SHIFT); +#endif + regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_LEN_MASK, + (pcc->dma.size / 4) << PCCR5_DMA_LEN_SHIFT); + regmap_update_bits(pcc->regmap, PCCR0, + PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE, + PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE); + + regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN, PCCR0_EN); + + return 0; +} + +static int aspeed_pcc_disable(struct aspeed_pcc_ctrl *pcc) +{ + /* Disable PCC and DMA Mode for safety */ + regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN | PCCR0_EN_DMA_MODE, 0); + + /* Clear Rx FIFO. */ + regmap_update_bits(pcc->regmap, PCCR0, PCCR0_CLR_RX_FIFO, 1); + + /* Clear All interrupts status. */ + regmap_write(pcc->regmap, PCCR2, + PCCR2_INT_STATUS_RX_OVER | PCCR2_INT_STATUS_DMA_DONE | + PCCR2_INT_STATUS_PATTERN_A | PCCR2_INT_STATUS_PATTERN_B); + + return 0; +} + +static int aspeed_pcc_probe(struct platform_device *pdev) +{ + int rc; + struct aspeed_pcc_ctrl *pcc; + struct device *dev =3D &pdev->dev; + uint32_t fifo_size =3D PAGE_SIZE; + + pcc =3D devm_kzalloc(dev, sizeof(*pcc), GFP_KERNEL); + if (!pcc) + return -ENOMEM; + + pcc->regmap =3D syscon_node_to_regmap(dev->parent->of_node); + if (IS_ERR(pcc->regmap)) + return dev_err_probe(dev, PTR_ERR(pcc->regmap), "Couldn't get regmap\n"); + + rc =3D of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port); + if (rc) { + dev_err(dev, "no pcc ports configured\n"); + return rc; + } + + rc =3D dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (rc) { + dev_err(dev, "cannot set 64-bits DMA mask\n"); + return rc; + } + + pcc->dma.size =3D PCC_DMA_BUFSZ; + pcc->dma.virt =3D dmam_alloc_coherent(dev, + pcc->dma.size, + &pcc->dma.addr, + GFP_KERNEL); + if (!pcc->dma.virt) { + dev_err(dev, "cannot allocate DMA buffer\n"); + return -ENOMEM; + } + + fifo_size =3D roundup(pcc->dma.size, PAGE_SIZE); + rc =3D kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL); + if (rc) + return rc; + + /* Disable PCC to clean up DMA buffer before request IRQ. */ + rc =3D aspeed_pcc_disable(pcc); + if (rc) { + dev_err(dev, "Couldn't disable PCC\n"); + goto err_free_kfifo; + } + + pcc->irq =3D platform_get_irq(pdev, 0); + if (pcc->irq < 0) { + rc =3D pcc->irq; + goto err_free_kfifo; + } + + rc =3D devm_request_irq(dev, pcc->irq, aspeed_pcc_isr, 0, DEVICE_NAME, pc= c); + if (rc < 0) { + dev_err(dev, "Couldn't request IRQ %d\n", pcc->irq); + goto err_free_kfifo; + } + + init_waitqueue_head(&pcc->wq); + + pcc->mdev_id =3D ida_alloc(&aspeed_pcc_ida, GFP_KERNEL); + if (pcc->mdev_id < 0) { + dev_err(dev, "Couldn't allocate ID\n"); + goto err_free_kfifo; + } + + pcc->mdev.parent =3D dev; + pcc->mdev.minor =3D MISC_DYNAMIC_MINOR; + pcc->mdev.name =3D devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, + pcc->mdev_id); + pcc->mdev.fops =3D &pcc_fops; + rc =3D misc_register(&pcc->mdev); + if (rc) { + dev_err(dev, "Couldn't register misc device\n"); + goto err_free_ida; + } + + rc =3D aspeed_pcc_enable(pcc, dev); + if (rc) { + dev_err(dev, "Couldn't enable PCC\n"); + goto err_dereg_mdev; + } + + dev_set_drvdata(dev, pcc); + + return 0; + +err_dereg_mdev: + misc_deregister(&pcc->mdev); + +err_free_ida: + ida_free(&aspeed_pcc_ida, pcc->mdev_id); + +err_free_kfifo: + kfifo_free(&pcc->fifo); + + return rc; +} + +static void aspeed_pcc_remove(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct aspeed_pcc_ctrl *pcc =3D dev_get_drvdata(dev); + + kfifo_free(&pcc->fifo); + ida_free(&aspeed_pcc_ida, pcc->mdev_id); + misc_deregister(&pcc->mdev); +} + +static const struct of_device_id aspeed_pcc_table[] =3D { + { .compatible =3D "aspeed,ast2600-lpc-pcc" }, +}; + +static struct platform_driver aspeed_pcc_driver =3D { + .driver =3D { + .name =3D "aspeed-pcc", + .of_match_table =3D aspeed_pcc_table, + }, + .probe =3D aspeed_pcc_probe, + .remove =3D aspeed_pcc_remove, +}; + +module_platform_driver(aspeed_pcc_driver); + +MODULE_AUTHOR("Chia-Wei Wang "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Driver for Aspeed Post Code Capture"); --=20 2.34.1