* Re: [PATCH v3 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop
From: Krzysztof Kozlowski @ 2026-06-25 6:36 UTC (permalink / raw)
To: Grégoire Layet
Cc: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt, andrew, jacky_chou, yh_chung, ninad,
anirudhsriniv, linux-serial, linux-aspeed, linux-arm-kernel,
linux-kernel
In-Reply-To: <CAFi2wKbKr8FMcJeGWA5e1UZUTh2=LwYNkLEj6exd2as7=AcvVQ@mail.gmail.com>
On 24/06/2026 14:48, Grégoire Layet wrote:
> Hi Krzysztof,
>
>> What does that mean? How UART can be accessible over PCI bus?
>
> It's a Virtual UART. Internally, it's two FIFOs accessible via
> 8250-compatible register sets on both ends.
I do not know what is Virtual UART...
> There is 4 Virtuals UARTs on the LPC bus of the AST2600 and 2 of them
> are bridged over the PCI bus.
> So, from the host, you can access the 8250 register set on the PCI bus.
You mean these appear (or are) as PCI devices?
>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v8 0/2] Add Meta(Facebook) ventura2 BMC(AST2600)
From: Kyle Hsieh @ 2026-06-25 5:35 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
Krzysztof Kozlowski
In-Reply-To: <20260615-ventura2_initial_dts-v8-0-c89f92c80447@gmail.com>
Hi Maintainers,
Just a gentle ping on this v8 series.
All review comments from the previous versions have been addressed.
Please let me know if there is anything else needed for this to be
applied.
Thanks,
Kyle
On Mon, Jun 15, 2026 at 10:44 AM Kyle Hsieh <kylehsieh1995@gmail.com> wrote:
>
> Summary:
> Add linux device tree entry related to Meta(Facebook) ventura2.
> specific devices connected to BMC(AST2600) SoC.
>
> Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
> ---
> Changes in v8:
> - Addressed review comments from Andrew Lunn:
> * Added a detailed comment to the Marvell 88E6393X EEPROM node to clarify its hardware I2C multiplexer isolation and out-of-band firmware update mechanism, explaining why there is no concurrent access or multi-master scenario.
> - Link to v7: https://lore.kernel.org/r/20260611-ventura2_initial_dts-v7-0-a61d8902bc5f@gmail.com
>
> Changes in v7:
> - Updated the commit message to include a detailed description of the Ventura2 platform's purpose and its key hardware features.
> - Fix comments from Andrew Jeffery:
> * Ensured consistent blank lines to separate child nodes from parent properties and from each other throughout the DTS.
> * Sorted fan nodes in ascending order.
> * Replaced '//' comments with '/* */' block comments.
> - Fix feedback from Sashiko AI:
> * Added 'idle-state = <6>;' to the PCA9548 mux on i2c4.
> - Link to v6: https://lore.kernel.org/r/20260610-ventura2_initial_dts-v6-0-375d8e9d7ebf@gmail.com
>
> Changes in v6:
> - Addressed automated feedback from Sashiko bot:
> * Clarified comments that io_expander0 and io_expander8 physically share the same interrupt line (Wired-OR) by hardware design.
> * Removed leading zeros from unit addresses in DAC nodes (dac@c, dac@e, dac@f).
> * Removed unused properties from the adc@48 node.
> - Link to v5: https://lore.kernel.org/r/20260608-ventura2_initial_dts-v5-0-37ee5bcf58b6@gmail.com
>
> Changes in v5:
> - Addressed review comments:
> * Added comments explaining the necessity of 'legacy_' prefixes (hardware label collision), pre-allocated I2C aliases (future expansions), and the 'ledd1' naming convention (schematic alignment).
> * Removed the empty `&mdio0` node to comply with upstream networking subsystem guidelines.
> * Removed the redundant `&peci0` node.
> * Sorted `&kcs3` and `&lpc_ctrl` nodes in strict alphabetical order.
> - Hardware/DT alignment updates:
> * Removed unpopulated sensors (adi,adt7461, infineon,tda38640, ti,ina230, ti,ina238) to accurately reflect the current board population.
> * Added the secondary flash node (flash@1 labeled "e810") under the &spi2 bus.
> - Link to v4: https://lore.kernel.org/r/20260424-ventura2_initial_dts-v4-0-806b00ea4314@gmail.com
>
> Changes in v4:
> - Fixed capitalization: "ventura2" -> "Ventura2".
> - Reordered I2C child nodes in ascending order of unit addresses.
> - Enable PECI, LPC control, and KCS3 interfaces for host communication.
> - Configure MCTP controller on I2C4 and enable MCTP support for specific mux channels.
> - Add Infineon TDA38640 and TI INA230 power monitor nodes.
> - GPIO and Pinmux cleanup for PVT:
> - Aligned gpio-line-names as requested.
> - Remove unused or non-existent GPIO line names to align with Ventura2 PVT.
> - Update specific GPIO pins to empty strings where signals were removed or consolidated.
> - Adjust SGPIOM frequency to 200kHz and update signal line names.
> - Enable UART3 and add serial2 alias.
> - Link to v3: https://lore.kernel.org/r/20260113-ventura2_initial_dts-v3-0-2dbfda6a5b47@gmail.com
>
> Changes in v3:
> - Add annotation for marvel 88e6393x
> - Modify the gpio-line-name
> - Modify the node order alphabetically
> - Modify dt-bindings document for rmc instead of bmc
> - Move the gpio-line-names to original node
> - Link to v2: https://lore.kernel.org/r/20251224-ventura2_initial_dts-v2-0-f193ba5d4073@gmail.com
>
> Changes in v2:
> - Remove unused mdio
> - Link to v1: https://lore.kernel.org/r/20251222-ventura2_initial_dts-v1-0-1f06166c78a3@gmail.com
>
> ---
> Kyle Hsieh (2):
> dt-bindings: arm: aspeed: add Meta ventura2 board
> ARM: dts: aspeed: ventura2: Add Meta ventura2 BMC
>
> .../devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
> arch/arm/boot/dts/aspeed/Makefile | 1 +
> .../dts/aspeed/aspeed-bmc-facebook-ventura2.dts | 2903 ++++++++++++++++++++
> 3 files changed, 2905 insertions(+)
> ---
> base-commit: 9448598b22c50c8a5bb77a9103e2d49f134c9578
> change-id: 20251222-ventura2_initial_dts-909b3277d665
>
> Best regards,
> --
> Kyle Hsieh <kylehsieh1995@gmail.com>
>
^ permalink raw reply
* Re: [PATCH v3 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop
From: Grégoire Layet @ 2026-06-24 12:48 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt, andrew, jacky_chou, yh_chung, ninad,
anirudhsriniv, linux-serial, linux-aspeed, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260624-original-vigorous-mayfly-dfceac@quoll>
Hi Krzysztof,
> What does that mean? How UART can be accessible over PCI bus?
It's a Virtual UART. Internally, it's two FIFOs accessible via
8250-compatible register sets on both ends.
There is 4 Virtuals UARTs on the LPC bus of the AST2600 and 2 of them
are bridged over the PCI bus.
So, from the host, you can access the 8250 register set on the PCI bus.
> > + aspeed,vuart-over-pci:
> > + type: boolean
> > + default: false
>
> There is no such syntax. Please do not introduce own style. Instead,
> look at other files how this is done.
Ack. I will remove 'default: false' for the v4.
> > + description: |
>
> Do not need '|' unless you need to preserve formatting.
Acknowledged
Best regards,
Grégoire
^ permalink raw reply
* Re: [PATCH v3 1/7] dt-bindings: serial: 8250: aspeed: add compatible string for ast2600
From: Grégoire Layet @ 2026-06-24 12:48 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt, andrew, jacky_chou, yh_chung, ninad,
anirudhsriniv, linux-serial, linux-aspeed, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260624-realistic-spiked-parrot-db1d9c@quoll>
Hi Krzysztof,
> Do not attach (thread) your patchsets to some other threads (unrelated
> or older versions). This buries them deep in the mailbox and might
> interfere with applying entire sets. See also:
> https://elixir.bootlin.com/linux/v6.16-rc2/source/Documentation/process/submitting-patches.rst#L830
Oh okay sorry I missed this information. Thank's for letting me know !
> This should be oneOf (by convention and actually more accurate meaning).
Acknowledged
> More important, where is documenting of the actual compatible?
Yes, you are right, I missed it. Will be added in v4.
Best regards,
Grégoire
^ permalink raw reply
* Re: [PATCH v3 6/7] ARM: dts: aspeed: g6: Change vuart compatible string for ast2600
From: Grégoire Layet @ 2026-06-24 13:44 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt, andrew, jacky_chou, yh_chung, ninad,
anirudhsriniv, linux-serial, linux-aspeed, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260624-copper-albatross-of-youth-6abae8@quoll>
Hi Krzysztof,
> Please start testing your patches. This for sure fails tests.
>
> It does not look like you tested the DTS against bindings. Please run
> 'make dtbs_check W=1' (see
> Documentation/devicetree/bindings/writing-schema.rst or
> https://www.linaro.org/blog/tips-and-tricks-for-validating-devicetree-sources-with-the-devicetree-schema/
> for instructions).
> Maybe you need to update your dtschema and yamllint. Don't rely on
> distro packages for dtschema and be sure you are using the latest
> released dtschema.
You are right, I had tested my patches but wrongly. It is indeed failling.
I'm very sorry for that. Thank's for taking the time to explain.
Best regards,
Grégoire
^ permalink raw reply
* Re: [PATCH 0/2] rtc: aspeed: Add AST2700 RTC support
From: Alexandre Belloni @ 2026-06-24 21:16 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, Tommy Huang
Cc: linux-rtc, devicetree, linux-kernel, linux-arm-kernel,
linux-aspeed
In-Reply-To: <20260601-ast2700-rtc-v1-0-15d4ca46500a@aspeedtech.com>
On Mon, 01 Jun 2026 17:14:05 +0800, Tommy Huang wrote:
> This patch series adds support for the ASPEED AST2700 RTC define,
> includeing dt-binding in the Document and rtc-aspeed.c
Applied, thanks!
[1/2] dt-bindings: rtc: add ASPEED AST2700 compatible
https://git.kernel.org/abelloni/c/5e7f746bc106
[2/2] rtc: aspeed: add AST2700 compatible
https://git.kernel.org/abelloni/c/3319cfeeb8c4
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: clock: ast2700: add PECI clock
From: Conor Dooley @ 2026-06-24 16:29 UTC (permalink / raw)
To: Ryan Chen
Cc: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
linux-clk, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel
In-Reply-To: <20260624-peci_clk-v1-1-ee28b92e22e9@aspeedtech.com>
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
From: Markus Elfring @ 2026-06-24 12:14 UTC (permalink / raw)
To: YH Chung, linux-aspeed, openbmc, linux-arm-kernel, devicetree,
Andrew Jeffery, Conor Dooley, Joel Stanley, Krzysztof Kozlowski,
Philipp Zabel, Rob Herring, Ryan Chen
Cc: LKML, Maciej Lawniczak
In-Reply-To: <20260313-upstream_espi-v1-5-9504428e1f43@aspeedtech.com>
…
> +++ b/drivers/soc/aspeed/espi/aspeed-espi.c
…
> +static void aspeed_espi_flash_rx_work(struct work_struct *work)
> +{
> + struct aspeed_espi_flash *flash = container_of(work, struct aspeed_espi_flash, rx_work);
> + struct aspeed_espi *espi = container_of(flash, struct aspeed_espi, flash);
> +
> + mutex_lock(&flash->tx_mtx);
> + aspeed_espi_flash_handle_lun(espi);
> + mutex_unlock(&flash->tx_mtx);
> +}
…
Under which circumstances would you become interested to apply a statement
like “guard(mutex)(&flash->tx_mtx);”?
https://elixir.bootlin.com/linux/v7.1.1/source/include/linux/mutex.h#L253
Regards,
Markus
^ permalink raw reply
* Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
From: Markus Elfring @ 2026-06-24 12:02 UTC (permalink / raw)
To: YH Chung, linux-aspeed, openbmc, linux-arm-kernel, devicetree,
Andrew Jeffery, Conor Dooley, Joel Stanley, Krzysztof Kozlowski,
Philipp Zabel, Rob Herring, Ryan Chen
Cc: LKML, Maciej Lawniczak
In-Reply-To: <20260313-upstream_espi-v1-5-9504428e1f43@aspeedtech.com>
…
> +++ b/drivers/soc/aspeed/espi/aspeed-espi-comm.h
> @@ -0,0 +1,62 @@
…
> +/*
> + * eSPI cycle type encoding
> + *
> + * Section 5.1 Cycle Types and Packet Format,
> + * Intel eSPI Interface Base Specification, Rev 1.0, Jan. 2016.
> + */
> +#define ESPI_FLASH_READ 0x00
> +#define ESPI_FLASH_WRITE 0x01
> +#define ESPI_FLASH_ERASE 0x02
…
How do you think about to use an enumeration for such data?
https://en.wikipedia.org/wiki/Enumerated_type#C_and_syntactically_similar_languages
Regards,
Markus
^ permalink raw reply
* Re: [PATCH v3 6/7] ARM: dts: aspeed: g6: Change vuart compatible string for ast2600
From: Krzysztof Kozlowski @ 2026-06-24 7:19 UTC (permalink / raw)
To: Grégoire Layet
Cc: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt, andrew, jacky_chou, yh_chung, ninad,
anirudhsriniv, linux-serial, linux-aspeed, linux-arm-kernel,
linux-kernel
In-Reply-To: <30aedaa9ffd5ba2d763d8802a07b77ef2d5bfcf0.1782224060.git.gregoire.layet@9elements.com>
On Tue, Jun 23, 2026 at 02:25:44PM +0000, Grégoire Layet wrote:
> Use the ast2600 compatible string.
> This makes it more precise and enables specific ast2600 properties.
> Still use the ast2500 compatible string as a fallback.
>
> Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
> ---
> arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> index 56bb3b0444f7..7c02633f2bd6 100644
> --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> @@ -707,7 +707,7 @@ emmc: sdhci@1e750100 {
> };
>
> vuart1: serial@1e787000 {
> - compatible = "aspeed,ast2500-vuart";
> + compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
Please start testing your patches. This for sure fails tests.
It does not look like you tested the DTS against bindings. Please run
'make dtbs_check W=1' (see
Documentation/devicetree/bindings/writing-schema.rst or
https://www.linaro.org/blog/tips-and-tricks-for-validating-devicetree-sources-with-the-devicetree-schema/
for instructions).
Maybe you need to update your dtschema and yamllint. Don't rely on
distro packages for dtschema and be sure you are using the latest
released dtschema.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v3 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop
From: Krzysztof Kozlowski @ 2026-06-24 7:17 UTC (permalink / raw)
To: Grégoire Layet
Cc: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt, andrew, jacky_chou, yh_chung, ninad,
anirudhsriniv, linux-serial, linux-aspeed, linux-arm-kernel,
linux-kernel
In-Reply-To: <73b2bd81ce70814612e6d3cb689c3296de742aaf.1782224059.git.gregoire.layet@9elements.com>
On Tue, Jun 23, 2026 at 02:25:40PM +0000, Grégoire Layet wrote:
> The ASPEED AST2600 has 2 VUART accessible over PCI.
What does that mean? How UART can be accessible over PCI bus?
> This boolean can be set to specify if the VUART is used over PCI.
>
> Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
> ---
> .../devicetree/bindings/serial/8250.yaml | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
> index 3cbd0f532e15..b03797f4674d 100644
> --- a/Documentation/devicetree/bindings/serial/8250.yaml
> +++ b/Documentation/devicetree/bindings/serial/8250.yaml
> @@ -26,6 +26,14 @@ allOf:
> anyOf:
> - const: aspeed,ast2500-vuart
> - const: aspeed,ast2600-vuart
> + - if:
> + anyOf:
> + - required:
> + - aspeed,vuart-over-pci
> + then:
> + properties:
> + compatible:
> + const: aspeed,ast2600-vuart
> - if:
> properties:
> compatible:
> @@ -312,6 +320,13 @@ properties:
> polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
> applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.
>
> + aspeed,vuart-over-pci:
> + type: boolean
> + default: false
There is no such syntax. Please do not introduce own style. Instead,
look at other files how this is done.
> + description: |
Do not need '|' unless you need to preserve formatting.
> + Enable the VUART over the BMC PCI device. Only applicable to
> + aspeed,ast2600-vuart.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v3 1/7] dt-bindings: serial: 8250: aspeed: add compatible string for ast2600
From: Krzysztof Kozlowski @ 2026-06-24 7:15 UTC (permalink / raw)
To: Grégoire Layet
Cc: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt, andrew, jacky_chou, yh_chung, ninad,
anirudhsriniv, linux-serial, linux-aspeed, linux-arm-kernel,
linux-kernel
In-Reply-To: <80d983887dfdfc7e70a6db95f8cb95b7312f3044.1782224059.git.gregoire.layet@9elements.com>
On Tue, Jun 23, 2026 at 02:25:39PM +0000, Grégoire Layet wrote:
> The ast2600 was using the ast2500 vuart compatible string.
> This change makes it possible to have ast2600-specific properties.
>
> Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
Do not attach (thread) your patchsets to some other threads (unrelated
or older versions). This buries them deep in the mailbox and might
interfere with applying entire sets. See also:
https://elixir.bootlin.com/linux/v6.16-rc2/source/Documentation/process/submitting-patches.rst#L830
> ---
> .../devicetree/bindings/serial/8250.yaml | 20 +++++++++++--------
> 1 file changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
> index bb7b9c87a807..3cbd0f532e15 100644
> --- a/Documentation/devicetree/bindings/serial/8250.yaml
> +++ b/Documentation/devicetree/bindings/serial/8250.yaml
> @@ -23,7 +23,9 @@ allOf:
> then:
> properties:
> compatible:
> - const: aspeed,ast2500-vuart
> + anyOf:
This should be oneOf (by convention and actually more accurate meaning).
> + - const: aspeed,ast2500-vuart
> + - const: aspeed,ast2600-vuart
> - if:
> properties:
> compatible:
> @@ -287,17 +289,19 @@ properties:
> aspeed,sirq-polarity-sense:
> $ref: /schemas/types.yaml#/definitions/phandle-array
> description: |
> - Phandle to aspeed,ast2500-scu compatible syscon alongside register
> - offset and bit number to identify how the SIRQ polarity should be
> - configured. One possible data source is the LPC/eSPI mode bit. Only
> - applicable to aspeed,ast2500-vuart.
> + Phandle to aspeed,ast2500-scu or aspeed,ast2600-scu compatible syscon
> + alongside register offset and bit number to identify how the SIRQ
> + polarity should be configured. One possible data source is the LPC/eSPI
> + mode bit. Only applicable to aspeed,ast2500-vuart and
> + aspeed,ast2600-vuart.
> deprecated: true
>
> aspeed,lpc-io-reg:
> $ref: /schemas/types.yaml#/definitions/uint32-array
> maxItems: 1
> description: |
> - The VUART LPC address. Only applicable to aspeed,ast2500-vuart.
> + The VUART LPC address. Only applicable to aspeed,ast2500-vuart and
> + aspeed,ast2600-vuart.
>
> aspeed,lpc-interrupts:
> $ref: /schemas/types.yaml#/definitions/uint32-array
> @@ -305,8 +309,8 @@ properties:
> maxItems: 2
> description: |
> A 2-cell property describing the VUART SIRQ number and SIRQ
> - polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
> - applicable to aspeed,ast2500-vuart.
> + polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
> + applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.
>
More important, where is documenting of the actual compatible?
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH 2/2] clk: aspeed: add AST2700 PECI clock
From: Ryan Chen @ 2026-06-24 5:45 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery
Cc: linux-clk, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, Ryan Chen
In-Reply-To: <20260624-peci_clk-v1-0-ee28b92e22e9@aspeedtech.com>
Register the SoC1 PECI clock as a mux selected by SCU1_CLK_SEL2 bit 16,
choosing between the 25MHz CLKIN and HPLL/4. Add the HPLL/4 fixed factor
clock to serve as the second mux parent.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
drivers/clk/aspeed/clk-ast2700.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/clk/aspeed/clk-ast2700.c b/drivers/clk/aspeed/clk-ast2700.c
index 8b7b382f6f3e..5f499ec0e1d1 100644
--- a/drivers/clk/aspeed/clk-ast2700.c
+++ b/drivers/clk/aspeed/clk-ast2700.c
@@ -273,6 +273,13 @@ static const unsigned int sdclk_parent_ids[] = {
static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)];
+static const unsigned int peciclk_parent_ids[] = {
+ SCU1_CLKIN,
+ SCU1_CLK_HPLL_DIV4
+};
+
+static const struct clk_hw *peciclk_parent_hws[ARRAY_SIZE(peciclk_parent_ids)];
+
#define FIXED_CLK(_id, _name, _rate) \
{ \
.id = _id, \
@@ -458,6 +465,7 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM),
PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM),
PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM),
+ FIXED_FACTOR_CLK(SCU1_CLK_HPLL_DIV4, "soc1-hpll_div4", SCU1_CLK_HPLL, 1, 4),
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2),
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4),
FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10),
@@ -481,6 +489,8 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2),
MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids),
uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2),
+ MUX_CLK(SCU1_CLK_PECI, "peciclk", peciclk_parent_ids, ARRAY_SIZE(peciclk_parent_ids),
+ peciclk_parent_hws, SCU1_CLK_SEL2, 16, 1),
DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX,
SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table),
PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL),
--
2.34.1
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: clock: ast2700: add PECI clock
From: Ryan Chen @ 2026-06-24 5:44 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery
Cc: linux-clk, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, Ryan Chen
In-Reply-To: <20260624-peci_clk-v1-0-ee28b92e22e9@aspeedtech.com>
Add SCU1_CLK_PECI for the SoC1 PECI controller clock source, and
SCU1_CLK_HPLL_DIV4 which serves as one of the PECI clock mux parents.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
include/dt-bindings/clock/aspeed,ast2700-scu.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/dt-bindings/clock/aspeed,ast2700-scu.h b/include/dt-bindings/clock/aspeed,ast2700-scu.h
index bacf712e8e04..138f78ce5f07 100644
--- a/include/dt-bindings/clock/aspeed,ast2700-scu.h
+++ b/include/dt-bindings/clock/aspeed,ast2700-scu.h
@@ -163,5 +163,7 @@
#define SCU1_CLK_GATE_PORTDUSB2CLK 85
#define SCU1_CLK_GATE_LTPI1TXCLK 86
#define SCU1_CLK_I3C 87
+#define SCU1_CLK_HPLL_DIV4 88
+#define SCU1_CLK_PECI 89
#endif
--
2.34.1
^ permalink raw reply related
* [PATCH 0/2] Add AST2700 PECI clock support
From: Ryan Chen @ 2026-06-24 5:44 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery
Cc: linux-clk, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, Ryan Chen
Add the PECI clock for the AST2700 SoC1. The PECI clock is a mux
controlled by SCU1_CLK_SEL2 bit 16, selecting between the 25MHz CLKIN
and HPLL/4.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
Ryan Chen (2):
dt-bindings: clock: ast2700: add PECI clock
clk: aspeed: add AST2700 PECI clock
drivers/clk/aspeed/clk-ast2700.c | 10 ++++++++++
include/dt-bindings/clock/aspeed,ast2700-scu.h | 2 ++
2 files changed, 12 insertions(+)
---
base-commit: 948efecf22e49aa4bf55bb73ec79a0ddcfd38571
change-id: 20260623-peci_clk-ba87e043ee5f
Best regards,
--
Ryan Chen <ryan_chen@aspeedtech.com>
^ permalink raw reply
* RE: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
From: YH Chung @ 2026-06-24 3:59 UTC (permalink / raw)
To: Shulzhenko, Oleksandr, Arnd Bergmann, Andrew Jeffery,
Conor Dooley
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Ryan Chen, Philipp Zabel, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com, Mark Brown
In-Reply-To: <KL1PR0601MB4276452D09689C90B04209C190EF2@KL1PR0601MB4276.apcprd06.prod.outlook.com>
Hi Mark,
> (1) Reuse the existing SPI subsystem and treat eSPI packets as pure signals.
> (2) Maintain the driver under the SoC subsystem, since there is currently no
> eSPI subsystem.
> (3) Create a new eSPI subsystem and rewrite the eSPI driver accordingly.
>
> For option 1, we do not think this would be a good fit, because eSPI has clearly
> defined semantics for each channel, and our hardware exposes different sets of
> registers for each of them.
Regarding option 1, could you kindly share your feedback on whether this
patch set should be modified to fit under the SPI subsystem, or whether a new
eSPI subsystem would be more appropriate?
For option 2, Arnd has indicated that he does not want to take this through
the SoC subsystem. Therefore, if the SPI subsystem is also not a good fit, we
think a new eSPI subsystem may be needed to provide a common home for channel
handling, even though the individual channels are relatively independent.
For example, the VW and OOB channel handling could potentially be integrated
with existing subsystems such as GPIO or net/mctp. However, the Flash channel
would still need an eSPI-specific interface to configure the backing store.
Placing that code under MTD feels awkward, since the driver is not really an
MTD device or a flash controller.
If this direction sounds reasonable, we would like to explore introducing a
new drivers/espi subsystem and moving the eSPI driver there. Please let us
know if you think we should take a different approach.
Thanks,
Yun Hsuan.
^ permalink raw reply
* [PATCH v3 0/7] soc: aspeed: Add BMC and host driver for PCIe BMC device
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1780929570.git.gregoire.layet@9elements.com>
This is a v3 for upstreaming the VUART over PCIe BMC device driver.
The initial driver is from the ASPEED kernel SDK (master-v6.18) [1].
There are two drivers: a BMC-side driver and a host-side driver.
Together they enable host<->BMC VUART communication via PCIe.
The host cannot access the BMC's memory. Only the enabled features are
accessible. These are the KCS4 channel and 2 VUARTs. There is also some
mailbox register functionality also exist for a communication between
the host and the BMC. More information can be found here [2].
This v3 mainly modifies the BMC driver and focuses on VUART.
The BMC driver is now incorporated into the '8250_aspeed_vuart' driver.
A specific flag can be set to indicate that the VUART should be used
over PCI. Several changes have been made to the 8250 device tree binding
and the 'aspeed-g6.dtsi'.
Changes since v2 [3]:
- Add the aspeed,ast2600-vuart compatible entry to the '8250' DT binding
- Add the aspeed,ast2600-vuart compatible property in 'aspeed-g6.dtsi'
- Add the aspeed,vuart-over-pci boolean property to the '8250' DT binding,
only for the aspeed,ast2600-vuart
- Add the aspeed,vuart-over-pci flag to the vuart3 and vuart4
- Add the aspeed,ast2600-vuart compatible property to the
'8250_aspeed_vuart' driver
- Add the VUART over PCI code to the '8250_aspeed_vuart' driver
- The v2 review of the host-side BMC driver has been applied.
The host-side driver is still in /soc/aspeed/, as it is very specific to
this SoC for me. I didn't receive any feedback on where to put this
driver. I can, of course, change this to the relevant location.
It's important to consider that the host driver will do multiple
functions. The AST2600 also supports LPC over PCI, with a specific KCS
channel (KCS4). This driver should also be used to enable the IPMI
automatically via this KCS channel. The UART and the IPMI will depend on
the same PCI resource (BAR1), so this must be configured in one driver.
As with v2, VUART data flow and MSI interrupts have been verified
working on the test hardware.
Tested on:
BMC:
- Asus IPMI Kommando Card R1.01, AST2600 A3.
- OpenBMC
Host:
- Linux kernel v7.0.0
This v3 only supports AST2600; the AST2700 is not supported by this series.
I would like to know whether I should add the 'lpc-io-reg' and
'lpc-interrupt' values to the vuart3 and vuart4 nodes directly in the
'aspeed-g6.dtsi'. The host driver is not capable of finding the vuart
address on his own, so they are hardcoded to 0x3f8 and 0x2f8. It will
not work with other adresses, so perhaps they should be in the .dtsi to
ensure the correct configuration for the 2 vuart over PCI.
For the interrupt number, my test is working with interrupt = 0
for vuart3 and interrupt = 1 for vuart4. I don't fully understand how
the silicon routes MSI numbers to the VUART but the following
combination is working :
| host MSI idx | BMC lpc-interrupts |
VUART3 | 16 | 0 |
VUART4 | 17 | 1 |
The original ASPEED driver used MSI index 15 for the VUART4.
I tested every lpc-interrupts on the BMC from 0 to 15, but none of them
worked with the host MSI index set to 15.
For me, the silicon only routes the MSI index 16 to VUART3 and 17 to
VUART4, and the lpc-interrupt needs to match the 4 least significant bits.
I might be wrong on this explanation but the data path is working with
those numbers. There is no explanation for any of this in the datasheet.
[1]: https://github.com/AspeedTech-BMC/linux/tree/aspeed-master-v6.18/drivers/soc/aspeed
[2]: https://lore.kernel.org/linux-aspeed/CAFi2wKYOAotiezepDqaR5PZDqDaPKKDfAEnpx5EHC0mL39hy6w@mail.gmail.com/
[3]: https://lore.kernel.org/linux-aspeed/cover.1780929570.git.gregoire.layet@9elements.com/
Grégoire Layet (7):
dt-bindings: serial: 8250: aspeed: add compatible string for ast2600
dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop
serial: 8250_aspeed_vuart: add aspeed,ast2600-vuart compatible string
serial: 8250_aspeed_vuart: add VUART over PCI
soc: aspeed: add host-side PCIe BMC device driver
ARM: dts: aspeed: g6: Change vuart compatible string for ast2600
ARM: dts: aspeed: g6: add aspeed,vuart-over-pci prop to vuart3 and 4
.../devicetree/bindings/serial/8250.yaml | 35 +++-
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 10 +-
drivers/soc/aspeed/Kconfig | 8 +
drivers/soc/aspeed/Makefile | 1 +
drivers/soc/aspeed/aspeed-host-bmc-dev.c | 183 ++++++++++++++++++
drivers/tty/serial/8250/8250_aspeed_vuart.c | 87 +++++++++
6 files changed, 312 insertions(+), 12 deletions(-)
create mode 100644 drivers/soc/aspeed/aspeed-host-bmc-dev.c
--
2.54.0
^ permalink raw reply
* [PATCH v3 1/7] dt-bindings: serial: 8250: aspeed: add compatible string for ast2600
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1782224059.git.gregoire.layet@9elements.com>
The ast2600 was using the ast2500 vuart compatible string.
This change makes it possible to have ast2600-specific properties.
Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
---
.../devicetree/bindings/serial/8250.yaml | 20 +++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
index bb7b9c87a807..3cbd0f532e15 100644
--- a/Documentation/devicetree/bindings/serial/8250.yaml
+++ b/Documentation/devicetree/bindings/serial/8250.yaml
@@ -23,7 +23,9 @@ allOf:
then:
properties:
compatible:
- const: aspeed,ast2500-vuart
+ anyOf:
+ - const: aspeed,ast2500-vuart
+ - const: aspeed,ast2600-vuart
- if:
properties:
compatible:
@@ -287,17 +289,19 @@ properties:
aspeed,sirq-polarity-sense:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: |
- Phandle to aspeed,ast2500-scu compatible syscon alongside register
- offset and bit number to identify how the SIRQ polarity should be
- configured. One possible data source is the LPC/eSPI mode bit. Only
- applicable to aspeed,ast2500-vuart.
+ Phandle to aspeed,ast2500-scu or aspeed,ast2600-scu compatible syscon
+ alongside register offset and bit number to identify how the SIRQ
+ polarity should be configured. One possible data source is the LPC/eSPI
+ mode bit. Only applicable to aspeed,ast2500-vuart and
+ aspeed,ast2600-vuart.
deprecated: true
aspeed,lpc-io-reg:
$ref: /schemas/types.yaml#/definitions/uint32-array
maxItems: 1
description: |
- The VUART LPC address. Only applicable to aspeed,ast2500-vuart.
+ The VUART LPC address. Only applicable to aspeed,ast2500-vuart and
+ aspeed,ast2600-vuart.
aspeed,lpc-interrupts:
$ref: /schemas/types.yaml#/definitions/uint32-array
@@ -305,8 +309,8 @@ properties:
maxItems: 2
description: |
A 2-cell property describing the VUART SIRQ number and SIRQ
- polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
- applicable to aspeed,ast2500-vuart.
+ polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
+ applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.
required:
- reg
--
2.54.0
^ permalink raw reply related
* [PATCH v3 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1782224059.git.gregoire.layet@9elements.com>
The ASPEED AST2600 has 2 VUART accessible over PCI.
This boolean can be set to specify if the VUART is used over PCI.
Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
---
.../devicetree/bindings/serial/8250.yaml | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
index 3cbd0f532e15..b03797f4674d 100644
--- a/Documentation/devicetree/bindings/serial/8250.yaml
+++ b/Documentation/devicetree/bindings/serial/8250.yaml
@@ -26,6 +26,14 @@ allOf:
anyOf:
- const: aspeed,ast2500-vuart
- const: aspeed,ast2600-vuart
+ - if:
+ anyOf:
+ - required:
+ - aspeed,vuart-over-pci
+ then:
+ properties:
+ compatible:
+ const: aspeed,ast2600-vuart
- if:
properties:
compatible:
@@ -312,6 +320,13 @@ properties:
polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.
+ aspeed,vuart-over-pci:
+ type: boolean
+ default: false
+ description: |
+ Enable the VUART over the BMC PCI device. Only applicable to
+ aspeed,ast2600-vuart.
+
required:
- reg
- interrupts
--
2.54.0
^ permalink raw reply related
* [PATCH v3 3/7] serial: 8250_aspeed_vuart: add aspeed,ast2600-vuart compatible string
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1782224059.git.gregoire.layet@9elements.com>
Makes the driver compatible with the ast2600-vuart.
This enables specific configuration for the AST2600.
Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
---
drivers/tty/serial/8250/8250_aspeed_vuart.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index 26fc0464f1cc..6afa2f4057e1 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -560,6 +560,7 @@ static void aspeed_vuart_remove(struct platform_device *pdev)
static const struct of_device_id aspeed_vuart_table[] = {
{ .compatible = "aspeed,ast2400-vuart" },
{ .compatible = "aspeed,ast2500-vuart" },
+ { .compatible = "aspeed,ast2600-vuart" },
{ },
};
MODULE_DEVICE_TABLE(of, aspeed_vuart_table);
--
2.54.0
^ permalink raw reply related
* [PATCH v3 4/7] serial: 8250_aspeed_vuart: add VUART over PCI
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1782224059.git.gregoire.layet@9elements.com>
This patch enables the VUART over PCI possible for the AST2600. This is
only activated if the 'aspeed,vuart-over-pci' property flag is set on an
'ast2600-vuart' compatible node.
The AST2600 has 2 VUART that are usable over PCI. These are the VUART3
and VUART4 in the 'apseed-g6.dtsi'.
This code sets the BMC PCI device enables
bits, sets the PCI class code to MFD device and configures MSI interrupts.
There is no disable function. Removing this driver should not disable
the BMC PCI device, as other drivers could use it.
However, if all the drivers using it are removed, the
BMC PCI device will still be activated, which is not ideal. Realistically though, this is not a
use case for a BMC, the drivers will never be removed.
This is useful on PCIe BMC expansion cards that use the AST2600, such as the
ASUS Kommando IPMI Expansion Card.
Registers initialisation taken from ASPEED 6.18 Kernel SDK.
Return code checks were added to each register write.
The code has been simplified and macros have been added.
The ASPEED_SCUC24 regmap update is missing a macro for 'BIT(14)'. I was
unable to determine the purpose of this bit. In the AST2600 A3
datasheet it is marked as 'reserved'. It is only used on the other
revision. As I only have the AST2600A3, I was unable to try this code
path.
Signed-off-by: Jacky Chou <jacky_chou@aspeedtech.com>
Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
Tested-by: Grégoire Layet <gregoire.layet@9elements.com>
---
drivers/tty/serial/8250/8250_aspeed_vuart.c | 86 +++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index 6afa2f4057e1..e204e26fa173 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -32,6 +32,27 @@
#define ASPEED_VUART_DEFAULT_SIRQ 4
#define ASPEED_VUART_DEFAULT_SIRQ_POLARITY IRQ_TYPE_LEVEL_LOW
+#define ASPEED_SCU_SILICON_REVISION_ID 0x04
+#define AST2600A3_REVISION_ID 0x05030303
+
+#define ASPEED_SCUC24 0xC24
+#define ASPEED_SCUC24_MSI_ROUTING_MASK GENMASK(11, 10)
+#define ASPEED_SCUC24_MSI_ROUTING_PCIe2LPC_PCIDEV1 (0x2 << 10)
+#define ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN BIT(18)
+#define ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN BIT(17)
+
+
+#define ASPEED_SCU_PCIE_CONF_CTRL 0xC20
+#define SCU_PCIE_CONF_BMC_DEV_EN BIT(8)
+#define SCU_PCIE_CONF_BMC_DEV_EN_MMIO BIT(9)
+#define SCU_PCIE_CONF_BMC_DEV_EN_MSI BIT(11)
+#define SCU_PCIE_CONF_BMC_DEV_EN_IRQ BIT(13)
+#define SCU_PCIE_CONF_BMC_DEV_EN_PCIE_BUS_MASTER BIT(14)
+#define SCU_PCIE_CONF_BMC_DEV_EN_E2L BIT(15)
+#define SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE BIT(21)
+
+#define ASPEED_SCU_BMC_DEV_CLASS 0xC68
+
struct aspeed_vuart {
struct device *dev;
int line;
@@ -412,6 +433,62 @@ static int aspeed_vuart_map_irq_polarity(u32 dt)
}
}
+static int aspeed_ast2600_vuart_over_pci_set_enabled(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ u32 silicon_revision_id;
+ struct regmap *scu;
+ int rc;
+
+ u32 pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_IRQ |
+ SCU_PCIE_CONF_BMC_DEV_EN_MMIO |
+ SCU_PCIE_CONF_BMC_DEV_EN_MSI |
+ SCU_PCIE_CONF_BMC_DEV_EN_PCIE_BUS_MASTER |
+ SCU_PCIE_CONF_BMC_DEV_EN_E2L |
+ SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE |
+ SCU_PCIE_CONF_BMC_DEV_EN;
+
+ scu = syscon_regmap_lookup_by_phandle(dev->of_node, "clocks");
+ if (IS_ERR(scu)) {
+ dev_err(&pdev->dev, "failed to find SCU regmap\n");
+ return PTR_ERR(scu);
+ }
+
+ /* update class code to be an MFD device */
+ if (regmap_write(scu, ASPEED_SCU_BMC_DEV_CLASS, 0xff000000)) {
+ dev_err(dev, "could not set PCI class code\n");
+ return -EIO;
+ }
+
+ if (regmap_update_bits(scu, ASPEED_SCU_PCIE_CONF_CTRL,
+ pcie_config_ctl, pcie_config_ctl)) {
+ dev_err(dev, "could not set PCIe configuration\n");
+ return -EIO;
+ }
+
+ if (regmap_read(scu, ASPEED_SCU_SILICON_REVISION_ID, &silicon_revision_id)) {
+ dev_err(dev, "could not read silicon revision\n");
+ return -EIO;
+ }
+
+ if (silicon_revision_id == AST2600A3_REVISION_ID)
+ rc = regmap_update_bits(scu, ASPEED_SCUC24,
+ ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_MASK,
+ ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_PCIe2LPC_PCIDEV1);
+ else
+ rc = regmap_update_bits(scu, ASPEED_SCUC24,
+ /* The bit 14 is reserved in the Datasheet, so we can't say what it does. This revision has not been tested */
+ ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_MASK,
+ ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_PCIe2LPC_PCIDEV1);
+ if (rc) {
+ dev_err(dev, "could not set PCI device 1 MSI interrupt routing\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+
static int aspeed_vuart_probe(struct platform_device *pdev)
{
struct of_phandle_args sirq_polarity_sense_args;
@@ -540,6 +617,15 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
aspeed_vuart_set_host_tx_discard(vuart, true);
platform_set_drvdata(pdev, vuart);
+ if (of_device_is_compatible(dev->of_node, "aspeed,ast2600-vuart") &&
+ of_property_read_bool(dev->of_node, "aspeed,vuart-over-pci")) {
+ rc = aspeed_ast2600_vuart_over_pci_set_enabled(pdev);
+ if (rc) {
+ dev_err(dev, "could not enable VUART over PCI\n");
+ return rc;
+ }
+ }
+
return 0;
err_sysfs_remove:
--
2.54.0
^ permalink raw reply related
* [PATCH v3 5/7] soc: aspeed: add host-side PCIe BMC device driver
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1782224059.git.gregoire.layet@9elements.com>
Add support for VUART over PCIe between BMC and host.
This add host side driver.
This only support the AST2600.
Taken from ASPEED 6.18 Kernel SDK and trimmed down.
The host can't detect the VUART adresses, they are forced
at 0x3f8 and 0x2f8, similar from the initial ASPEED driver.
The MSI vector index has been changed for the VUART2 from 15 to 17.
The index 15 used in the initial driver was not working.
Data path in both direction is tested on both VUART.
Signed-off-by: Jacky Chou <jacky_chou@aspeedtech.com>
Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
Tested-by: Grégoire Layet <gregoire.layet@9elements.com>
---
drivers/soc/aspeed/Kconfig | 8 +
drivers/soc/aspeed/Makefile | 1 +
drivers/soc/aspeed/aspeed-host-bmc-dev.c | 183 +++++++++++++++++++++++
3 files changed, 192 insertions(+)
create mode 100644 drivers/soc/aspeed/aspeed-host-bmc-dev.c
diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
index 63a656449a1a..ebd023b10701 100644
--- a/drivers/soc/aspeed/Kconfig
+++ b/drivers/soc/aspeed/Kconfig
@@ -4,6 +4,14 @@ if ARCH_ASPEED || COMPILE_TEST
menu "ASPEED SoC drivers"
+config ASPEED_HOST_BMC_DEV
+ tristate "ASPEED Host BMC Device"
+ depends on PCI
+ depends on SERIAL_8250
+ help
+ Enable support for the ASPEED AST2600 BMC Device on the Host.
+ This configure the PCIe and setup two 8250 compatible VUART ports.
+
config ASPEED_LPC_CTRL
tristate "ASPEED LPC firmware cycle control"
select REGMAP
diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
index b35d74592964..c515e163eab7 100644
--- a/drivers/soc/aspeed/Makefile
+++ b/drivers/soc/aspeed/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ASPEED_HOST_BMC_DEV) += aspeed-host-bmc-dev.o
obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o
diff --git a/drivers/soc/aspeed/aspeed-host-bmc-dev.c b/drivers/soc/aspeed/aspeed-host-bmc-dev.c
new file mode 100644
index 000000000000..3160b6aedb5b
--- /dev/null
+++ b/drivers/soc/aspeed/aspeed-host-bmc-dev.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright (C) ASPEED Technology Inc.
+
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#define BMC_MULTI_MSI 32
+#define PCI_BMC_DEVICE_ID 0x2402
+
+#define DRIVER_NAME "aspeed-host-bmc-dev"
+
+enum aspeed_platform_id {
+ ASPEED,
+};
+
+static int vuart_msi_index[2] = { 16, 17 };
+static int vuart_port_addr[2] = {0x3f8, 0x2f8};
+
+struct aspeed_pci_bmc_dev {
+ struct device *dev;
+ kernel_ulong_t driver_data;
+ int id;
+
+ unsigned long message_bar_base;
+
+ struct uart_8250_port uart[2];
+ int uart_line[2];
+
+ int *msi_idx_table;
+};
+
+static void aspeed_pci_setup_irq_resource(struct pci_dev *pdev)
+{
+ struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
+
+ pci_bmc_dev->msi_idx_table = vuart_msi_index;
+
+ if (pci_alloc_irq_vectors(pdev, 1, BMC_MULTI_MSI, PCI_IRQ_INTX | PCI_IRQ_MSI) <= 1)
+ /* If pci_alloc fail, set all msi index to the first vector */
+ memset(pci_bmc_dev->msi_idx_table, 0, sizeof(vuart_msi_index));
+}
+
+static int aspeed_pci_bmc_device_setup_vuart(struct pci_dev *pdev, int idx)
+{
+ struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ struct uart_8250_port *uart = &pci_bmc_dev->uart[idx];
+ u16 vuart_ioport;
+ int ret;
+
+ /* Assign the line to non-exist device before everything is setup */
+ pci_bmc_dev->uart_line[idx] = -ENOENT;
+
+ vuart_ioport = vuart_port_addr[idx];
+ /* ASPEED BMC device shift adresses by 2 to the left */
+ vuart_ioport = vuart_ioport << 2;
+
+ uart->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ uart->port.uartclk = 115200 * 16;
+ uart->port.irq = pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[idx]);
+ uart->port.dev = dev;
+ uart->port.iotype = UPIO_MEM32;
+ uart->port.iobase = 0;
+ uart->port.mapbase = pci_bmc_dev->message_bar_base + vuart_ioport;
+ uart->port.membase = 0;
+ uart->port.type = PORT_16550A;
+ uart->port.flags |= (UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+ uart->port.regshift = 2;
+
+ ret = serial8250_register_8250_port(&pci_bmc_dev->uart[idx]);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "Can't setup PCIe VUART%d\n", idx);
+ return ret;
+ }
+
+ pci_bmc_dev->uart_line[idx] = ret;
+
+ return 0;
+}
+
+static void aspeed_pci_host_bmc_device_release_vuart(struct pci_dev *pdev, int idx)
+{
+ struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
+
+ if (pci_bmc_dev->uart_line[idx] >= 0)
+ serial8250_unregister_port(pci_bmc_dev->uart_line[idx]);
+}
+
+static int aspeed_pci_host_setup(struct pci_dev *pdev)
+{
+ struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
+ int rc = 0;
+
+ pci_bmc_dev->message_bar_base = pci_resource_start(pdev, 1);
+
+ if (pdev->revision == 0x27) {
+ pr_err("AST2700 detected but not supported");
+ return -ENODEV;
+ }
+
+ rc = aspeed_pci_bmc_device_setup_vuart(pdev, 0);
+ if (rc)
+ return rc;
+
+ rc = aspeed_pci_bmc_device_setup_vuart(pdev, 1);
+ if (rc)
+ goto out_freeVUART1;
+
+ return 0;
+
+out_freeVUART1:
+ aspeed_pci_host_bmc_device_release_vuart(pdev, 0);
+
+ return rc;
+}
+
+static int aspeed_pci_host_bmc_device_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct aspeed_pci_bmc_dev *pci_bmc_dev;
+ int rc = 0;
+
+ pci_bmc_dev = devm_kzalloc(&pdev->dev, sizeof(*pci_bmc_dev), GFP_KERNEL);
+ if (!pci_bmc_dev)
+ return -ENOMEM;
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ dev_err(&pdev->dev, "pci_enable_device() returned error %d\n", rc);
+ return rc;
+ }
+
+ pci_set_master(pdev);
+ pci_set_drvdata(pdev, pci_bmc_dev);
+
+ aspeed_pci_setup_irq_resource(pdev);
+
+ /* Setup BMC PCI device */
+ rc = aspeed_pci_host_setup(pdev);
+ if (rc) {
+ dev_err(&pdev->dev, "ASPEED PCIe Host device returned error %d\n", rc);
+ pci_free_irq_vectors(pdev);
+ pci_disable_device(pdev);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void aspeed_pci_host_bmc_device_remove(struct pci_dev *pdev)
+{
+ aspeed_pci_host_bmc_device_release_vuart(pdev, 0);
+ aspeed_pci_host_bmc_device_release_vuart(pdev, 1);
+
+ pci_free_irq_vectors(pdev);
+ pci_disable_device(pdev);
+}
+
+static struct pci_device_id aspeed_host_bmc_dev_pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ASPEED, PCI_BMC_DEVICE_ID), .class = 0xFF0000, .class_mask = 0xFFFF00,
+ .driver_data = ASPEED },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, aspeed_host_bmc_dev_pci_ids);
+
+static struct pci_driver aspeed_host_bmc_dev_driver = {
+ .name = DRIVER_NAME,
+ .id_table = aspeed_host_bmc_dev_pci_ids,
+ .probe = aspeed_pci_host_bmc_device_probe,
+ .remove = aspeed_pci_host_bmc_device_remove,
+};
+
+module_driver(aspeed_host_bmc_dev_driver, pci_register_driver, pci_unregister_driver);
+
+MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
+MODULE_DESCRIPTION("ASPEED Host BMC DEVICE Driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH v3 6/7] ARM: dts: aspeed: g6: Change vuart compatible string for ast2600
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1782224059.git.gregoire.layet@9elements.com>
Use the ast2600 compatible string.
This makes it more precise and enables specific ast2600 properties.
Still use the ast2500 compatible string as a fallback.
Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
---
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 56bb3b0444f7..7c02633f2bd6 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -707,7 +707,7 @@ emmc: sdhci@1e750100 {
};
vuart1: serial@1e787000 {
- compatible = "aspeed,ast2500-vuart";
+ compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
reg = <0x1e787000 0x40>;
reg-shift = <2>;
interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
@@ -717,7 +717,7 @@ vuart1: serial@1e787000 {
};
vuart3: serial@1e787800 {
- compatible = "aspeed,ast2500-vuart";
+ compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
reg = <0x1e787800 0x40>;
reg-shift = <2>;
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
@@ -727,7 +727,7 @@ vuart3: serial@1e787800 {
};
vuart2: serial@1e788000 {
- compatible = "aspeed,ast2500-vuart";
+ compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
reg = <0x1e788000 0x40>;
reg-shift = <2>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
@@ -737,7 +737,7 @@ vuart2: serial@1e788000 {
};
vuart4: serial@1e788800 {
- compatible = "aspeed,ast2500-vuart";
+ compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
reg = <0x1e788800 0x40>;
reg-shift = <2>;
interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
--
2.54.0
^ permalink raw reply related
* [PATCH v3 7/7] ARM: dts: aspeed: g6: add aspeed,vuart-over-pci prop to vuart3 and 4
From: Grégoire Layet @ 2026-06-23 14:25 UTC (permalink / raw)
To: joel, andrew, lkundrak, devicetree, gregkh, jirislaby, robh,
krzk+dt, conor+dt
Cc: andrew, jacky_chou, yh_chung, ninad, anirudhsriniv, linux-serial,
linux-aspeed, linux-arm-kernel, linux-kernel, Grégoire Layet
In-Reply-To: <cover.1782224059.git.gregoire.layet@9elements.com>
The VUART 3 and 4 are VUART over PCI.
This flag indicates this information.
Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
---
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 7c02633f2bd6..2a19463b4c21 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -723,6 +723,7 @@ vuart3: serial@1e787800 {
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&syscon ASPEED_CLK_APB2>;
no-loopback-test;
+ aspeed,vuart-over-pci;
status = "disabled";
};
@@ -743,6 +744,7 @@ vuart4: serial@1e788800 {
interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&syscon ASPEED_CLK_APB2>;
no-loopback-test;
+ aspeed,vuart-over-pci;
status = "disabled";
};
--
2.54.0
^ permalink raw reply related
* [PATCH v33 5/5] i2c: ast2600: Add target mode support
From: Ryan Chen @ 2026-06-23 1:15 UTC (permalink / raw)
To: jk, andriy.shevchenko, Andi Shyti, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
Benjamin Herrenschmidt, Rayn Chen, Philipp Zabel
Cc: linux-i2c, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, openbmc, Ryan Chen
In-Reply-To: <20260623-upstream_i2c-v33-0-6d5338fc56ed@aspeedtech.com>
Add target mode support to the AST2600 I2C driver.
Target mode features implemented include:
- Add target interrupt handling
- Address match and response logic
This complements the existing controller-mode support, enabling
dual-role capability.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
Changes in v32:
- Fix target RX data loss in the master-abort fast path: remove the
BUFF_CTRL zeroing that preceded the controller IER clear. The shared
BUFF_CTRL register holds the pending target RX length in bits [29:24];
zeroing it before the switch statement causes target_rx_len to read
back as 0, silently discarding all bytes already received by the
target.
- Fix use-after-free in master-abort fast path: null msgs and re-enable
the controller IER before calling complete(), not after. Calling
complete() first allows process context to immediately start a new
i2c_transfer() and install a new msgs pointer; a stale controller IRQ
firing during the subsequent IER restore would then dereference the
new transfer's msgs buffer.
- Fix shared-buffer corruption on coalesced STOP+SLAVE_MATCH IRQ:
restore the SLAVE_PENDING guard on the target_active = false
transition. SLAVE_PENDING (bit 29) is set precisely when a new
address-match is already queued while the previous DMA receive has
not yet been processed. Clearing target_active unconditionally on
STOP in that case lets the controller side overwrite the shared Tx/Rx
buffer before the new target transaction has been re-armed.
- Use READ_ONCE() for all process-context reads of target_active.
The IRQ path writes target_active with WRITE_ONCE(); plain loads in
process context allow the compiler to cache the value across the
IER-disable window, potentially seeing a stale false and starting a
controller transfer that races with an active target transaction.
Changes in v31:
- Address Sashiko AI code review feedback on the target patch:
- Clear target_active on any STOP. The previous condition
`(sts & STOP) && !(sts & SLAVE_PENDING)` failed under coalesced
STOP+SLAVE_PENDING IRQs and left target_active stuck true,
deadlocking controller_xfer() with -EBUSY forever.
- Enable the target IER inside reg_target() instead of
unconditionally in probe(). unreg_target() disables it; without
matching re-enable in reg_target() a subsequent re-registration
would never receive IRQs. Also avoids spurious IRQ activity when
no slave is registered.
- Add the missing CMD_STS write in the
SLAVE_PENDING|RX_DONE|WAIT_TX_DMA|STOP target ISR case so the
HW state machine is re-armed (TRIGGER | TX_BUFF_EN); otherwise
the controller stretches SCL until INACTIVE_TO recovers.
- Default target ISR case now writes TARGET_TRIGGER_CMD to re-arm
the HW state machine instead of silently breaking, which
previously left the bus hung on unhandled sts combinations.
- W1C-clear the ADDR1/2/3_NAK bits in HW (not just locally) in
ast2600_i2c_target_irq(); stale ADDR_NAK bits made
controller_xfer() see I2CS_ISR != 0 and bounce every transfer
with -EBUSY.
- unreg_target(): replace masked ADDR_CTRL write with writel(0, ...);
AST2600_I2CS_ADDR1_MASK covers only bits[6:0] (the 7-bit address),
leaving ADDR1_ENABLE (BIT(7)) set after unregister. Although SLAVE_EN
is cleared first, writing 0 is the correct and complete teardown.
Changes in v30:
- Address Sashiko AI code review feedback:
- Force-stop path (target IRQ aborting an in-flight controller
transfer): disable the controller IER and W1C-clear pending ISR
before calling complete(), then restore the IER after the wake-up.
Without the disable/clear sequence the controller IRQ handler can
race with the target abort path and double-complete or touch
freed msgs.
- unreg_target() teardown ordering: disable the target IER first,
then disable SLAVE_EN / clear ADDR_CTRL, synchronize_irq(), W1C
pending ISR, and only then NULL i2c_bus->target and clear
target_active. The old order left IER enabled while target was
being cleared, allowing an in-flight handler to dereference a
target pointer the caller had already freed.
- reg_target() bring-up ordering: assign i2c_bus->target before
enabling SLAVE_EN. Otherwise an IRQ that fires after SLAVE_EN is
set but before the pointer is stored finds target == NULL, exits
without clearing the ISR, and the unmasked event re-fires as an
IRQ storm.
- Use writel() instead of writeb() when staging a TX byte into the
target buffer. The AST2600 buffer SRAM only supports 32-bit
accesses; byte writes are silently dropped (or, on some
revisions, raise a bus fault), so a SLAVE_READ_REQUESTED reply
never reaches the master.
- reg_target() rejects 10-bit client addresses with -EAFNOSUPPORT.
AST2600_I2CS_ADDR1 is only a 7-bit field; without the check, the
high bits of a 10-bit address overflow into the adjacent ADDR2
field and silently corrupt a second target slot.
- Initialise the local `u8 value` to 0 in the target packet IRQ
handler. Its address is passed to i2c_slave_event() for events
such as I2C_SLAVE_STOP / I2C_SLAVE_READ_REQUESTED; a slave
backend that reads the byte before writing would otherwise leak
uninitialised kernel stack.
Changes in v29:
- fix race between unreg_target and IRQ handler.
- move i2cs ier enable from ast2600_i2c_init to probe after master ier enable.
- remove dma/byte transfer, use buffer mode only.
Changes in v28:
- fix typo condication -> condition
- fix compile error, when disable CONFIG_I2C_SLAVE
Changes in v26:
- change int to bool target_operate
- rename target_operate to target_active
- use i2c_bus->target replace require IO
- use WRITE_ONCE replace target_operate write.
---
drivers/i2c/busses/i2c-ast2600.c | 359 +++++++++++++++++++++++++++++++++++++++
1 file changed, 359 insertions(+)
diff --git a/drivers/i2c/busses/i2c-ast2600.c b/drivers/i2c/busses/i2c-ast2600.c
index 5cb2d91b78e0..af950a4c4d6d 100644
--- a/drivers/i2c/busses/i2c-ast2600.c
+++ b/drivers/i2c/busses/i2c-ast2600.c
@@ -255,6 +255,11 @@ struct ast2600_i2c_bus {
bool multi_master;
bool stop_pending;
void __iomem *buf_base;
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ /* target structure */
+ bool target_active;
+ struct i2c_client *target;
+#endif
};
static void ast2600_i2c_ac_timing_config(struct ast2600_i2c_bus *i2c_bus)
@@ -348,6 +353,253 @@ static int ast2600_i2c_recover_bus(struct ast2600_i2c_bus *i2c_bus)
return ret;
}
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static void ast2600_i2c_target_packet_buff_irq(struct ast2600_i2c_bus *i2c_bus, u32 sts)
+{
+ u8 value = 0;
+ int target_rx_len = 0;
+ u32 cmd = 0;
+ int i;
+
+ /* due to controller target is common buffer, need force the master stop not issue */
+ if (readl(i2c_bus->reg_base + AST2600_I2CM_CMD_STS) & GENMASK(15, 0)) {
+ writel(0, i2c_bus->reg_base + AST2600_I2CM_CMD_STS);
+ writel(0, i2c_bus->reg_base + AST2600_I2CM_IER);
+ writel(readl(i2c_bus->reg_base + AST2600_I2CM_ISR),
+ i2c_bus->reg_base + AST2600_I2CM_ISR);
+ i2c_bus->cmd_err = -EBUSY;
+ WRITE_ONCE(i2c_bus->msgs, NULL);
+ writel(AST2600_I2CM_PKT_DONE | AST2600_I2CM_BUS_RECOVER,
+ i2c_bus->reg_base + AST2600_I2CM_IER);
+ complete(&i2c_bus->cmd_complete);
+ }
+
+ /* Handle i2c target timeout condition */
+ if (sts & AST2600_I2CS_INACTIVE_TO) {
+ /* Reset timeout counter */
+ u32 ac_timing = readl(i2c_bus->reg_base + AST2600_I2CC_AC_TIMING) &
+ AST2600_I2CC_AC_TIMING_MASK;
+
+ writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
+ ac_timing |= AST2600_I2CC_TTIMEOUT(i2c_bus->timeout);
+ writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
+ writel(TARGET_TRIGGER_CMD, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
+ writel(AST2600_I2CS_PKT_DONE, i2c_bus->reg_base + AST2600_I2CS_ISR);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ WRITE_ONCE(i2c_bus->target_active, false);
+ return;
+ }
+
+ sts &= ~(AST2600_I2CS_PKT_DONE | AST2600_I2CS_PKT_ERROR);
+
+ if (sts & AST2600_I2CS_SLAVE_MATCH)
+ WRITE_ONCE(i2c_bus->target_active, true);
+
+ switch (sts) {
+ case AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_WAIT_RX_DMA |
+ AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
+ case AST2600_I2CS_SLAVE_PENDING |
+ AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
+ case AST2600_I2CS_SLAVE_PENDING |
+ AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_STOP:
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ fallthrough;
+ case AST2600_I2CS_SLAVE_PENDING |
+ AST2600_I2CS_WAIT_RX_DMA | AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE:
+ case AST2600_I2CS_WAIT_RX_DMA | AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE:
+ case AST2600_I2CS_WAIT_RX_DMA | AST2600_I2CS_SLAVE_MATCH:
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_REQUESTED, &value);
+ cmd = TARGET_TRIGGER_CMD;
+ if (sts & AST2600_I2CS_RX_DONE) {
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ }
+ if (readl(i2c_bus->reg_base + AST2600_I2CS_CMD_STS) & AST2600_I2CS_RX_BUFF_EN)
+ cmd = 0;
+ else
+ cmd = TARGET_TRIGGER_CMD | AST2600_I2CS_RX_BUFF_EN;
+
+ writel(AST2600_I2CC_SET_RX_BUF_LEN(i2c_bus->buf_size),
+ i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ break;
+ case AST2600_I2CS_WAIT_RX_DMA | AST2600_I2CS_RX_DONE:
+ cmd = TARGET_TRIGGER_CMD;
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ cmd |= AST2600_I2CS_RX_BUFF_EN;
+ writel(AST2600_I2CC_SET_RX_BUF_LEN(i2c_bus->buf_size),
+ i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ break;
+ case AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_WAIT_RX_DMA |
+ AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
+ cmd = TARGET_TRIGGER_CMD;
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ cmd |= AST2600_I2CS_RX_BUFF_EN;
+ writel(AST2600_I2CC_SET_RX_BUF_LEN(i2c_bus->buf_size),
+ i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ break;
+ case AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
+ cmd = TARGET_TRIGGER_CMD;
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ /* workaround for avoid next start with len != 0 */
+ writel(BIT(0), i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ break;
+ case AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
+ cmd = TARGET_TRIGGER_CMD;
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ /* workaround for avoid next start with len != 0 */
+ writel(BIT(0), i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ break;
+ case AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_RX_DONE |
+ AST2600_I2CS_WAIT_TX_DMA | AST2600_I2CS_STOP:
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_READ_REQUESTED, &value);
+ writel(value, i2c_bus->buf_base);
+ writel(AST2600_I2CC_SET_TX_BUF_LEN(1),
+ i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ cmd = TARGET_TRIGGER_CMD | AST2600_I2CS_TX_BUFF_EN;
+ break;
+ case AST2600_I2CS_WAIT_TX_DMA | AST2600_I2CS_SLAVE_MATCH:
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_READ_REQUESTED, &value);
+ writel(value, i2c_bus->buf_base);
+ writel(AST2600_I2CC_SET_TX_BUF_LEN(1),
+ i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ cmd = TARGET_TRIGGER_CMD | AST2600_I2CS_TX_BUFF_EN;
+ break;
+ case AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_STOP |
+ AST2600_I2CS_TX_NAK | AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE:
+ case AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_WAIT_RX_DMA | AST2600_I2CS_STOP |
+ AST2600_I2CS_TX_NAK | AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE:
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_REQUESTED, &value);
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ writel(AST2600_I2CC_SET_RX_BUF_LEN(i2c_bus->buf_size),
+ i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ cmd = TARGET_TRIGGER_CMD | AST2600_I2CS_RX_BUFF_EN;
+ break;
+ case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_WAIT_TX_DMA | AST2600_I2CS_RX_DONE:
+ case AST2600_I2CS_WAIT_TX_DMA | AST2600_I2CS_RX_DONE:
+ case AST2600_I2CS_WAIT_TX_DMA:
+ if (sts & AST2600_I2CS_SLAVE_MATCH)
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_REQUESTED, &value);
+
+ if (sts & AST2600_I2CS_RX_DONE) {
+ target_rx_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
+ AST2600_I2CC_BUFF_CTRL));
+ for (i = 0; i < target_rx_len; i++) {
+ value = readb(i2c_bus->buf_base + i2c_bus->buf_size + i);
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_RECEIVED, &value);
+ }
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_READ_REQUESTED, &value);
+ } else {
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_READ_PROCESSED, &value);
+ }
+ writel(value, i2c_bus->buf_base);
+ writel(AST2600_I2CC_SET_TX_BUF_LEN(1),
+ i2c_bus->reg_base + AST2600_I2CC_BUFF_CTRL);
+ cmd = TARGET_TRIGGER_CMD | AST2600_I2CS_TX_BUFF_EN;
+ break;
+ /* workaround : trigger the cmd twice to fix next state keep 1000000 */
+ case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE:
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_WRITE_REQUESTED, &value);
+ cmd = TARGET_TRIGGER_CMD | AST2600_I2CS_RX_BUFF_EN;
+ writel(cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
+ break;
+ case AST2600_I2CS_TX_NAK | AST2600_I2CS_STOP:
+ case AST2600_I2CS_STOP:
+ cmd = TARGET_TRIGGER_CMD;
+ i2c_slave_event(i2c_bus->target, I2C_SLAVE_STOP, &value);
+ break;
+ default:
+ dev_dbg(i2c_bus->dev, "unhandled target isr case %x, sts %x\n", sts,
+ readl(i2c_bus->reg_base + AST2600_I2CC_STS_AND_BUFF));
+ cmd = TARGET_TRIGGER_CMD;
+ break;
+ }
+
+ if (cmd)
+ writel(cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
+
+ writel(AST2600_I2CS_PKT_DONE, i2c_bus->reg_base + AST2600_I2CS_ISR);
+ readl(i2c_bus->reg_base + AST2600_I2CS_ISR);
+
+ if ((sts & AST2600_I2CS_STOP) && !(sts & AST2600_I2CS_SLAVE_PENDING))
+ WRITE_ONCE(i2c_bus->target_active, false);
+}
+
+static int ast2600_i2c_target_irq(struct ast2600_i2c_bus *i2c_bus)
+{
+ u32 ier = readl(i2c_bus->reg_base + AST2600_I2CS_IER);
+ u32 isr = readl(i2c_bus->reg_base + AST2600_I2CS_ISR);
+
+ if (!(isr & ier))
+ return 0;
+
+ /*
+ * Target interrupt coming after controller packet done
+ * So need handle controller first.
+ */
+ if (readl(i2c_bus->reg_base + AST2600_I2CM_ISR) & AST2600_I2CM_PKT_DONE)
+ return 0;
+
+ isr &= ~(AST2600_I2CS_ADDR_INDICATE_MASK);
+
+ if (isr & (AST2600_I2CS_ADDR1_NAK | AST2600_I2CS_ADDR2_NAK |
+ AST2600_I2CS_ADDR3_NAK)) {
+ writel(isr & (AST2600_I2CS_ADDR1_NAK | AST2600_I2CS_ADDR2_NAK |
+ AST2600_I2CS_ADDR3_NAK),
+ i2c_bus->reg_base + AST2600_I2CS_ISR);
+ isr &= ~(AST2600_I2CS_ADDR1_NAK | AST2600_I2CS_ADDR2_NAK |
+ AST2600_I2CS_ADDR3_NAK);
+ }
+
+ if (AST2600_I2CS_ADDR_MASK & isr)
+ isr &= ~AST2600_I2CS_ADDR_MASK;
+
+ if (AST2600_I2CS_PKT_DONE & isr)
+ ast2600_i2c_target_packet_buff_irq(i2c_bus, isr);
+
+ return 1;
+}
+#endif
+
static int ast2600_i2c_setup_buff_tx(u32 cmd, struct ast2600_i2c_bus *i2c_bus)
{
struct i2c_msg *msg = &i2c_bus->msgs[i2c_bus->msgs_index];
@@ -561,6 +813,20 @@ static void ast2600_i2c_controller_packet_irq(struct ast2600_i2c_bus *i2c_bus, u
}
break;
case AST2600_I2CM_RX_DONE:
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ /*
+ * Workaround for controller/target packet mode enable rx done stuck issue
+ * When controller go for first read (RX_DONE), target mode will also effect
+ * Then controller will send nack, not operate anymore.
+ */
+ if (readl(i2c_bus->reg_base + AST2600_I2CS_CMD_STS) & AST2600_I2CS_PKT_MODE_EN) {
+ u32 target_cmd = readl(i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
+
+ writel(0, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
+ writel(target_cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
+ }
+ fallthrough;
+#endif
case AST2600_I2CM_RX_DONE | AST2600_I2CM_NORMAL_STOP:
xfer_len = AST2600_I2CC_GET_RX_BUF_LEN(readl(i2c_bus->reg_base +
AST2600_I2CC_BUFF_CTRL));
@@ -668,6 +934,12 @@ static irqreturn_t ast2600_i2c_bus_irq(int irq, void *dev_id)
{
struct ast2600_i2c_bus *i2c_bus = dev_id;
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ if (i2c_bus->target) {
+ if (ast2600_i2c_target_irq(i2c_bus))
+ return IRQ_HANDLED;
+ }
+#endif
return IRQ_RETVAL(ast2600_i2c_controller_irq(i2c_bus));
}
@@ -684,6 +956,21 @@ static int ast2600_i2c_controller_xfer(struct i2c_adapter *adap, struct i2c_msg
return ret;
}
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ if (READ_ONCE(i2c_bus->target_active))
+ return -EBUSY;
+ /*
+ * Controller and target share the same buffer register. A target
+ * transaction can update buffer state asynchronously via IRQ, so block
+ * controller transfers while target is active to avoid buffer corruption.
+ */
+ writel(0, i2c_bus->reg_base + AST2600_I2CS_IER);
+ if (readl(i2c_bus->reg_base + AST2600_I2CS_ISR) || READ_ONCE(i2c_bus->target_active)) {
+ writel(AST2600_I2CS_PKT_DONE, i2c_bus->reg_base + AST2600_I2CS_IER);
+ return -EBUSY;
+ }
+#endif
+
i2c_bus->cmd_err = 0;
i2c_bus->msgs = msgs;
i2c_bus->msgs_index = 0;
@@ -691,6 +978,10 @@ static int ast2600_i2c_controller_xfer(struct i2c_adapter *adap, struct i2c_msg
WRITE_ONCE(i2c_bus->stop_pending, false);
reinit_completion(&i2c_bus->cmd_complete);
ret = ast2600_i2c_do_start(i2c_bus);
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ /* avoid race condition target is wait and controller wait 1st target operate */
+ writel(AST2600_I2CS_PKT_DONE, i2c_bus->reg_base + AST2600_I2CS_IER);
+#endif
if (ret)
goto controller_out;
timeout = wait_for_completion_timeout(&i2c_bus->cmd_complete, i2c_bus->adap.timeout);
@@ -719,6 +1010,9 @@ static int ast2600_i2c_controller_xfer(struct i2c_adapter *adap, struct i2c_msg
* if the bus is still busy.
*/
if (i2c_bus->multi_master &&
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ !READ_ONCE(i2c_bus->target_active) &&
+#endif
(readl(i2c_bus->reg_base + AST2600_I2CC_STS_AND_BUFF) &
AST2600_I2CC_BUS_BUSY_STS))
ast2600_i2c_recover_bus(i2c_bus);
@@ -767,8 +1061,66 @@ static int ast2600_i2c_init(struct ast2600_i2c_bus *i2c_bus)
/* Clear Interrupt */
writel(GENMASK(27, 0), i2c_bus->reg_base + AST2600_I2CM_ISR);
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ writel(GENMASK(27, 0), i2c_bus->reg_base + AST2600_I2CS_ISR);
+#endif
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static int ast2600_i2c_reg_target(struct i2c_client *client)
+{
+ struct ast2600_i2c_bus *i2c_bus = i2c_get_adapdata(client->adapter);
+ u32 cmd = TARGET_TRIGGER_CMD;
+
+ if (i2c_bus->target)
+ return -EINVAL;
+
+ if (client->flags & I2C_CLIENT_TEN)
+ return -EAFNOSUPPORT;
+
+ dev_dbg(i2c_bus->dev, "target addr %x\n", client->addr);
+
+ writel(0, i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
+
+ i2c_bus->target = client;
+
+ writel(AST2600_I2CC_SLAVE_EN | readl(i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL),
+ i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
+
+ writel(cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
+ /* Set target addr. */
+ writel(client->addr | AST2600_I2CS_ADDR1_ENABLE,
+ i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
+
+ writel(AST2600_I2CS_PKT_DONE, i2c_bus->reg_base + AST2600_I2CS_IER);
+
+ return 0;
+}
+
+static int ast2600_i2c_unreg_target(struct i2c_client *client)
+{
+ struct ast2600_i2c_bus *i2c_bus = i2c_get_adapdata(client->adapter);
+ u32 val;
+
+ writel(0, i2c_bus->reg_base + AST2600_I2CS_IER);
+
+ val = readl(i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
+ writel(val & ~AST2600_I2CC_SLAVE_EN, i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
+ writel(0, i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
+
+ synchronize_irq(i2c_bus->irq);
+
+ writel(readl(i2c_bus->reg_base + AST2600_I2CS_ISR),
+ i2c_bus->reg_base + AST2600_I2CS_ISR);
+
+ i2c_bus->target = NULL;
+ WRITE_ONCE(i2c_bus->target_active, false);
+
return 0;
}
+#endif
static u32 ast2600_i2c_functionality(struct i2c_adapter *adap)
{
@@ -778,6 +1130,10 @@ static u32 ast2600_i2c_functionality(struct i2c_adapter *adap)
static const struct i2c_algorithm i2c_ast2600_algorithm = {
.xfer = ast2600_i2c_controller_xfer,
.functionality = ast2600_i2c_functionality,
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ .reg_target = ast2600_i2c_reg_target,
+ .unreg_target = ast2600_i2c_unreg_target,
+#endif
};
static const struct i2c_adapter_quirks ast2600_i2c_quirks = {
@@ -821,6 +1177,9 @@ static int ast2600_i2c_probe(struct platform_device *pdev)
regmap_write(i2c_bus->global_regs, AST2600_I2CG_CLK_DIV_CTRL, I2CCG_DIV_CTRL);
}
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ WRITE_ONCE(i2c_bus->target_active, false);
+#endif
i2c_bus->dev = dev;
i2c_bus->multi_master = device_property_read_bool(dev, "multi-master");
--
2.34.1
^ permalink raw reply related
page: next (older)
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox