* Re: [RFC PATCH v2 3/5] dt-bindings: clock: meson: document A1 SoC audio clock controller driver
From: Krzysztof Kozlowski @ 2024-03-28 9:01 UTC (permalink / raw)
To: Jan Dakinevich, Neil Armstrong, Jerome Brunet, Michael Turquette,
Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Kevin Hilman, Martin Blumenstingl, Philipp Zabel, linux-amlogic,
linux-clk, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20240328010831.884487-4-jan.dakinevich@salutedevices.com>
On 28/03/2024 02:08, Jan Dakinevich wrote:
> Add device tree bindings for A1 SoC audio clock and reset controllers.
>
> Signed-off-by: Jan Dakinevich <jan.dakinevich@salutedevices.com>
> ---
> +title: Amlogic A1 Audio Clock Control Unit and Reset Controller
> +
> +maintainers:
> + - Neil Armstrong <neil.armstrong@linaro.org>
> + - Jerome Brunet <jbrunet@baylibre.com>
> + - Jan Dakinevich <jan.dakinevich@salutedevices.com>
> +
> +properties:
> + compatible:
> + enum:
> + - amlogic,a1-audio-clkc
> + - amlogic,a1-audio2-clkc
What is "2"?
> +
> + '#clock-cells':
> + const: 1
> +
> + '#reset-cells':
> + const: 1
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + minItems: 6
> + maxItems: 7
> +
> + clock-names:
> + minItems: 6
> + maxItems: 7
> +
> +required:
> + - compatible
> + - '#clock-cells'
> + - reg
> + - clocks
> + - clock-names
> +
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - amlogic,a1-audio-clkc
> + then:
> + properties:
> + clocks:
> + items:
> + - description: input core clock
> + - description: input main peripheral bus clock
> + - description: input dds_in
> + - description: input fixed pll div2
> + - description: input fixed pll div3
> + - description: input hifi_pll
> + - description: input oscillator (usually at 24MHz)
> + clocks-names:
> + items:
> + - const: core
> + - const: pclk
> + - const: dds_in
> + - const: fclk_div2
> + - const: fclk_div3
> + - const: hifi_pll
> + - const: xtal
> + required:
> + - '#reset-cells'
> + else:
> + properties:
> + clocks:
> + items:
> + - description: input main peripheral bus clock
> + - description: input dds_in
> + - description: input fixed pll div2
> + - description: input fixed pll div3
> + - description: input hifi_pll
> + - description: input oscillator (usually at 24MHz)
> + clock-names:
> + items:
> + - const: pclk
> + - const: dds_in
> + - const: fclk_div2
> + - const: fclk_div3
> + - const: hifi_pll
> + - const: xtal
#reset-cells: false
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
> + #include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
> + #include <dt-bindings/clock/amlogic,a1-audio-clkc.h>
> + audio {
If there is going to be any new version/resend:
soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + clkc_audio: audio-clock-controller@fe050000 {
Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
So: clock-controller
> + compatible = "amlogic,a1-audio-clkc";
> + reg = <0x0 0xfe050000 0x0 0xb0>;
> + #clock-cells = <1>;
> + #reset-cells = <1>;
> + clocks = <&clkc_audio2 AUD2_CLKID_AUDIOTOP>,
> + <&clkc_periphs CLKID_AUDIO>,
> + <&clkc_periphs CLKID_DDS_IN>,
> + <&clkc_pll CLKID_FCLK_DIV2>,
> + <&clkc_pll CLKID_FCLK_DIV3>,
> + <&clkc_pll CLKID_HIFI_PLL>,
> + <&xtal>;
> + clock-names = "core",
> + "pclk",
> + "dds_in",
> + "fclk_div2",
> + "fclk_div3",
> + "hifi_pll",
> + "xtal";
> + };
> +
> + clkc_audio2: audio-clock-controller@fe054800 {
clock-controller
(so I expect resend)
> + compatible = "amlogic,a1-audio2-clkc";
> + reg = <0x0 0xfe054800 0x0 0x20>;
> + #clock-cells = <1>;
> + clocks = <&clkc_periphs CLKID_AUDIO>,
> + <&clkc_periphs CLKID_DDS_IN>,
> + <&clkc_pll CLKID_FCLK_DIV2>,
> + <&clkc_pll CLKID_FCLK_DIV3>,
> + <&clkc_pll CLKID_HIFI_PLL>,
> + <&xtal>;
> + clock-names = "pclk",
> + "dds_in",
> + "fclk_div2",
> + "fclk_div3",
> + "hifi_pll",
> + "xtal";
> + };
> + };
> diff --git a/include/dt-bindings/clock/amlogic,a1-audio-clkc.h b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
> new file mode 100644
> index 000000000000..b30df3b1ae08
> --- /dev/null
> +++ b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
> @@ -0,0 +1,122 @@
> +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
> +/*
> + * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
> + *
> + * Author: Jan Dakinevich <jan.dakinevich@salutedevices.com>
> + */
> +
> +#ifndef __A1_AUDIO_CLKC_BINDINGS_H
> +#define __A1_AUDIO_CLKC_BINDINGS_H
> +
> +#define AUD_CLKID_DDR_ARB 1
> +#define AUD_CLKID_TDMIN_A 2
> +#define AUD_CLKID_TDMIN_B 3
> +#define AUD_CLKID_TDMIN_LB 4
Why both clock controllers have the same clocks? This is confusing. It
seems you split same block into two!
Best regards,
Krzysztof
^ permalink raw reply
* Re: [RFC PATCH v2 3/5] dt-bindings: clock: meson: document A1 SoC audio clock controller driver
From: Krzysztof Kozlowski @ 2024-03-28 9:02 UTC (permalink / raw)
To: Jan Dakinevich, Neil Armstrong, Jerome Brunet, Michael Turquette,
Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Kevin Hilman, Martin Blumenstingl, Philipp Zabel, linux-amlogic,
linux-clk, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <cff5e036-7f7c-4270-be0c-f49b196a502b@linaro.org>
On 28/03/2024 10:01, Krzysztof Kozlowski wrote:
>> diff --git a/include/dt-bindings/clock/amlogic,a1-audio-clkc.h b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
>> new file mode 100644
>> index 000000000000..b30df3b1ae08
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
>> @@ -0,0 +1,122 @@
>> +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
>> +/*
>> + * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
>> + *
>> + * Author: Jan Dakinevich <jan.dakinevich@salutedevices.com>
>> + */
>> +
>> +#ifndef __A1_AUDIO_CLKC_BINDINGS_H
>> +#define __A1_AUDIO_CLKC_BINDINGS_H
>> +
>> +#define AUD_CLKID_DDR_ARB 1
>> +#define AUD_CLKID_TDMIN_A 2
>> +#define AUD_CLKID_TDMIN_B 3
>> +#define AUD_CLKID_TDMIN_LB 4
>
> Why both clock controllers have the same clocks? This is confusing. It
> seems you split same block into two!
Ah, no, I missed there are IDs for second clock controller. It's fine.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH net-next v2 2/4] net: macb: Add ARP support to WOL
From: claudiu beznea @ 2024-03-28 9:05 UTC (permalink / raw)
To: Vineeth Karumanchi, nicolas.ferre, davem, edumazet, kuba, pabeni,
robh+dt, krzysztof.kozlowski+dt, conor+dt, linux, vadim.fedorenko,
andrew
Cc: netdev, devicetree, linux-kernel, git
In-Reply-To: <20240222153848.2374782-3-vineeth.karumanchi@amd.com>
On 22.02.2024 17:38, Vineeth Karumanchi wrote:
> -Add wake-on LAN support using ARP with the provision to select
> through ethtool. Advertise wakeup capability in the probe and
> get the supported modes from OS policy (MACB_CAPS_WOL).
>
> -Re-order MACB_WOL_<> macros for ease of extension.
> -Add ARP support configurable through ethtool, "wolopts" variable in
> struct macb contains the current WOL options configured through ethtool.
>
> -For WOL via ARP, ensure the IP address is assigned and
> report an error otherwise.
Having '-' for each thing that you did makes the 1st time reader of this
commit message think that you did multiple things in this patch, which
should be avoided.
Also, please compose the commit message such that it responds to the
questions "what the patch does?" and "why it's necessary?"
>
> Co-developed-by: Harini Katakam <harini.katakam@amd.com>
> Signed-off-by: Harini Katakam <harini.katakam@amd.com>
> Signed-off-by: Vineeth Karumanchi <vineeth.karumanchi@amd.com>
> ---
> drivers/net/ethernet/cadence/macb.h | 2 +
> drivers/net/ethernet/cadence/macb_main.c | 52 +++++++++++++++++-------
> 2 files changed, 40 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
> index 50cd35ef21ad..c9ca61959f3c 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -738,6 +738,7 @@
> #define MACB_CAPS_MIIONRGMII 0x00000200
> #define MACB_CAPS_NEED_TSUCLK 0x00000400
> #define MACB_CAPS_QUEUE_DISABLE 0x00000800
> +#define MACB_CAPS_WOL 0x00001000
> #define MACB_CAPS_PCS 0x01000000
> #define MACB_CAPS_HIGH_SPEED 0x02000000
> #define MACB_CAPS_CLK_HW_CHG 0x04000000
> @@ -1306,6 +1307,7 @@ struct macb {
> unsigned int jumbo_max_len;
>
> u32 wol;
> + u32 wolopts;
>
> /* holds value of rx watermark value for pbuf_rxcutthru register */
> u32 rx_watermark;
> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> index f34933ef03b0..62d796ef4035 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -38,6 +38,7 @@
> #include <linux/ptp_classify.h>
> #include <linux/reset.h>
> #include <linux/firmware/xlnx-zynqmp.h>
> +#include <linux/inetdevice.h>
> #include "macb.h"
>
> /* This structure is only used for MACB on SiFive FU540 devices */
> @@ -84,8 +85,9 @@ struct sifive_fu540_macb_mgmt {
> #define GEM_MTU_MIN_SIZE ETH_MIN_MTU
> #define MACB_NETIF_LSO NETIF_F_TSO
>
> -#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0)
> -#define MACB_WOL_ENABLED (0x1 << 1)
> +#define MACB_WOL_ENABLED (0x1 << 0)> +#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 1)
Is there a reason you changed the values of these 2 macros?
> +#define MACB_WOL_HAS_ARP_PACKET (0x1 << 2)
>
> #define HS_SPEED_10000M 4
> #define MACB_SERDES_RATE_10G 1
> @@ -3278,18 +3280,18 @@ static void macb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
> {
> struct macb *bp = netdev_priv(netdev);
>
> - if (bp->wol & MACB_WOL_HAS_MAGIC_PACKET) {
> + if (bp->wol & (MACB_WOL_HAS_MAGIC_PACKET | MACB_WOL_HAS_ARP_PACKET))
> phylink_ethtool_get_wol(bp->phylink, wol);
> - wol->supported |= WAKE_MAGIC;
> -
> - if (bp->wol & MACB_WOL_ENABLED)
> - wol->wolopts |= WAKE_MAGIC;
> - }
> + wol->supported |= (bp->wol & MACB_WOL_HAS_MAGIC_PACKET) ? WAKE_MAGIC : 0;
> + wol->supported |= (bp->wol & MACB_WOL_HAS_ARP_PACKET) ? WAKE_ARP : 0;
> + /* Pass wolopts to ethtool */
> + wol->wolopts = bp->wolopts;
> }
>
> static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
> {
> struct macb *bp = netdev_priv(netdev);
> + bp->wolopts = 0;
> int ret;
>
> /* Pass the order to phylink layer */
> @@ -3300,11 +3302,14 @@ static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
> if (!ret || ret != -EOPNOTSUPP)
> return ret;
>
> - if (!(bp->wol & MACB_WOL_HAS_MAGIC_PACKET) ||
> - (wol->wolopts & ~WAKE_MAGIC))
> + if (!(bp->wol & (MACB_WOL_HAS_MAGIC_PACKET | MACB_WOL_HAS_ARP_PACKET)) ||
> + (wol->wolopts & ~(WAKE_MAGIC | WAKE_ARP)))
> return -EOPNOTSUPP;
>
> - if (wol->wolopts & WAKE_MAGIC)
> + bp->wolopts |= (wol->wolopts & WAKE_MAGIC) ? WAKE_MAGIC : 0;
> + bp->wolopts |= (wol->wolopts & WAKE_ARP) ? WAKE_ARP : 0;
> +
> + if (bp->wolopts)
> bp->wol |= MACB_WOL_ENABLED;
> else
> bp->wol &= ~MACB_WOL_ENABLED;
> @@ -5087,7 +5092,6 @@ static int macb_probe(struct platform_device *pdev)
> bp->wol = 0;
> if (of_property_read_bool(np, "magic-packet"))
> bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
> - device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
>
> bp->usrio = macb_config->usrio;
>
> @@ -5115,6 +5119,11 @@ static int macb_probe(struct platform_device *pdev)
> /* setup capabilities */
> macb_configure_caps(bp, macb_config);
>
> + if (bp->caps & MACB_CAPS_WOL)
> + bp->wol |= (MACB_WOL_HAS_ARP_PACKET | MACB_WOL_HAS_MAGIC_PACKET);
> +
> + device_set_wakeup_capable(&pdev->dev, (bp->wol) ? true : false);
It can be simplified with:
device_set_wakeup_capable(&pdev->dev, !!bp->wol);
> +
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
> dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
> @@ -5244,6 +5253,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
> struct net_device *netdev = dev_get_drvdata(dev);
> struct macb *bp = netdev_priv(netdev);
> struct macb_queue *queue;
> + struct in_ifaddr *ifa;
> unsigned long flags;
> unsigned int q;
> int err;
> @@ -5256,6 +5266,12 @@ static int __maybe_unused macb_suspend(struct device *dev)
> return 0;
>
> if (bp->wol & MACB_WOL_ENABLED) {
> + /* Check for IP address in WOL ARP mode */
> + ifa = rcu_dereference(__in_dev_get_rcu(bp->dev)->ifa_list);
> + if ((bp->wolopts & WAKE_ARP) && !ifa) {
> + netdev_err(netdev, "IP address not assigned\n");
> + return -EOPNOTSUPP;
> + }
> spin_lock_irqsave(&bp->lock, flags);
>
> /* Disable Tx and Rx engines before disabling the queues,
> @@ -5289,6 +5305,14 @@ static int __maybe_unused macb_suspend(struct device *dev)
> macb_writel(bp, TSR, -1);
> macb_writel(bp, RSR, -1);
>
> + tmp = (bp->wolopts & WAKE_MAGIC) ? MACB_BIT(MAG) : 0;
> + if (bp->wolopts & WAKE_ARP) {
> + tmp |= MACB_BIT(ARP);
> + /* write IP address into register */
> + tmp |= MACB_BFEXT(IP,
> + (__force u32)(cpu_to_be32p((uint32_t *)&ifa->ifa_local)));
> + }
> +
> /* Change interrupt handler and
> * Enable WoL IRQ on queue 0
> */
> @@ -5304,7 +5328,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
> return err;
> }
> queue_writel(bp->queues, IER, GEM_BIT(WOL));
> - gem_writel(bp, WOL, MACB_BIT(MAG));
> + gem_writel(bp, WOL, tmp);
> } else {
> err = devm_request_irq(dev, bp->queues[0].irq, macb_wol_interrupt,
> IRQF_SHARED, netdev->name, bp->queues);
> @@ -5316,7 +5340,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
> return err;
> }
> queue_writel(bp->queues, IER, MACB_BIT(WOL));
> - macb_writel(bp, WOL, MACB_BIT(MAG));
> + macb_writel(bp, WOL, tmp);
> }
> spin_unlock_irqrestore(&bp->lock, flags);
>
^ permalink raw reply
* Re: [PATCH RESEND v6 5/5] spmi: pmic-arb: Add multi bus support
From: Neil Armstrong @ 2024-03-28 9:05 UTC (permalink / raw)
To: Abel Vesa, Stephen Boyd, Matthias Brugger, Bjorn Andersson,
Konrad Dybcio, Dmitry Baryshkov, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree
In-Reply-To: <20240326-spmi-multi-master-support-v6-5-1c87d8306c5b@linaro.org>
Hi Abel,
On 26/03/2024 17:28, Abel Vesa wrote:
> Starting with HW version 7, there are actually two separate buses
> (with two separate sets of wires). So in order to support both
> buses, we need to register a separate spmi controller for each one.
> Add a separate compatible for v7 only, but allow the legacy platforms
> that have v7 to still work with the old one, for DT backwards
> compatibility.
>
> Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> ---
> drivers/spmi/spmi-pmic-arb.c | 726 +++++++++++++++++++++++++------------------
> 1 file changed, 429 insertions(+), 297 deletions(-)
>
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 188252bfb95f..ca0f42952445 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -13,6 +13,8 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> #include <linux/spmi.h>
> @@ -94,6 +96,8 @@ enum pmic_arb_channel {
> PMIC_ARB_CHANNEL_OBS,
> };
>
> +#define PMIC_ARB_MAX_BUSES 2
> +
> /* Maximum number of support PMIC peripherals */
> #define PMIC_ARB_MAX_PERIPHS 512
> #define PMIC_ARB_MAX_PERIPHS_V7 1024
> @@ -125,58 +129,68 @@ struct apid_data {
> u8 irq_ee;
> };
>
> +struct spmi_pmic_arb;
> +
> /**
> - * struct spmi_pmic_arb - SPMI PMIC Arbiter object
> + * struct spmi_pmic_arb_bus - SPMI PMIC Arbiter Bus object
> *
> - * @rd_base: on v1 "core", on v2 "observer" register base off DT.
> - * @wr_base: on v1 "core", on v2 "chnls" register base off DT.
> * @intr: address of the SPMI interrupt control registers.
> * @cnfg: address of the PMIC Arbiter configuration registers.
> - * @lock: lock to synchronize accesses.
> - * @channel: execution environment channel to use for accesses.
> - * @irq: PMIC ARB interrupt.
> - * @ee: the current Execution Environment
> - * @bus_instance: on v7: 0 = primary SPMI bus, 1 = secondary SPMI bus
> - * @min_apid: minimum APID (used for bounding IRQ search)
> - * @max_apid: maximum APID
> + * @domain: irq domain object for PMIC IRQ domain
> * @base_apid: on v7: minimum APID associated with the particular SPMI
> * bus instance
> * @apid_count: on v5 and v7: number of APIDs associated with the
> * particular SPMI bus instance
> * @mapping_table: in-memory copy of PPID -> APID mapping table.
> - * @domain: irq domain object for PMIC IRQ domain
> - * @spmic: SPMI controller object
> - * @ver_ops: version dependent operations.
> * @ppid_to_apid: in-memory copy of PPID -> APID mapping table.
> - * @last_apid: Highest value APID in use
> * @apid_data: Table of data for all APIDs
> + * @last_apid: Highest value APID in use
> + * @irq: PMIC ARB interrupt.
Those are moved for no reason, and it doesn't match anymore with the actual fields in spmi_pmic_arb_bus,
please fix.
> + */
> +struct spmi_pmic_arb_bus {
> + struct spmi_pmic_arb *pmic_arb;
> + struct irq_domain *domain;
> + void __iomem *intr;
> + void __iomem *cnfg;
> + struct spmi_controller *spmic;
> + u16 base_apid;
> + int apid_count;
> + u32 *mapping_table;
> + DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
> + u16 *ppid_to_apid;
> + u16 last_apid;
> + struct apid_data *apid_data;
> + u16 min_apid;
> + u16 max_apid;
> + int irq;
> + u8 id;
> +};
> +
> +/**
> + * struct spmi_pmic_arb - SPMI PMIC Arbiter object
> + *
> + * @rd_base: on v1 "core", on v2 "observer" register base off DT.
> + * @wr_base: on v1 "core", on v2 "chnls" register base off DT.
> + * @lock: lock to synchronize accesses.
> + * @channel: execution environment channel to use for accesses.
> + * @ee: the current Execution Environment
> + * @min_apid: minimum APID (used for bounding IRQ search)
> + * @max_apid: maximum APID
> + * @ver_ops: version dependent operations.
> * @max_periphs: Number of elements in apid_data[]
> */
> struct spmi_pmic_arb {
> void __iomem *rd_base;
> void __iomem *wr_base;
> - void __iomem *intr;
> - void __iomem *cnfg;
> void __iomem *core;
> resource_size_t core_size;
> raw_spinlock_t lock;
> u8 channel;
> - int irq;
> u8 ee;
> - u32 bus_instance;
> - u16 min_apid;
> - u16 max_apid;
> - u16 base_apid;
> - int apid_count;
> - u32 *mapping_table;
> - DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
> - struct irq_domain *domain;
> - struct spmi_controller *spmic;
> const struct pmic_arb_ver_ops *ver_ops;
> - u16 *ppid_to_apid;
> - u16 last_apid;
> - struct apid_data *apid_data;
> int max_periphs;
> + struct spmi_pmic_arb_bus buses[PMIC_ARB_MAX_BUSES];
> + int buses_available;
> };
Same here, please refresh/resync the struct documentation
I get the following:
drivers/spmi/spmi-pmic-arb.c:167: warning: Function parameter or struct member 'pmic_arb' not described in 'spmi_pmic_arb_bus'
drivers/spmi/spmi-pmic-arb.c:167: warning: Function parameter or struct member 'spmic' not described in 'spmi_pmic_arb_bus'
drivers/spmi/spmi-pmic-arb.c:167: warning: Function parameter or struct member 'mapping_table_valid' not described in 'spmi_pmic_arb_bus'
drivers/spmi/spmi-pmic-arb.c:167: warning: Function parameter or struct member 'min_apid' not described in 'spmi_pmic_arb_bus'
drivers/spmi/spmi-pmic-arb.c:167: warning: Function parameter or struct member 'max_apid' not described in 'spmi_pmic_arb_bus'
drivers/spmi/spmi-pmic-arb.c:167: warning: Function parameter or struct member 'id' not described in 'spmi_pmic_arb_bus'
drivers/spmi/spmi-pmic-arb.c:194: warning: Function parameter or struct member 'core' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:194: warning: Function parameter or struct member 'core_size' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:194: warning: Function parameter or struct member 'buses' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:194: warning: Function parameter or struct member 'buses_available' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:194: warning: Excess struct member 'min_apid' description in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:194: warning: Excess struct member 'max_apid' description in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:236: warning: Function parameter or struct member 'get_core_resources' not described in 'pmic_arb_ver_ops'
drivers/spmi/spmi-pmic-arb.c:258: warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_read_data'
drivers/spmi/spmi-pmic-arb.c:272: warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_write_data'
>
> /**
> @@ -204,21 +218,21 @@ struct spmi_pmic_arb {
> struct pmic_arb_ver_ops {
> const char *ver_str;
> int (*get_core_resources)(struct platform_device *pdev, void __iomem *core);
> - int (*init_apid)(struct spmi_pmic_arb *pmic_arb, int index);
> - int (*ppid_to_apid)(struct spmi_pmic_arb *pmic_arb, u16 ppid);
> + int (*init_apid)(struct spmi_pmic_arb_bus *bus, int index);
> + int (*ppid_to_apid)(struct spmi_pmic_arb_bus *bus, u16 ppid);
> /* spmi commands (read_cmd, write_cmd, cmd) functionality */
> - int (*offset)(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> - enum pmic_arb_channel ch_type);
> + int (*offset)(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
> + enum pmic_arb_channel ch_type);
> u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
> int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
> /* Interrupts controller functionality (offset of PIC registers) */
> - void __iomem *(*owner_acc_status)(struct spmi_pmic_arb *pmic_arb, u8 m,
> + void __iomem *(*owner_acc_status)(struct spmi_pmic_arb_bus *bus, u8 m,
> u16 n);
> - void __iomem *(*acc_enable)(struct spmi_pmic_arb *pmic_arb, u16 n);
> - void __iomem *(*irq_status)(struct spmi_pmic_arb *pmic_arb, u16 n);
> - void __iomem *(*irq_clear)(struct spmi_pmic_arb *pmic_arb, u16 n);
> + void __iomem *(*acc_enable)(struct spmi_pmic_arb_bus *bus, u16 n);
> + void __iomem *(*irq_status)(struct spmi_pmic_arb_bus *bus, u16 n);
> + void __iomem *(*irq_clear)(struct spmi_pmic_arb_bus *bus, u16 n);
> u32 (*apid_map_offset)(u16 n);
> - void __iomem *(*apid_owner)(struct spmi_pmic_arb *pmic_arb, u16 n);
> + void __iomem *(*apid_owner)(struct spmi_pmic_arb_bus *bus, u16 n);
> };
>
> static inline void pmic_arb_base_write(struct spmi_pmic_arb *pmic_arb,
> @@ -266,13 +280,14 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
> void __iomem *base, u8 sid, u16 addr,
> enum pmic_arb_channel ch_type)
> {
> - struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u32 status = 0;
> u32 timeout = PMIC_ARB_TIMEOUT_US;
> u32 offset;
> int rc;
>
> - rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, ch_type);
> + rc = pmic_arb->ver_ops->offset(bus, sid, addr, ch_type);
> if (rc < 0)
> return rc;
>
> @@ -284,21 +299,21 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
>
> if (status & PMIC_ARB_STATUS_DONE) {
> if (status & PMIC_ARB_STATUS_DENIED) {
> - dev_err(&ctrl->dev, "%s: %#x %#x: transaction denied (%#x)\n",
> - __func__, sid, addr, status);
> + dev_err(&ctrl->dev, "%s: %#x %#x %#x: transaction denied (%#x)\n",
> + __func__, bus->id, sid, addr, status);
Won't "dev_err(&ctrl->dev" already print the bus id ?
> return -EPERM;
> }
>
> if (status & PMIC_ARB_STATUS_FAILURE) {
> - dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x)\n",
> - __func__, sid, addr, status);
> + dev_err(&ctrl->dev, "%s: %#x %#x %#x: transaction failed (%#x) reg: 0x%x\n",
> + __func__, bus->id, sid, addr, status, offset);
> WARN_ON(1);
> return -EIO;
> }
>
> if (status & PMIC_ARB_STATUS_DROPPED) {
> - dev_err(&ctrl->dev, "%s: %#x %#x: transaction dropped (%#x)\n",
> - __func__, sid, addr, status);
> + dev_err(&ctrl->dev, "%s: %#x %#x %#x: transaction dropped (%#x)\n",
> + __func__, bus->id, sid, addr, status);
> return -EIO;
> }
>
> @@ -307,8 +322,8 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
> udelay(1);
> }
>
> - dev_err(&ctrl->dev, "%s: %#x %#x: timeout, status %#x\n",
> - __func__, sid, addr, status);
> + dev_err(&ctrl->dev, "%s: %#x %#x %#x: timeout, status %#x\n",
> + __func__, bus->id, sid, addr, status);
> return -ETIMEDOUT;
> }
>
> @@ -316,12 +331,13 @@ static int
> pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid)
> {
> struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb_bus *bus = &pmic_arb->buses[0];
> unsigned long flags;
> u32 cmd;
> int rc;
> u32 offset;
>
> - rc = pmic_arb->ver_ops->offset(pmic_arb, sid, 0, PMIC_ARB_CHANNEL_RW);
> + rc = pmic_arb->ver_ops->offset(bus, sid, 0, PMIC_ARB_CHANNEL_RW);
> if (rc < 0)
> return rc;
>
> @@ -357,20 +373,21 @@ static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
> return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid);
> }
>
> -static int pmic_arb_fmt_read_cmd(struct spmi_pmic_arb *pmic_arb, u8 opc, u8 sid,
> +static int pmic_arb_fmt_read_cmd(struct spmi_pmic_arb_bus *bus, u8 opc, u8 sid,
> u16 addr, size_t len, u32 *cmd, u32 *offset)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u8 bc = len - 1;
> int rc;
>
> - rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr,
> + rc = pmic_arb->ver_ops->offset(bus, sid, addr,
> PMIC_ARB_CHANNEL_OBS);
> if (rc < 0)
> return rc;
>
> *offset = rc;
> if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
> - dev_err(&pmic_arb->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
> + dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
> PMIC_ARB_MAX_TRANS_BYTES, len);
> return -EINVAL;
> }
> @@ -394,7 +411,8 @@ static int pmic_arb_read_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
> u32 offset, u8 sid, u16 addr, u8 *buf,
> size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u8 bc = len - 1;
> int rc;
>
> @@ -416,12 +434,13 @@ static int pmic_arb_read_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
> static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> u16 addr, u8 *buf, size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> unsigned long flags;
> u32 cmd, offset;
> int rc;
>
> - rc = pmic_arb_fmt_read_cmd(pmic_arb, opc, sid, addr, len, &cmd,
> + rc = pmic_arb_fmt_read_cmd(bus, opc, sid, addr, len, &cmd,
> &offset);
> if (rc)
> return rc;
> @@ -433,21 +452,22 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> return rc;
> }
>
> -static int pmic_arb_fmt_write_cmd(struct spmi_pmic_arb *pmic_arb, u8 opc,
> +static int pmic_arb_fmt_write_cmd(struct spmi_pmic_arb_bus *bus, u8 opc,
> u8 sid, u16 addr, size_t len, u32 *cmd,
> u32 *offset)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u8 bc = len - 1;
> int rc;
>
> - rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr,
> + rc = pmic_arb->ver_ops->offset(bus, sid, addr,
> PMIC_ARB_CHANNEL_RW);
> if (rc < 0)
> return rc;
>
> *offset = rc;
> if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
> - dev_err(&pmic_arb->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
> + dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
> PMIC_ARB_MAX_TRANS_BYTES, len);
> return -EINVAL;
> }
> @@ -473,7 +493,8 @@ static int pmic_arb_write_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
> u32 offset, u8 sid, u16 addr,
> const u8 *buf, size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u8 bc = len - 1;
>
> /* Write data to FIFOs */
> @@ -492,12 +513,13 @@ static int pmic_arb_write_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
> static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> u16 addr, const u8 *buf, size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> unsigned long flags;
> u32 cmd, offset;
> int rc;
>
> - rc = pmic_arb_fmt_write_cmd(pmic_arb, opc, sid, addr, len, &cmd,
> + rc = pmic_arb_fmt_write_cmd(bus, opc, sid, addr, len, &cmd,
> &offset);
> if (rc)
> return rc;
> @@ -513,18 +535,19 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> static int pmic_arb_masked_write(struct spmi_controller *ctrl, u8 sid, u16 addr,
> const u8 *buf, const u8 *mask, size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u32 read_cmd, read_offset, write_cmd, write_offset;
> u8 temp[PMIC_ARB_MAX_TRANS_BYTES];
> unsigned long flags;
> int rc, i;
>
> - rc = pmic_arb_fmt_read_cmd(pmic_arb, SPMI_CMD_EXT_READL, sid, addr, len,
> + rc = pmic_arb_fmt_read_cmd(bus, SPMI_CMD_EXT_READL, sid, addr, len,
> &read_cmd, &read_offset);
> if (rc)
> return rc;
>
> - rc = pmic_arb_fmt_write_cmd(pmic_arb, SPMI_CMD_EXT_WRITEL, sid, addr,
> + rc = pmic_arb_fmt_write_cmd(bus, SPMI_CMD_EXT_WRITEL, sid, addr,
> len, &write_cmd, &write_offset);
> if (rc)
> return rc;
> @@ -567,25 +590,25 @@ struct spmi_pmic_arb_qpnpint_type {
> static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
> size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
> u8 sid = hwirq_to_sid(d->hwirq);
> u8 per = hwirq_to_per(d->hwirq);
>
> - if (pmic_arb_write_cmd(pmic_arb->spmic, SPMI_CMD_EXT_WRITEL, sid,
> + if (pmic_arb_write_cmd(bus->spmic, SPMI_CMD_EXT_WRITEL, sid,
> (per << 8) + reg, buf, len))
> - dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n",
> + dev_err_ratelimited(&bus->spmic->dev, "failed irqchip transaction on %x\n",
> d->irq);
> }
>
> static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
> u8 sid = hwirq_to_sid(d->hwirq);
> u8 per = hwirq_to_per(d->hwirq);
>
> - if (pmic_arb_read_cmd(pmic_arb->spmic, SPMI_CMD_EXT_READL, sid,
> + if (pmic_arb_read_cmd(bus->spmic, SPMI_CMD_EXT_READL, sid,
> (per << 8) + reg, buf, len))
> - dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n",
> + dev_err_ratelimited(&bus->spmic->dev, "failed irqchip transaction on %x\n",
> d->irq);
> }
>
> @@ -593,47 +616,49 @@ static int qpnpint_spmi_masked_write(struct irq_data *d, u8 reg,
> const void *buf, const void *mask,
> size_t len)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
> u8 sid = hwirq_to_sid(d->hwirq);
> u8 per = hwirq_to_per(d->hwirq);
> int rc;
>
> - rc = pmic_arb_masked_write(pmic_arb->spmic, sid, (per << 8) + reg, buf,
> + rc = pmic_arb_masked_write(bus->spmic, sid, (per << 8) + reg, buf,
> mask, len);
> if (rc)
> - dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x rc=%d\n",
> + dev_err_ratelimited(&bus->spmic->dev, "failed irqchip transaction on %x rc=%d\n",
> d->irq, rc);
> return rc;
> }
>
> -static void cleanup_irq(struct spmi_pmic_arb *pmic_arb, u16 apid, int id)
> +static void cleanup_irq(struct spmi_pmic_arb_bus *bus, u16 apid, int id)
> {
> - u16 ppid = pmic_arb->apid_data[apid].ppid;
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> + u16 ppid = bus->apid_data[apid].ppid;
> u8 sid = ppid >> 8;
> u8 per = ppid & 0xFF;
> u8 irq_mask = BIT(id);
>
> - dev_err_ratelimited(&pmic_arb->spmic->dev, "%s apid=%d sid=0x%x per=0x%x irq=%d\n",
> - __func__, apid, sid, per, id);
> - writel_relaxed(irq_mask, pmic_arb->ver_ops->irq_clear(pmic_arb, apid));
> + dev_err_ratelimited(&bus->spmic->dev, "%s apid=%d sid=0x%x per=0x%x irq=%d\n",
> + __func__, apid, sid, per, id);
> + writel_relaxed(irq_mask, pmic_arb->ver_ops->irq_clear(bus, apid));
> }
>
> -static int periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid)
> +static int periph_interrupt(struct spmi_pmic_arb_bus *bus, u16 apid)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> unsigned int irq;
> u32 status, id;
> int handled = 0;
> - u8 sid = (pmic_arb->apid_data[apid].ppid >> 8) & 0xF;
> - u8 per = pmic_arb->apid_data[apid].ppid & 0xFF;
> + u8 sid = (bus->apid_data[apid].ppid >> 8) & 0xF;
> + u8 per = bus->apid_data[apid].ppid & 0xFF;
>
> - status = readl_relaxed(pmic_arb->ver_ops->irq_status(pmic_arb, apid));
> + status = readl_relaxed(pmic_arb->ver_ops->irq_status(bus, apid));
> while (status) {
> id = ffs(status) - 1;
> status &= ~BIT(id);
> - irq = irq_find_mapping(pmic_arb->domain,
> - spec_to_hwirq(sid, per, id, apid));
> + irq = irq_find_mapping(bus->domain,
> + spec_to_hwirq(sid, per, id, apid));
> if (irq == 0) {
> - cleanup_irq(pmic_arb, apid, id);
> + cleanup_irq(bus, apid, id);
> continue;
> }
> generic_handle_irq(irq);
> @@ -645,16 +670,17 @@ static int periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid)
>
> static void pmic_arb_chained_irq(struct irq_desc *desc)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_desc_get_handler_data(desc);
> + struct spmi_pmic_arb_bus *bus = irq_desc_get_handler_data(desc);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> const struct pmic_arb_ver_ops *ver_ops = pmic_arb->ver_ops;
> struct irq_chip *chip = irq_desc_get_chip(desc);
> - int first = pmic_arb->min_apid;
> - int last = pmic_arb->max_apid;
> + int first = bus->min_apid;
> + int last = bus->max_apid;
> /*
> * acc_offset will be non-zero for the secondary SPMI bus instance on
> * v7 controllers.
> */
> - int acc_offset = pmic_arb->base_apid >> 5;
> + int acc_offset = bus->base_apid >> 5;
> u8 ee = pmic_arb->ee;
> u32 status, enable, handled = 0;
> int i, id, apid;
> @@ -665,7 +691,7 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
> chained_irq_enter(chip, desc);
>
> for (i = first >> 5; i <= last >> 5; ++i) {
> - status = readl_relaxed(ver_ops->owner_acc_status(pmic_arb, ee, i - acc_offset));
> + status = readl_relaxed(ver_ops->owner_acc_status(bus, ee, i - acc_offset));
> if (status)
> acc_valid = true;
>
> @@ -679,9 +705,9 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
> continue;
> }
> enable = readl_relaxed(
> - ver_ops->acc_enable(pmic_arb, apid));
> + ver_ops->acc_enable(bus, apid));
> if (enable & SPMI_PIC_ACC_ENABLE_BIT)
> - if (periph_interrupt(pmic_arb, apid) != 0)
> + if (periph_interrupt(bus, apid) != 0)
> handled++;
> }
> }
> @@ -690,19 +716,19 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
> if (!acc_valid) {
> for (i = first; i <= last; i++) {
> /* skip if APPS is not irq owner */
> - if (pmic_arb->apid_data[i].irq_ee != pmic_arb->ee)
> + if (bus->apid_data[i].irq_ee != pmic_arb->ee)
> continue;
>
> irq_status = readl_relaxed(
> - ver_ops->irq_status(pmic_arb, i));
> + ver_ops->irq_status(bus, i));
> if (irq_status) {
> enable = readl_relaxed(
> - ver_ops->acc_enable(pmic_arb, i));
> + ver_ops->acc_enable(bus, i));
> if (enable & SPMI_PIC_ACC_ENABLE_BIT) {
> - dev_dbg(&pmic_arb->spmic->dev,
> + dev_dbg(&bus->spmic->dev,
> "Dispatching IRQ for apid=%d status=%x\n",
> i, irq_status);
> - if (periph_interrupt(pmic_arb, i) != 0)
> + if (periph_interrupt(bus, i) != 0)
> handled++;
> }
> }
> @@ -717,12 +743,13 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
>
> static void qpnpint_irq_ack(struct irq_data *d)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u8 irq = hwirq_to_irq(d->hwirq);
> u16 apid = hwirq_to_apid(d->hwirq);
> u8 data;
>
> - writel_relaxed(BIT(irq), pmic_arb->ver_ops->irq_clear(pmic_arb, apid));
> + writel_relaxed(BIT(irq), pmic_arb->ver_ops->irq_clear(bus, apid));
>
> data = BIT(irq);
> qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
> @@ -738,14 +765,15 @@ static void qpnpint_irq_mask(struct irq_data *d)
>
> static void qpnpint_irq_unmask(struct irq_data *d)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> const struct pmic_arb_ver_ops *ver_ops = pmic_arb->ver_ops;
> u8 irq = hwirq_to_irq(d->hwirq);
> u16 apid = hwirq_to_apid(d->hwirq);
> u8 buf[2];
>
> writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT,
> - ver_ops->acc_enable(pmic_arb, apid));
> + ver_ops->acc_enable(bus, apid));
>
> qpnpint_spmi_read(d, QPNPINT_REG_EN_SET, &buf[0], 1);
> if (!(buf[0] & BIT(irq))) {
> @@ -802,9 +830,9 @@ static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
>
> static int qpnpint_irq_set_wake(struct irq_data *d, unsigned int on)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
>
> - return irq_set_irq_wake(pmic_arb->irq, on);
> + return irq_set_irq_wake(bus->irq, on);
> }
>
> static int qpnpint_get_irqchip_state(struct irq_data *d,
> @@ -826,17 +854,18 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
> static int qpnpint_irq_domain_activate(struct irq_domain *domain,
> struct irq_data *d, bool reserve)
> {
> - struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u16 periph = hwirq_to_per(d->hwirq);
> u16 apid = hwirq_to_apid(d->hwirq);
> u16 sid = hwirq_to_sid(d->hwirq);
> u16 irq = hwirq_to_irq(d->hwirq);
> u8 buf;
>
> - if (pmic_arb->apid_data[apid].irq_ee != pmic_arb->ee) {
> - dev_err(&pmic_arb->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u: ee=%u but owner=%u\n",
> + if (bus->apid_data[apid].irq_ee != pmic_arb->ee) {
> + dev_err(&bus->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u: ee=%u but owner=%u\n",
> sid, periph, irq, pmic_arb->ee,
> - pmic_arb->apid_data[apid].irq_ee);
> + bus->apid_data[apid].irq_ee);
> return -ENODEV;
> }
>
> @@ -863,15 +892,16 @@ static int qpnpint_irq_domain_translate(struct irq_domain *d,
> unsigned long *out_hwirq,
> unsigned int *out_type)
> {
> - struct spmi_pmic_arb *pmic_arb = d->host_data;
> + struct spmi_pmic_arb_bus *bus = d->host_data;
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u32 *intspec = fwspec->param;
> u16 apid, ppid;
> int rc;
>
> - dev_dbg(&pmic_arb->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
> + dev_dbg(&bus->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
> intspec[0], intspec[1], intspec[2]);
>
> - if (irq_domain_get_of_node(d) != pmic_arb->spmic->dev.of_node)
> + if (irq_domain_get_of_node(d) != bus->spmic->dev.of_node)
> return -EINVAL;
> if (fwspec->param_count != 4)
> return -EINVAL;
> @@ -879,37 +909,38 @@ static int qpnpint_irq_domain_translate(struct irq_domain *d,
> return -EINVAL;
>
> ppid = intspec[0] << 8 | intspec[1];
> - rc = pmic_arb->ver_ops->ppid_to_apid(pmic_arb, ppid);
> + rc = pmic_arb->ver_ops->ppid_to_apid(bus, ppid);
> if (rc < 0) {
> - dev_err(&pmic_arb->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u rc = %d\n",
> - intspec[0], intspec[1], intspec[2], rc);
> + dev_err(&bus->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u rc = %d\n",
> + intspec[0], intspec[1], intspec[2], rc);
> return rc;
> }
>
> apid = rc;
> /* Keep track of {max,min}_apid for bounding search during interrupt */
> - if (apid > pmic_arb->max_apid)
> - pmic_arb->max_apid = apid;
> - if (apid < pmic_arb->min_apid)
> - pmic_arb->min_apid = apid;
> + if (apid > bus->max_apid)
> + bus->max_apid = apid;
> + if (apid < bus->min_apid)
> + bus->min_apid = apid;
>
> *out_hwirq = spec_to_hwirq(intspec[0], intspec[1], intspec[2], apid);
> *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
>
> - dev_dbg(&pmic_arb->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
> + dev_dbg(&bus->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
>
> return 0;
> }
>
> static struct lock_class_key qpnpint_irq_lock_class, qpnpint_irq_request_class;
>
> -static void qpnpint_irq_domain_map(struct spmi_pmic_arb *pmic_arb,
> +static void qpnpint_irq_domain_map(struct spmi_pmic_arb_bus *bus,
> struct irq_domain *domain, unsigned int virq,
> irq_hw_number_t hwirq, unsigned int type)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> irq_flow_handler_t handler;
>
> - dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu, type = %u\n",
> + dev_dbg(&bus->spmic->dev, "virq = %u, hwirq = %lu, type = %u\n",
> virq, hwirq, type);
>
> if (type & IRQ_TYPE_EDGE_BOTH)
> @@ -928,7 +959,7 @@ static int qpnpint_irq_domain_alloc(struct irq_domain *domain,
> unsigned int virq, unsigned int nr_irqs,
> void *data)
> {
> - struct spmi_pmic_arb *pmic_arb = domain->host_data;
> + struct spmi_pmic_arb_bus *bus = domain->host_data;
> struct irq_fwspec *fwspec = data;
> irq_hw_number_t hwirq;
> unsigned int type;
> @@ -939,20 +970,22 @@ static int qpnpint_irq_domain_alloc(struct irq_domain *domain,
> return ret;
>
> for (i = 0; i < nr_irqs; i++)
> - qpnpint_irq_domain_map(pmic_arb, domain, virq + i, hwirq + i,
> + qpnpint_irq_domain_map(bus, domain, virq + i, hwirq + i,
> type);
>
> return 0;
> }
>
> -static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb *pmic_arb)
> +static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb_bus *bus)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> +
> /*
> * Initialize max_apid/min_apid to the opposite bounds, during
> * the irq domain translation, we are sure to update these
> */
> - pmic_arb->max_apid = 0;
> - pmic_arb->min_apid = pmic_arb->max_periphs - 1;
> + bus->max_apid = 0;
> + bus->min_apid = pmic_arb->max_periphs - 1;
>
> return 0;
> }
> @@ -970,43 +1003,44 @@ static int pmic_arb_get_core_resources_v1(struct platform_device *pdev,
> return 0;
> }
>
> -static int pmic_arb_init_apid_v1(struct spmi_pmic_arb *pmic_arb, int index)
> +static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus, int index)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u32 *mapping_table;
>
> if (index) {
> - dev_err(&pmic_arb->spmic->dev, "Unsupported buses count %d detected\n",
> + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n",
> index);
> return -EINVAL;
> }
>
> - mapping_table = devm_kcalloc(&pmic_arb->spmic->dev, pmic_arb->max_periphs,
> + mapping_table = devm_kcalloc(&bus->spmic->dev, pmic_arb->max_periphs,
> sizeof(*mapping_table), GFP_KERNEL);
> if (!mapping_table)
> return -ENOMEM;
>
> - pmic_arb->mapping_table = mapping_table;
> + bus->mapping_table = mapping_table;
>
> - return pmic_arb_init_apid_min_max(pmic_arb);
> + return pmic_arb_init_apid_min_max(bus);
> }
>
> -static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> +static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb_bus *bus, u16 ppid)
> {
> - u32 *mapping_table = pmic_arb->mapping_table;
> + u32 *mapping_table = bus->mapping_table;
> int index = 0, i;
> u16 apid_valid;
> u16 apid;
> u32 data;
>
> - apid_valid = pmic_arb->ppid_to_apid[ppid];
> + apid_valid = bus->ppid_to_apid[ppid];
> if (apid_valid & PMIC_ARB_APID_VALID) {
> apid = apid_valid & ~PMIC_ARB_APID_VALID;
> return apid;
> }
>
> for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
> - if (!test_and_set_bit(index, pmic_arb->mapping_table_valid))
> - mapping_table[index] = readl_relaxed(pmic_arb->cnfg +
> + if (!test_and_set_bit(index, bus->mapping_table_valid))
> + mapping_table[index] = readl_relaxed(bus->cnfg +
> SPMI_MAPPING_TABLE_REG(index));
>
> data = mapping_table[index];
> @@ -1016,9 +1050,9 @@ static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
> } else {
> apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
> - pmic_arb->ppid_to_apid[ppid]
> + bus->ppid_to_apid[ppid]
> = apid | PMIC_ARB_APID_VALID;
> - pmic_arb->apid_data[apid].ppid = ppid;
> + bus->apid_data[apid].ppid = ppid;
> return apid;
> }
> } else {
> @@ -1026,9 +1060,9 @@ static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
> } else {
> apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
> - pmic_arb->ppid_to_apid[ppid]
> + bus->ppid_to_apid[ppid]
> = apid | PMIC_ARB_APID_VALID;
> - pmic_arb->apid_data[apid].ppid = ppid;
> + bus->apid_data[apid].ppid = ppid;
> return apid;
> }
> }
> @@ -1038,24 +1072,26 @@ static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> }
>
> /* v1 offset per ee */
> -static int pmic_arb_offset_v1(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> - enum pmic_arb_channel ch_type)
> +static int pmic_arb_offset_v1(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
> + enum pmic_arb_channel ch_type)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> return 0x800 + 0x80 * pmic_arb->channel;
> }
>
> -static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> +static u16 pmic_arb_find_apid(struct spmi_pmic_arb_bus *bus, u16 ppid)
> {
> - struct apid_data *apidd = &pmic_arb->apid_data[pmic_arb->last_apid];
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> + struct apid_data *apidd = &bus->apid_data[bus->last_apid];
> u32 regval, offset;
> u16 id, apid;
>
> - for (apid = pmic_arb->last_apid; ; apid++, apidd++) {
> + for (apid = bus->last_apid; ; apid++, apidd++) {
> offset = pmic_arb->ver_ops->apid_map_offset(apid);
> if (offset >= pmic_arb->core_size)
> break;
>
> - regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(pmic_arb,
> + regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(bus,
> apid));
> apidd->irq_ee = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
> apidd->write_ee = apidd->irq_ee;
> @@ -1065,14 +1101,14 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> continue;
>
> id = (regval >> 8) & PMIC_ARB_PPID_MASK;
> - pmic_arb->ppid_to_apid[id] = apid | PMIC_ARB_APID_VALID;
> + bus->ppid_to_apid[id] = apid | PMIC_ARB_APID_VALID;
> apidd->ppid = id;
> if (id == ppid) {
> apid |= PMIC_ARB_APID_VALID;
> break;
> }
> }
> - pmic_arb->last_apid = apid & ~PMIC_ARB_APID_VALID;
> + bus->last_apid = apid & ~PMIC_ARB_APID_VALID;
>
> return apid;
> }
> @@ -1104,21 +1140,22 @@ static int pmic_arb_get_core_resources_v2(struct platform_device *pdev,
> return pmic_arb_get_obsrvr_chnls_v2(pdev);
> }
>
> -static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> +static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb_bus *bus, u16 ppid)
> {
> u16 apid_valid;
>
> - apid_valid = pmic_arb->ppid_to_apid[ppid];
> + apid_valid = bus->ppid_to_apid[ppid];
> if (!(apid_valid & PMIC_ARB_APID_VALID))
> - apid_valid = pmic_arb_find_apid(pmic_arb, ppid);
> + apid_valid = pmic_arb_find_apid(bus, ppid);
> if (!(apid_valid & PMIC_ARB_APID_VALID))
> return -ENODEV;
>
> return apid_valid & ~PMIC_ARB_APID_VALID;
> }
>
> -static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
> +static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb_bus *bus)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> struct apid_data *apidd;
> struct apid_data *prev_apidd;
> u16 i, apid, ppid, apid_max;
> @@ -1140,9 +1177,9 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
> * where N = number of APIDs supported by the primary bus and
> * M = number of APIDs supported by the secondary bus
> */
> - apidd = &pmic_arb->apid_data[pmic_arb->base_apid];
> - apid_max = pmic_arb->base_apid + pmic_arb->apid_count;
> - for (i = pmic_arb->base_apid; i < apid_max; i++, apidd++) {
> + apidd = &bus->apid_data[bus->base_apid];
> + apid_max = bus->base_apid + bus->apid_count;
> + for (i = bus->base_apid; i < apid_max; i++, apidd++) {
> offset = pmic_arb->ver_ops->apid_map_offset(i);
> if (offset >= pmic_arb->core_size)
> break;
> @@ -1153,19 +1190,18 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
> ppid = (regval >> 8) & PMIC_ARB_PPID_MASK;
> is_irq_ee = PMIC_ARB_CHAN_IS_IRQ_OWNER(regval);
>
> - regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(pmic_arb,
> - i));
> + regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(bus, i));
> apidd->write_ee = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
>
> apidd->irq_ee = is_irq_ee ? apidd->write_ee : INVALID_EE;
>
> - valid = pmic_arb->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID;
> - apid = pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
> - prev_apidd = &pmic_arb->apid_data[apid];
> + valid = bus->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID;
> + apid = bus->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
> + prev_apidd = &bus->apid_data[apid];
>
> if (!valid || apidd->write_ee == pmic_arb->ee) {
> /* First PPID mapping or one for this EE */
> - pmic_arb->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID;
> + bus->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID;
> } else if (valid && is_irq_ee &&
> prev_apidd->write_ee == pmic_arb->ee) {
> /*
> @@ -1176,42 +1212,43 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
> }
>
> apidd->ppid = ppid;
> - pmic_arb->last_apid = i;
> + bus->last_apid = i;
> }
>
> /* Dump the mapping table for debug purposes. */
> - dev_dbg(&pmic_arb->spmic->dev, "PPID APID Write-EE IRQ-EE\n");
> + dev_dbg(&bus->spmic->dev, "PPID APID Write-EE IRQ-EE\n");
> for (ppid = 0; ppid < PMIC_ARB_MAX_PPID; ppid++) {
> - apid = pmic_arb->ppid_to_apid[ppid];
> + apid = bus->ppid_to_apid[ppid];
> if (apid & PMIC_ARB_APID_VALID) {
> apid &= ~PMIC_ARB_APID_VALID;
> - apidd = &pmic_arb->apid_data[apid];
> - dev_dbg(&pmic_arb->spmic->dev, "%#03X %3u %2u %2u\n",
> - ppid, apid, apidd->write_ee, apidd->irq_ee);
> + apidd = &bus->apid_data[apid];
> + dev_dbg(&bus->spmic->dev, "%#03X %3u %2u %2u\n",
> + ppid, apid, apidd->write_ee, apidd->irq_ee);
> }
> }
>
> return 0;
> }
>
> -static int pmic_arb_ppid_to_apid_v5(struct spmi_pmic_arb *pmic_arb, u16 ppid)
> +static int pmic_arb_ppid_to_apid_v5(struct spmi_pmic_arb_bus *bus, u16 ppid)
> {
> - if (!(pmic_arb->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID))
> + if (!(bus->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID))
> return -ENODEV;
>
> - return pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
> + return bus->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
> }
>
> /* v2 offset per ppid and per ee */
> -static int pmic_arb_offset_v2(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> - enum pmic_arb_channel ch_type)
> +static int pmic_arb_offset_v2(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
> + enum pmic_arb_channel ch_type)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u16 apid;
> u16 ppid;
> int rc;
>
> ppid = sid << 8 | ((addr >> 8) & 0xFF);
> - rc = pmic_arb_ppid_to_apid_v2(pmic_arb, ppid);
> + rc = pmic_arb_ppid_to_apid_v2(bus, ppid);
> if (rc < 0)
> return rc;
>
> @@ -1219,33 +1256,34 @@ static int pmic_arb_offset_v2(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> return 0x1000 * pmic_arb->ee + 0x8000 * apid;
> }
>
> -static int pmic_arb_init_apid_v5(struct spmi_pmic_arb *pmic_arb, int index)
> +static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus, int index)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> int ret;
>
> if (index) {
> - dev_err(&pmic_arb->spmic->dev, "Unsupported buses count %d detected\n",
> + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n",
> index);
> return -EINVAL;
> }
>
> - pmic_arb->base_apid = 0;
> - pmic_arb->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
> + bus->base_apid = 0;
> + bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
> PMIC_ARB_FEATURES_PERIPH_MASK;
>
> - if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) {
> - dev_err(&pmic_arb->spmic->dev, "Unsupported APID count %d detected\n",
> - pmic_arb->base_apid + pmic_arb->apid_count);
> + if (bus->base_apid + bus->apid_count > pmic_arb->max_periphs) {
> + dev_err(&bus->spmic->dev, "Unsupported APID count %d detected\n",
> + bus->base_apid + bus->apid_count);
> return -EINVAL;
> }
>
> - ret = pmic_arb_init_apid_min_max(pmic_arb);
> + ret = pmic_arb_init_apid_min_max(bus);
> if (ret)
> return ret;
>
> - ret = pmic_arb_read_apid_map_v5(pmic_arb);
> + ret = pmic_arb_read_apid_map_v5(bus);
> if (ret) {
> - dev_err(&pmic_arb->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
> + dev_err(&bus->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
> ret);
> return ret;
> }
> @@ -1257,15 +1295,16 @@ static int pmic_arb_init_apid_v5(struct spmi_pmic_arb *pmic_arb, int index)
> * v5 offset per ee and per apid for observer channels and per apid for
> * read/write channels.
> */
> -static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> - enum pmic_arb_channel ch_type)
> +static int pmic_arb_offset_v5(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
> + enum pmic_arb_channel ch_type)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u16 apid;
> int rc;
> u32 offset = 0;
> u16 ppid = (sid << 8) | (addr >> 8);
>
> - rc = pmic_arb_ppid_to_apid_v5(pmic_arb, ppid);
> + rc = pmic_arb_ppid_to_apid_v5(bus, ppid);
> if (rc < 0)
> return rc;
>
> @@ -1275,8 +1314,8 @@ static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> offset = 0x10000 * pmic_arb->ee + 0x80 * apid;
> break;
> case PMIC_ARB_CHANNEL_RW:
> - if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) {
> - dev_err(&pmic_arb->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
> + if (bus->apid_data[apid].write_ee != pmic_arb->ee) {
> + dev_err(&bus->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
> sid, addr);
> return -EPERM;
> }
> @@ -1303,38 +1342,39 @@ static int pmic_arb_get_core_resources_v7(struct platform_device *pdev,
> * Only v7 supports 2 buses. Each bus will get a different apid count, read
> * from different registers.
> */
> -static int pmic_arb_init_apid_v7(struct spmi_pmic_arb *pmic_arb, int index)
> +static int pmic_arb_init_apid_v7(struct spmi_pmic_arb_bus *bus, int index)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> int ret;
>
> if (index == 0) {
> - pmic_arb->base_apid = 0;
> - pmic_arb->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
> + bus->base_apid = 0;
> + bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
> PMIC_ARB_FEATURES_PERIPH_MASK;
> } else if (index == 1) {
> - pmic_arb->base_apid = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
> + bus->base_apid = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
> PMIC_ARB_FEATURES_PERIPH_MASK;
> - pmic_arb->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES1) &
> + bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES1) &
> PMIC_ARB_FEATURES_PERIPH_MASK;
> } else {
> - dev_err(&pmic_arb->spmic->dev, "Unsupported buses count %d detected\n",
> - index);
> + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n",
> + bus->id);
> return -EINVAL;
> }
>
> - if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) {
> - dev_err(&pmic_arb->spmic->dev, "Unsupported APID count %d detected\n",
> - pmic_arb->base_apid + pmic_arb->apid_count);
> + if (bus->base_apid + bus->apid_count > pmic_arb->max_periphs) {
> + dev_err(&bus->spmic->dev, "Unsupported APID count %d detected\n",
> + bus->base_apid + bus->apid_count);
> return -EINVAL;
> }
>
> - ret = pmic_arb_init_apid_min_max(pmic_arb);
> + ret = pmic_arb_init_apid_min_max(bus);
> if (ret)
> return ret;
>
> - ret = pmic_arb_read_apid_map_v5(pmic_arb);
> + ret = pmic_arb_read_apid_map_v5(bus);
> if (ret) {
> - dev_err(&pmic_arb->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
> + dev_err(&bus->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
> ret);
> return ret;
> }
> @@ -1346,15 +1386,16 @@ static int pmic_arb_init_apid_v7(struct spmi_pmic_arb *pmic_arb, int index)
> * v7 offset per ee and per apid for observer channels and per apid for
> * read/write channels.
> */
> -static int pmic_arb_offset_v7(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> - enum pmic_arb_channel ch_type)
> +static int pmic_arb_offset_v7(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
> + enum pmic_arb_channel ch_type)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> u16 apid;
> int rc;
> u32 offset = 0;
> u16 ppid = (sid << 8) | (addr >> 8);
>
> - rc = pmic_arb->ver_ops->ppid_to_apid(pmic_arb, ppid);
> + rc = pmic_arb->ver_ops->ppid_to_apid(bus, ppid);
> if (rc < 0)
> return rc;
>
> @@ -1364,8 +1405,8 @@ static int pmic_arb_offset_v7(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
> offset = 0x8000 * pmic_arb->ee + 0x20 * apid;
> break;
> case PMIC_ARB_CHANNEL_RW:
> - if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) {
> - dev_err(&pmic_arb->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
> + if (bus->apid_data[apid].write_ee != pmic_arb->ee) {
> + dev_err(&bus->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
> sid, addr);
> return -EPERM;
> }
> @@ -1387,104 +1428,110 @@ static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc)
> }
>
> static void __iomem *
> -pmic_arb_owner_acc_status_v1(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
> +pmic_arb_owner_acc_status_v1(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
> {
> - return pmic_arb->intr + 0x20 * m + 0x4 * n;
> + return bus->intr + 0x20 * m + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_owner_acc_status_v2(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
> +pmic_arb_owner_acc_status_v2(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
> {
> - return pmic_arb->intr + 0x100000 + 0x1000 * m + 0x4 * n;
> + return bus->intr + 0x100000 + 0x1000 * m + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_owner_acc_status_v3(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
> +pmic_arb_owner_acc_status_v3(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
> {
> - return pmic_arb->intr + 0x200000 + 0x1000 * m + 0x4 * n;
> + return bus->intr + 0x200000 + 0x1000 * m + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
> +pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
> {
> - return pmic_arb->intr + 0x10000 * m + 0x4 * n;
> + return bus->intr + 0x10000 * m + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_owner_acc_status_v7(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
> +pmic_arb_owner_acc_status_v7(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
> {
> - return pmic_arb->intr + 0x1000 * m + 0x4 * n;
> + return bus->intr + 0x1000 * m + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_acc_enable_v1(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_acc_enable_v1(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->intr + 0x200 + 0x4 * n;
> + return bus->intr + 0x200 + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_acc_enable_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_acc_enable_v2(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->intr + 0x1000 * n;
> + return bus->intr + 0x1000 * n;
> }
>
> static void __iomem *
> -pmic_arb_acc_enable_v5(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_acc_enable_v5(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> return pmic_arb->wr_base + 0x100 + 0x10000 * n;
> }
>
> static void __iomem *
> -pmic_arb_acc_enable_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_acc_enable_v7(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> return pmic_arb->wr_base + 0x100 + 0x1000 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_status_v1(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_status_v1(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->intr + 0x600 + 0x4 * n;
> + return bus->intr + 0x600 + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_status_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_status_v2(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->intr + 0x4 + 0x1000 * n;
> + return bus->intr + 0x4 + 0x1000 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_status_v5(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_status_v5(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> return pmic_arb->wr_base + 0x104 + 0x10000 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_status_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_status_v7(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> return pmic_arb->wr_base + 0x104 + 0x1000 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_clear_v1(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_clear_v1(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->intr + 0xA00 + 0x4 * n;
> + return bus->intr + 0xA00 + 0x4 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_clear_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_clear_v2(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->intr + 0x8 + 0x1000 * n;
> + return bus->intr + 0x8 + 0x1000 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_clear_v5(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_clear_v5(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> return pmic_arb->wr_base + 0x108 + 0x10000 * n;
> }
>
> static void __iomem *
> -pmic_arb_irq_clear_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_irq_clear_v7(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
> return pmic_arb->wr_base + 0x108 + 0x1000 * n;
> }
>
> @@ -1504,9 +1551,9 @@ static u32 pmic_arb_apid_map_offset_v7(u16 n)
> }
>
> static void __iomem *
> -pmic_arb_apid_owner_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_apid_owner_v2(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->cnfg + 0x700 + 0x4 * n;
> + return bus->cnfg + 0x700 + 0x4 * n;
> }
>
> /*
> @@ -1515,9 +1562,9 @@ pmic_arb_apid_owner_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
> * 0.
> */
> static void __iomem *
> -pmic_arb_apid_owner_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
> +pmic_arb_apid_owner_v7(struct spmi_pmic_arb_bus *bus, u16 n)
> {
> - return pmic_arb->cnfg + 0x4 * (n - pmic_arb->base_apid);
> + return bus->cnfg + 0x4 * (n - bus->base_apid);
> }
>
> static const struct pmic_arb_ver_ops pmic_arb_v1 = {
> @@ -1607,29 +1654,159 @@ static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
> .translate = qpnpint_irq_domain_translate,
> };
>
> +static int spmi_pmic_arb_bus_init(struct platform_device *pdev,
> + struct device_node *node,
> + struct spmi_pmic_arb *pmic_arb)
> +{
> + int bus_index = pmic_arb->buses_available;
> + struct spmi_pmic_arb_bus *bus = &pmic_arb->buses[bus_index];
> + struct device *dev = &pdev->dev;
> + struct spmi_controller *ctrl;
> + void __iomem *intr;
> + void __iomem *cnfg;
> + int index, ret;
> + u32 irq;
> +
> + ctrl = devm_spmi_controller_alloc(dev, sizeof(*ctrl));
> + if (IS_ERR(ctrl))
> + return PTR_ERR(ctrl);
> +
> + ctrl->cmd = pmic_arb_cmd;
> + ctrl->read_cmd = pmic_arb_read_cmd;
> + ctrl->write_cmd = pmic_arb_write_cmd;
> +
> + bus = spmi_controller_get_drvdata(ctrl);
> + bus->spmic = ctrl;
> +
> + bus->ppid_to_apid = devm_kcalloc(dev, PMIC_ARB_MAX_PPID,
> + sizeof(*bus->ppid_to_apid),
> + GFP_KERNEL);
> + if (!bus->ppid_to_apid)
> + return -ENOMEM;
> +
> + bus->apid_data = devm_kcalloc(dev, pmic_arb->max_periphs,
> + sizeof(*bus->apid_data),
> + GFP_KERNEL);
> + if (!bus->apid_data)
> + return -ENOMEM;
> +
> + index = of_property_match_string(node, "reg-names", "cnfg");
> + if (index < 0) {
> + dev_err(dev, "cnfg reg region missing");
> + return -EINVAL;
> + }
> +
> + cnfg = devm_of_iomap(dev, node, index, NULL);
> + if (IS_ERR(cnfg))
> + return PTR_ERR(cnfg);
> +
> + index = of_property_match_string(node, "reg-names", "intr");
> + if (index < 0) {
> + dev_err(dev, "intr reg region missing");
> + return -EINVAL;
> + }
> +
> + intr = devm_of_iomap(dev, node, index, NULL);
> + if (IS_ERR(intr))
> + return PTR_ERR(intr);
> +
> + irq = of_irq_get_byname(node, "periph_irq");
> + if (irq < 0)
> + return irq;
> +
> + bus->pmic_arb = pmic_arb;
> + bus->intr = intr;
> + bus->cnfg = cnfg;
> + bus->irq = irq;
> + bus->id = bus_index;
> +
> + ret = pmic_arb->ver_ops->init_apid(bus, bus_index);
> + if (ret)
> + return ret;
> +
> + dev_dbg(&pdev->dev, "adding irq domain for bus %d\n", bus_index);
> +
> + bus->domain = irq_domain_add_tree(dev->of_node,
> + &pmic_arb_irq_domain_ops, bus);
> + if (!bus->domain) {
> + dev_err(&pdev->dev, "unable to create irq_domain\n");
> + return -ENOMEM;
> + }
> +
> + irq_set_chained_handler_and_data(bus->irq,
> + pmic_arb_chained_irq, bus);
> +
> + bus->spmic->dev.of_node = node;
> + dev_set_name(&bus->spmic->dev, "spmi-%d", bus_index);
> +
> + ret = devm_spmi_controller_add(dev, bus->spmic);
> + if (ret)
> + return ret;
> +
> + pmic_arb->buses_available++;
> +
> + return 0;
> +}
> +
> +static int spmi_pmic_arb_register_buses(struct spmi_pmic_arb *pmic_arb,
> + struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *node = dev->of_node;
> + struct device_node *child;
> + int ret;
> +
> + /* legacy mode doesn't provide child node for the bus */
> + if (of_device_is_compatible(node, "qcom,spmi-pmic-arb"))
> + return spmi_pmic_arb_bus_init(pdev, node, pmic_arb);
> +
> + for_each_available_child_of_node(node, child) {
> + if (of_node_name_eq(child, "spmi")) {
> + ret = spmi_pmic_arb_bus_init(pdev, child, pmic_arb);
> + if (ret)
> + return ret;
> + }
> + }
> +
> + return ret;
> +}
> +
> +static void spmi_pmic_arb_deregister_buses(struct spmi_pmic_arb *pmic_arb)
> +{
> + int i;
> +
> + for (i = 0; i < PMIC_ARB_MAX_BUSES; i++) {
> + struct spmi_pmic_arb_bus *bus = &pmic_arb->buses[i];
> +
> + irq_set_chained_handler_and_data(bus->irq,
> + NULL, NULL);
> + irq_domain_remove(bus->domain);
> + }
> +}
> +
> static int spmi_pmic_arb_probe(struct platform_device *pdev)
> {
> struct spmi_pmic_arb *pmic_arb;
> - struct spmi_controller *ctrl;
> + struct device *dev = &pdev->dev;
> struct resource *res;
> void __iomem *core;
> u32 channel, ee, hw_ver;
> int err;
>
> - ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*pmic_arb));
> - if (IS_ERR(ctrl))
> - return PTR_ERR(ctrl);
> -
> - pmic_arb = spmi_controller_get_drvdata(ctrl);
> - pmic_arb->spmic = ctrl;
> + pmic_arb = devm_kzalloc(dev, sizeof(*pmic_arb), GFP_KERNEL);
> + if (!pmic_arb)
> + return -ENOMEM;
>
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
> - core = devm_ioremap(&ctrl->dev, res->start, resource_size(res));
> + core = devm_ioremap(dev, res->start, resource_size(res));
> if (IS_ERR(core))
> return PTR_ERR(core);
>
> pmic_arb->core_size = resource_size(res);
>
> + platform_set_drvdata(pdev, pmic_arb);
> + raw_spin_lock_init(&pmic_arb->lock);
> +
> hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
>
> if (hw_ver < PMIC_ARB_VERSION_V2_MIN)
> @@ -1643,30 +1820,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
> else
> pmic_arb->ver_ops = &pmic_arb_v7;
>
> - dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
> - pmic_arb->ver_ops->ver_str, hw_ver);
> -
> err = pmic_arb->ver_ops->get_core_resources(pdev, core);
> if (err)
> return err;
>
> - err = pmic_arb->ver_ops->init_apid(pmic_arb, 0);
> - if (err)
> - return err;
> -
> - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
> - pmic_arb->intr = devm_ioremap_resource(&ctrl->dev, res);
> - if (IS_ERR(pmic_arb->intr))
> - return PTR_ERR(pmic_arb->intr);
> -
> - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg");
> - pmic_arb->cnfg = devm_ioremap_resource(&ctrl->dev, res);
> - if (IS_ERR(pmic_arb->cnfg))
> - return PTR_ERR(pmic_arb->cnfg);
> -
> - pmic_arb->irq = platform_get_irq_byname(pdev, "periph_irq");
> - if (pmic_arb->irq < 0)
> - return pmic_arb->irq;
> + dev_info(dev, "PMIC arbiter version %s (0x%x)\n",
> + pmic_arb->ver_ops->ver_str, hw_ver);
>
> err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel);
> if (err) {
> @@ -1695,46 +1854,19 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>
> pmic_arb->ee = ee;
>
> - platform_set_drvdata(pdev, ctrl);
> - raw_spin_lock_init(&pmic_arb->lock);
> -
> - ctrl->cmd = pmic_arb_cmd;
> - ctrl->read_cmd = pmic_arb_read_cmd;
> - ctrl->write_cmd = pmic_arb_write_cmd;
> -
> - dev_dbg(&pdev->dev, "adding irq domain\n");
> - pmic_arb->domain = irq_domain_add_tree(pdev->dev.of_node,
> - &pmic_arb_irq_domain_ops, pmic_arb);
> - if (!pmic_arb->domain) {
> - dev_err(&pdev->dev, "unable to create irq_domain\n");
> - return -ENOMEM;
> - }
> -
> - irq_set_chained_handler_and_data(pmic_arb->irq, pmic_arb_chained_irq,
> - pmic_arb);
> - err = spmi_controller_add(ctrl);
> - if (err)
> - goto err_domain_remove;
> -
> - return 0;
> -
> -err_domain_remove:
> - irq_set_chained_handler_and_data(pmic_arb->irq, NULL, NULL);
> - irq_domain_remove(pmic_arb->domain);
> - return err;
> + return spmi_pmic_arb_register_buses(pmic_arb, pdev);
> }
>
> static void spmi_pmic_arb_remove(struct platform_device *pdev)
> {
> - struct spmi_controller *ctrl = platform_get_drvdata(pdev);
> - struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
> - spmi_controller_remove(ctrl);
> - irq_set_chained_handler_and_data(pmic_arb->irq, NULL, NULL);
> - irq_domain_remove(pmic_arb->domain);
> + struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
> +
> + spmi_pmic_arb_deregister_buses(pmic_arb);
> }
>
> static const struct of_device_id spmi_pmic_arb_match_table[] = {
> { .compatible = "qcom,spmi-pmic-arb", },
> + { .compatible = "qcom,x1e80100-spmi-pmic-arb", },
> {},
> };
> MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);
>
The change is quite long and it's hard to disinguish the introduction of
spmi_pmic_arb_bus and the addition of 2 busses for v7.
Could you split in 2 by:
1) adding spmi_pmic_arb_bus but only registering a single bus
2) add the plumbing for 2 busses for v7
it would help review and bisecting.
Thanks,
Neil
^ permalink raw reply
* Re: [PATCH v6 01/16] regulator: dt-bindings: describe the PMU module of the QCA6390 package
From: Krzysztof Kozlowski @ 2024-03-28 9:06 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Saravana Kannan, Geert Uytterhoeven,
Arnd Bergmann, Neil Armstrong, Marek Szyprowski, Alex Elder,
Srini Kandagatla, Greg Kroah-Hartman, Abel Vesa,
Manivannan Sadhasivam, Lukas Wunner, Dmitry Baryshkov,
linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <CAMRc=Mdw9Ox5EC6=GdR_1kzWcfhpdbz1Hu3e7+GY9-wqTh2fhQ@mail.gmail.com>
On 27/03/2024 19:55, Bartosz Golaszewski wrote:
> On Wed, Mar 27, 2024 at 7:17 PM Krzysztof Kozlowski
> <krzysztof.kozlowski@linaro.org> wrote:
>>
>> On 25/03/2024 14:16, Bartosz Golaszewski wrote:
>>> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>>>
>>> The QCA6390 package contains discreet modules for WLAN and Bluetooth. They
>>> are powered by the Power Management Unit (PMU) that takes inputs from the
>>> host and provides LDO outputs. This document describes this module.
>>>
>>> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>>
>> Can you start using b4?
>>
>> This is a friendly reminder during the review process.
>>
>> It looks like you received a tag and forgot to add it.
>>
>> If you do not know the process, here is a short explanation:
>> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
>> versions, under or above your Signed-off-by tag. Tag is "received", when
>> provided in a message replied to you on the mailing list. Tools like b4
>> can help here. However, there's no need to repost patches *only* to add
>> the tags. The upstream maintainer will do that for tags received on the
>> version they apply.
>>
>> https://elixir.bootlin.com/linux/v6.5-rc3/source/Documentation/process/submitting-patches.rst#L577
>>
>> If a tag was not added on purpose, please state why and what changed.
>>
>
> As per the first sentence of the cover letter: I dropped review tags
> from the patches that changed significantly while keeping them for
> those that didn't. If there's a way to let your automation know about
> this, please let me know/point me in the right direction because I
> don't know about it.
>
I went through changelog and did not see any remarks that patch #1
changed. b4 diff tells me: not much changed. Same properties and you
just do not require supplies on other variant.
This is rather minor change - just see by yourself.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v6 01/16] regulator: dt-bindings: describe the PMU module of the QCA6390 package
From: Krzysztof Kozlowski @ 2024-03-28 9:07 UTC (permalink / raw)
To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Kalle Valo,
Bjorn Andersson, Konrad Dybcio, Liam Girdwood, Mark Brown,
Catalin Marinas, Will Deacon, Bjorn Helgaas, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-2-brgl@bgdev.pl>
On 25/03/2024 14:16, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> The QCA6390 package contains discreet modules for WLAN and Bluetooth. They
> are powered by the Power Management Unit (PMU) that takes inputs from the
> host and provides LDO outputs. This document describes this module.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> ---
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH RESEND v6 0/5] spmi: pmic-arb: Add support for multiple buses
From: Neil Armstrong @ 2024-03-28 9:07 UTC (permalink / raw)
To: Abel Vesa, Stephen Boyd, Matthias Brugger, Bjorn Andersson,
Konrad Dybcio, Dmitry Baryshkov, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree
In-Reply-To: <20240326-spmi-multi-master-support-v6-0-1c87d8306c5b@linaro.org>
Hi Abel,
On 26/03/2024 17:28, Abel Vesa wrote:
> This RFC prepares for and adds support for 2 buses, which is supported
> in HW starting with version 7. Until now, none of the currently
> supported platforms in upstream have used the second bus. The X1E80100
> platform, on the other hand, needs the second bus for the USB2.0 to work
> as there are 3 SMB2360 PMICs which provide eUSB2 repeaters and they are
> all found on the second bus.
@Dmitry, @Konrad, @Bjorn, could you apply those patches and test an devices
you have to make sure there's no regression ?
>
> Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> ---
> Changes in v6:
> - Changed the compatible to platform specific (X1E80100) along with the
> schema. Fixed the spmi buses unit addresses and added the empty ranges
> property. Added missing properties to the spmi buses and the
> "unevaluatedProperties: false".
> - Deprecated the "qcom,bus-id" in the legacy schema.
> - Changed the driver to check for legacy compatible first
> - Link to v5: https://lore.kernel.org/r/20240221-spmi-multi-master-support-v5-0-3255ca413a0b@linaro.org
>
> Changes in v5:
> - Dropped the RFC as there aren't any concerns about the approach anymore
> - Dropped the unused dev and res variables from pmic_arb_get_obsrvr_chnls_v2
> - Link to v4: https://lore.kernel.org/r/20240220-spmi-multi-master-support-v4-0-dc813c878ba8@linaro.org
>
> Changes in v4:
> - Fixed comment above pmic_arb_init_apid_v7 by dropping the extra "bus" word
> - Swicthed to devm_platform_ioremap_resource_byname for obsrvr and chnls.
> The core remains with platform_get_resource_byname as we need the core size.
> - Dropped comment from probe related to the need of platform_get_resource_byname
> as it not true anymore.
> - Dropped the qcom,bus-id optional property.
> - Link to v3: https://lore.kernel.org/r/20240214-spmi-multi-master-support-v3-0-0bae0ef04faf@linaro.org
>
> Changes in v3:
> - Split the change into 3 separate patches. First 2 patches are moving
> apid init and core resources into version specific ops. Third one is
> adding the support for 2 buses and dedicated compatible.
> - Added separate bindings patch
> - Link to v2: https://lore.kernel.org/r/20240213-spmi-multi-master-support-v2-1-b3b102326906@linaro.org
>
> Changes in v2:
> - Reworked it so that it registers a spmi controller for each bus
> rather than relying on the generic framework to pass on the bus
> (master) id.
> - Link to v1: https://lore.kernel.org/r/20240207-spmi-multi-master-support-v1-0-ce57f301c7fd@linaro.org
>
> ---
> Abel Vesa (5):
> dt-bindings: spmi: Add X1E80100 SPMI PMIC ARB schema
> dt-bindings: spmi: Deprecate qcom,bus-id
Forgot to add, but please fix this in a v7:
> spmi: pmic-arb: Make the APID init a version operation
drivers/spmi/spmi-pmic-arb.c:180: warning: Function parameter or struct member 'core' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:180: warning: Function parameter or struct member 'core_size' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:180: warning: Function parameter or struct member 'mapping_table_valid' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:243: warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_read_data'
drivers/spmi/spmi-pmic-arb.c:257: warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_write_data'
> spmi: pmic-arb: Make core resources acquiring a version operation
drivers/spmi/spmi-pmic-arb.c:180: warning: Function parameter or struct member 'core' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:180: warning: Function parameter or struct member 'core_size' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:180: warning: Function parameter or struct member 'mapping_table_valid' not described in 'spmi_pmic_arb'
drivers/spmi/spmi-pmic-arb.c:222: warning: Function parameter or struct member 'get_core_resources' not described in 'pmic_arb_ver_ops'
drivers/spmi/spmi-pmic-arb.c:244: warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_read_data'
drivers/spmi/spmi-pmic-arb.c:258: warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_write_data'
> spmi: pmic-arb: Add multi bus support
>
> .../bindings/spmi/qcom,spmi-pmic-arb.yaml | 1 +
> .../bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml | 136 +++
> drivers/spmi/spmi-pmic-arb.c | 948 +++++++++++++--------
> 3 files changed, 715 insertions(+), 370 deletions(-)
> ---
> base-commit: 4893c639cc3659cefaa675bf1e59f4e7571afb5c
> change-id: 20240207-spmi-multi-master-support-832a704b779b
>
> Best regards,
Thanks,
Neil
^ permalink raw reply
* Re: [PATCH v6 3/3] pinctrl: nuvoton: Add ma35d1 pinctrl and GPIO driver
From: Linus Walleij @ 2024-03-28 9:10 UTC (permalink / raw)
To: Jacky Huang
Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, p.zabel, j.neuschaefer,
linux-arm-kernel, linux-gpio, devicetree, linux-kernel, ychuang3,
schung
In-Reply-To: <20240313035719.768469-4-ychuang570808@gmail.com>
Hi Jacky,
overall this looks very good.
On Wed, Mar 13, 2024 at 4:57 AM Jacky Huang <ychuang570808@gmail.com> wrote:
> From: Jacky Huang <ychuang3@nuvoton.com>
>
> Add common pinctrl and GPIO driver for Nuvoton MA35 series SoC, and
> add support for ma35d1 pinctrl.
>
> Signed-off-by: Jacky Huang <ychuang3@nuvoton.com>
(...)
> +static int ma35_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
> + unsigned int group)
> +{
> + struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
> + struct ma35_pin_group *grp = &npctl->groups[group];
> + struct ma35_pin_setting *setting = grp->settings;
> + u32 i, regval;
> +
> + dev_dbg(npctl->dev, "enable function %s group %s\n",
> + npctl->functions[selector].name, npctl->groups[group].name);
> +
> + for (i = 0; i < grp->npins; i++) {
> + regmap_read(npctl->regmap, setting->offset, ®val);
> + regval &= ~GENMASK(setting->shift + 3, setting->shift);
Add a comment explaining why you add +3
> +static int ma35_gpio_core_direction_in(struct gpio_chip *gc, unsigned int gpio)
> +{
> + struct ma35_pin_bank *bank = gpiochip_get_data(gc);
> + void __iomem *reg_mode = bank->reg_base + MA35_GP_REG_MODE;
> + unsigned long flags;
> + unsigned int regval;
> +
> + spin_lock_irqsave(&bank->lock, flags);
> +
> + regval = readl(reg_mode);
> + regval &= ~GENMASK(gpio * 2 + 1, gpio * 2);
> + regval |= MA35_GP_MODE_INPUT << gpio * 2;
Here the first time you do this magic explain in a comment why you
use *2+1 and *2 overall (I guess two bits per line).
> +static int ma35_gpio_core_get(struct gpio_chip *gc, unsigned int gpio)
> +{
> + struct ma35_pin_bank *bank = gpiochip_get_data(gc);
> +
> + return readl(bank->reg_base + MA35_PIN_MAP_BASE + gpio * 4);
Here add a comment explaining the *4
I guess one 32-bit register per pin?
> +static int ma35_irq_irqtype(struct irq_data *d, unsigned int type)
> +{
> + struct ma35_pin_bank *bank = gpiochip_get_data(irq_data_get_irq_chip_data(d));
> + void __iomem *reg_itype = bank->reg_base + MA35_GP_REG_INTTYPE;
> + void __iomem *reg_ien = bank->reg_base + MA35_GP_REG_INTEN;
> + unsigned int num = (d->hwirq);
> +
> + if (type == IRQ_TYPE_PROBE) {
> + writel(readl(reg_itype) & ~BIT(num), reg_itype);
> + writel(readl(reg_ien) | BIT(num) | BIT(num + 16), reg_ien);
> + bank->irqtype &= ~BIT(num);
> + bank->irqinten |= BIT(num) | BIT(num + 16);
> + return 0;
> + }
> +
> + if (type & IRQ_TYPE_LEVEL_MASK) {
> + writel(readl(reg_itype) | BIT(num), reg_itype);
> + writel(readl(reg_ien) & ~(BIT(num) | BIT(num + 16)), reg_ien);
> + bank->irqtype |= BIT(num);
> + bank->irqinten &= ~(BIT(num) | BIT(num + 16));
> + if (type == IRQ_TYPE_LEVEL_HIGH) {
> + writel(readl(reg_ien) | BIT(num + 16), reg_ien);
> + bank->irqinten |= BIT(num + 16);
> + return 0;
> + }
> +
> + if (type == IRQ_TYPE_LEVEL_LOW) {
> + writel(readl(reg_ien) | BIT(num), reg_ien);
> + bank->irqinten |= BIT(num);
> + return 0;
> + }
> +
> + } else {
> + writel(readl(reg_itype) & ~BIT(num), reg_itype);
> + bank->irqtype &= ~BIT(num);
> +
> + if (type & IRQ_TYPE_EDGE_RISING) {
> + writel(readl(reg_ien) | BIT(num + 16), reg_ien);
> + bank->irqinten |= BIT(num + 16);
> +
> + } else {
> + writel(readl(reg_ien) & ~BIT(num + 16), reg_ien);
> + bank->irqinten &= ~BIT(num + 16);
> + }
> +
> + if (type & IRQ_TYPE_EDGE_FALLING) {
> + writel(readl(reg_ien) | BIT(num), reg_ien);
> + bank->irqinten |= BIT(num);
> +
> + } else {
> + writel(readl(reg_ien) & ~BIT(num), reg_ien);
> + bank->irqinten &= ~BIT(num);
> + }
> + }
> + return 0;
> +}
I don't understand why you don't set the irq_handler:
irq_set_handler_locked(d, handle_edge_irq);
irq_set_handler_locked(d, handle_level_irq);
It seems you are not handling IRQ_TYPE_EDGE_BOTH?
What happens if both rising and falling is specified simultaneously?
The if/else nesting is hard to read.
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
(...)
case IRQ_TYPE_EDGE_RISING:
(...)
See drivers/gpio/gpio-ftgpio010.c for an example.
Have you checked that handling edge and level IRQs really work
as expected?
> +static int ma35_gpiolib_register(struct platform_device *pdev, struct ma35_pinctrl *npctl)
> +{
> + struct ma35_pin_ctrl *ctrl = npctl->ctrl;
> + struct ma35_pin_bank *bank = ctrl->pin_banks;
> + int ret;
> + int i;
> +
> + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
> + if (!bank->valid) {
> + dev_warn(&pdev->dev, "bank %s is not valid\n",
> + bank->np->name);
> + continue;
> + }
> + bank->irqtype = 0;
> + bank->irqinten = 0;
> + bank->chip.label = bank->name;
> + bank->chip.of_gpio_n_cells = 2;
> + bank->chip.parent = &pdev->dev;
> + bank->chip.request = ma35_gpio_core_to_request;
> + bank->chip.direction_input = ma35_gpio_core_direction_in;
> + bank->chip.direction_output = ma35_gpio_core_direction_out;
> + bank->chip.get = ma35_gpio_core_get;
> + bank->chip.set = ma35_gpio_core_set;
> + bank->chip.base = -1;
> + bank->chip.ngpio = bank->nr_pins;
> + bank->chip.can_sleep = false;
> + spin_lock_init(&bank->lock);
> +
> + if (bank->irq > 0) {
> + struct gpio_irq_chip *girq;
> +
> + girq = &bank->chip.irq;
> + gpio_irq_chip_set_chip(girq, &ma35_gpio_irqchip);
> + girq->parent_handler = ma35_irq_demux_intgroup;
> + girq->num_parents = 1;
> +
> + girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents),
> + GFP_KERNEL);
> + if (!girq->parents)
> + return -ENOMEM;
> +
> + girq->parents[0] = bank->irq;
> + girq->default_type = IRQ_TYPE_NONE;
> + girq->handler = handle_level_irq;
Does this really work for the edge IRQs?
I recommend setting this to handle_bad_irq and assign the right
handler in .set_type().
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: arm64: marvell: add solidrun cn9130 clearfog boards
From: Krzysztof Kozlowski @ 2024-03-28 9:14 UTC (permalink / raw)
To: Josua Mayer, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Yazan Shhady, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1153cdd4-ed86-4a1f-ae4d-d9da1161f763@solid-run.com>
On 27/03/2024 11:55, Josua Mayer wrote:
>>
>> I don't even understand what is your case.
> I see :(
> Yes there is a disconnect *somewhere*.
>
Your way of quoting, including removing blank lines, weird wrapping,
does not make it easy to answer anything here. Use decent email client
which solves all these problems.
> I shall try again:
> Marvell is selling two chips:
> 1. CN9130, High-Performance Multi-Core CPU, System on Chip
> (can be used alone)
So this is the main SoC?
> 2. 88F8215, SouthBridge Communication Processor, System on Chip
> (only usable in combination with a CN9130)
>
> Now, in terms of compatible string, what happens when a board
> has multiples of these?
Multiple of CN9130? 2x CN9130? Nothing happens, does not really matter.
Anyway the compatible is just to uniquely identify the device for users,
not represent some programming model, because there is no programming
model of a board.
>
>> What is 9131 and 9132?
> I have no idea who came up with 9131 and 9132.
> But explanation is given by Grzegorz Jaszczyk <jaz@semihalf.com>
> when he submitted cn9131-db.dts (Marvell evaluation board):
>
> Extend the support of the CN9130 by adding an external CP115.
> The last number indicates how many external CP115 are used.
You use the compatibles in your patchset, so you should know, not me. I
have zero knowledge, also actually almost zero interest, in learning
your particular platform. I tried to fixup some bindings and maintainers
for Marvell: failed with not really helpful comments. Therefore I don't
care anymore about Marvell.
You or your platform maintainers should know what is this about and come
with explanation to the community.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH v16 01/22] dt-bindings: PCI: Add PLDA XpressRICH PCIe host common properties
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Add PLDA XpressRICH PCIe host common properties dt-binding doc.
PolarFire PCIe host using PLDA IP. Move common properties from Microchip
PolarFire PCIe host to PLDA files.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Tested-by: John Clark <inindev@gmail.com>
---
.../bindings/pci/microchip,pcie-host.yaml | 55 +-------------
.../pci/plda,xpressrich3-axi-common.yaml | 75 +++++++++++++++++++
MAINTAINERS | 6 ++
3 files changed, 82 insertions(+), 54 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
diff --git a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
index f7a3c2636355..7c2d51221f65 100644
--- a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
+++ b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
@@ -10,21 +10,13 @@ maintainers:
- Daire McNamara <daire.mcnamara@microchip.com>
allOf:
- - $ref: /schemas/pci/pci-bus.yaml#
+ - $ref: plda,xpressrich3-axi-common.yaml#
- $ref: /schemas/interrupt-controller/msi-controller.yaml#
properties:
compatible:
const: microchip,pcie-host-1.0 # PolarFire
- reg:
- maxItems: 2
-
- reg-names:
- items:
- - const: cfg
- - const: apb
-
clocks:
description:
Fabric Interface Controllers, FICs, are the interface between the FPGA
@@ -52,18 +44,6 @@ properties:
items:
pattern: '^fic[0-3]$'
- interrupts:
- minItems: 1
- items:
- - description: PCIe host controller
- - description: builtin MSI controller
-
- interrupt-names:
- minItems: 1
- items:
- - const: pcie
- - const: msi
-
ranges:
maxItems: 1
@@ -71,39 +51,6 @@ properties:
minItems: 1
maxItems: 6
- msi-controller:
- description: Identifies the node as an MSI controller.
-
- msi-parent:
- description: MSI controller the device is capable of using.
-
- interrupt-controller:
- type: object
- properties:
- '#address-cells':
- const: 0
-
- '#interrupt-cells':
- const: 1
-
- interrupt-controller: true
-
- required:
- - '#address-cells'
- - '#interrupt-cells'
- - interrupt-controller
-
- additionalProperties: false
-
-required:
- - reg
- - reg-names
- - "#interrupt-cells"
- - interrupts
- - interrupt-map-mask
- - interrupt-map
- - msi-controller
-
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
new file mode 100644
index 000000000000..31bb17b11e58
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/plda,xpressrich3-axi-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: PLDA XpressRICH PCIe host common properties
+
+maintainers:
+ - Daire McNamara <daire.mcnamara@microchip.com>
+ - Kevin Xie <kevin.xie@starfivetech.com>
+
+description:
+ Generic PLDA XpressRICH PCIe host common properties.
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+ reg:
+ maxItems: 2
+
+ reg-names:
+ items:
+ - const: cfg
+ - const: apb
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: PCIe host controller
+ - description: builtin MSI controller
+
+ interrupt-names:
+ minItems: 1
+ items:
+ - const: pcie
+ - const: msi
+
+ msi-controller:
+ description: Identifies the node as an MSI controller.
+
+ msi-parent:
+ description: MSI controller the device is capable of using.
+
+ interrupt-controller:
+ type: object
+ properties:
+ '#address-cells':
+ const: 0
+
+ '#interrupt-cells':
+ const: 1
+
+ interrupt-controller: true
+
+ required:
+ - '#address-cells'
+ - '#interrupt-cells'
+ - interrupt-controller
+
+ additionalProperties: false
+
+required:
+ - reg
+ - reg-names
+ - interrupts
+ - msi-controller
+ - "#interrupt-cells"
+ - interrupt-map-mask
+ - interrupt-map
+
+additionalProperties: true
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index aa3b947fb080..06278f1db13f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16946,6 +16946,12 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
F: drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
+PCI DRIVER FOR PLDA PCIE IP
+M: Daire McNamara <daire.mcnamara@microchip.com>
+L: linux-pci@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
+
PCI DRIVER FOR RENESAS R-CAR
M: Marek Vasut <marek.vasut+renesas@gmail.com>
M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
--
2.17.1
^ permalink raw reply related
* [PATCH v16 00/22] Refactoring Microchip PCIe driver and add StarFive PCIe
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
This patchset final purpose is add PCIe driver for StarFive JH7110 SoC.
JH7110 using PLDA XpressRICH PCIe IP. Microchip PolarFire Using the
same IP and have commit their codes, which are mixed with PLDA
controller codes and Microchip platform codes.
For re-use the PLDA controller codes, I request refactoring microchip
codes, move PLDA common codes to PLDA files.
Desigware and Cadence is good example for refactoring codes.
----------------------------------------------------------
The refactoring patches total number is 16,(patch 1-16)
which do NOT contain changing logic of codes.
These patches just contain three type basic operations.
(rename, modify codes to support starfive platform, and moving to common file)
If these patched are all be reviewed. They can be accepted first.
Refactoring patches can be devided to different groups
1. (patch 1- 3 is the prepare work of refactoring)
patch1 is move PLDA XpressRICH PCIe host common properties dt-binding
docs from microchip,pcie-host.yaml
patch2 is move PolarFire codes to PLDA directory.
patch3 is move PLDA IP register macros to plda-pcie.h
2. (patch4 - 6 is processing and re-use PCIe host instance)
patch4 is add bridge_addr field to PCIe host instance.
patch5 is rename data structure in microchip codes.
patch6 is moving two data structures to head file
3. (patch 7 - 9 are for re-use two PCIe setup function)
patch7 is rename two setup functions in microchip codes, prepare to move
to common file.
patch8 is change the arguments of plda_pcie_setup_iomems()
patch9 is move the two setup functions to common file pcie-plda-host.c
4.(patch 10 - 16 are for re-use interupt processing codes)
patch10 is rename the IRQ related functions, prepare to move to
pcie-plda-host.c
patch 11 - 15 is modify the interrupt event codes, preparing for support starfive
and microchip two platforms.
patch16 is move IRQ related functions to pcie-plda-host.c
------------------------------------------------------------
The remainder patches (patch 17 -22) are not refactoring patch.
They are for adding StarFive codes and dont modify the microchip's
codes.
patch17 is Add event bitmap for mask unused/unimpementes interrupts
patch18 is Add host init/deinit functions.
patch19 is add StarFive JH7110 PCIe dt-binding doc.
patch20 is Add a PCIe delay time macro
patch21 is add StarFive JH7110 Soc PCIe driver code.
qurik).
patch22 is Starfive dts config
This patchset is base on v6.9-rc1
previous version:
v10:https://patchwork.kernel.org/project/linux-pci/cover/20231031115430.113586-1-minda.chen@starfivetech.com/
v11:https://patchwork.kernel.org/project/linux-pci/cover/20231115114912.71448-1-minda.chen@starfivetech.com/
v12:https://patchwork.kernel.org/project/linux-pci/cover/20231206105839.25805-1-minda.chen@starfivetech.com/
v13:https://patchwork.kernel.org/project/linux-pci/cover/20231214072839.2367-1-minda.chen@starfivetech.com/
v14:https://patchwork.kernel.org/project/linux-pci/cover/20240129005854.3554-1-minda.chen@starfivetech.com/
v15:https://patchwork.kernel.org/project/linux-pci/cover/20240227103522.80915-1-minda.chen@starfivetech.com/
change:
v16:
modify the patch 3 - 9 commit message. (follow Lorrenzo's review comments)
Update the MAINTAINER in correct patch.
Add more comments in Starfive pcie driver to explain the pcie setting.(patch 21)
Remove v15 patch 22. We will get the delay time errdata or find a correct fix method.
v15:
resend: rebase on v6.8-rc6
Add new patch 22.(A workaround to JH7110 PCIe quirk).
v14:
resend: correct some commit messages. base on v6.8-rc1
Add a new patch 17. Add interrupt eventmap to mask non-implemented or unused interrupt.
patch3: rename the PLDA interrupts macro name.
patch9: remove the redundant head file.
patch10,11: modify the commit message suggested by Lorrenzo.
patch12: modify the commit message.
patch14, 15: PLDA codes will handle DMA interrupts. Modify the commit message.
patch18 remove plda default events. This is implemented by vendor.
patch21 Add plda_event instance stf_pcie_event.
v13:
patch14: 1. Add plda_get_event() function. This can be compare with mc_get_event() easily and
track the codes changes in case in the future..
2. The host event_ops is directly set to plda host port.
3. Setting default host event_ops instead of checking event ops.
patch15:1. Add PLDA event irq_chip instead of event_domain_ops, The
event_domain_ops can be re-used.
2. The host event irq_chip is directly set to plda host port.
3. Add PLDA event irqchip ops codes.
4. Remove Conor's review tag due to whole patch have been changed.
patch16: Also move the new added PLDA event codes.
patch18: Add plda host init and deinit function only.
v12:
patch18: modify the commit message and add starfive review tag.
Add PCIE_RESET_CONFIG_DEVICE_WAIT_MS to patch 19.
patch21: Add disable runtime pm function in starfive_pcie_remove()
Add "depens on ARCH_STARFIVE || COMPILE_TEST" in Starfive PCie Kconfig
v11:
check and modify some commit messages again.
All the codes are the same with v10.
v10:
All the commit message set to fit in 75 columns.
All the codes fit in less than 80 colunms.
patch 14:
Commit message changes suggested by Conor.
patch 21:
Add 100 ms delay macro to pci.h
generic phy pointer related codes moving to pcie-starfive.c
This patch Change pcie-starfive only, bus_ops move to patch 16.
Some Codes changes suggested by Bjorn.
Kevin Xie (1):
PCI: Add PCIE_RESET_CONFIG_DEVICE_WAIT_MS waiting time value
Minda Chen (21):
dt-bindings: PCI: Add PLDA XpressRICH PCIe host common properties
PCI: microchip: Move pcie-microchip-host.c to plda directory
PCI: microchip: Move PLDA IP register macros to pcie-plda.h
PCI: microchip: Add bridge_addr field to struct mc_pcie
PCI: microchip: Rename two PCIe data structures
PCI: microchip: Move PCIe host data structures to plda-pcie.h
PCI: microchip: Rename two setup functions
PCI: microchip: Change the argument of plda_pcie_setup_iomems()
PCI: microchip: Move setup functions to pcie-plda-host.c
PCI: microchip: Rename interrupt related functions
PCI: microchip: Add num_events field to struct plda_pcie_rp
PCI: microchip: Add request_event_irq() callback function
PCI: microchip: Add INTx and MSI event num to struct plda_event
PCI: microchip: Add get_events() callback and add PLDA get_event()
PCI: microchip: Add event irqchip field to host port and add PLDA
irqchip
PCI: microchip: Move IRQ functions to pcie-plda-host.c
PCI: plda: Add event bitmap field to struct plda_pcie_rp
PCI: plda: Add host init/deinit and map bus functions
dt-bindings: PCI: Add StarFive JH7110 PCIe controller
PCI: starfive: Add JH7110 PCIe controller
riscv: dts: starfive: add PCIe dts configuration for JH7110
.../bindings/pci/microchip,pcie-host.yaml | 55 +-
.../pci/plda,xpressrich3-axi-common.yaml | 75 ++
.../bindings/pci/starfive,jh7110-pcie.yaml | 120 ++++
MAINTAINERS | 19 +-
.../jh7110-starfive-visionfive-2.dtsi | 64 ++
arch/riscv/boot/dts/starfive/jh7110.dtsi | 86 +++
drivers/pci/controller/Kconfig | 9 +-
drivers/pci/controller/Makefile | 2 +-
drivers/pci/controller/plda/Kconfig | 30 +
drivers/pci/controller/plda/Makefile | 4 +
.../{ => plda}/pcie-microchip-host.c | 615 ++---------------
drivers/pci/controller/plda/pcie-plda-host.c | 651 ++++++++++++++++++
drivers/pci/controller/plda/pcie-plda.h | 273 ++++++++
drivers/pci/controller/plda/pcie-starfive.c | 488 +++++++++++++
drivers/pci/pci.h | 16 +
15 files changed, 1891 insertions(+), 616 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
create mode 100644 Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
create mode 100644 drivers/pci/controller/plda/Kconfig
create mode 100644 drivers/pci/controller/plda/Makefile
rename drivers/pci/controller/{ => plda}/pcie-microchip-host.c (54%)
create mode 100644 drivers/pci/controller/plda/pcie-plda-host.c
create mode 100644 drivers/pci/controller/plda/pcie-plda.h
create mode 100644 drivers/pci/controller/plda/pcie-starfive.c
base-commit: 4cece764965020c22cff7665b18a012006359095
--
2.17.1
^ permalink raw reply
* [PATCH v16 08/22] PCI: microchip: Change the argument of plda_pcie_setup_iomems()
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
If other vendor do not select PCI_HOST_COMMON, the driver data is not
struct pci_host_bridge.
Move calling platform_get_drvdata() to mc_platform_init().
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 9b367927cd32..805870aed61d 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -876,11 +876,10 @@ static void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
}
-static int plda_pcie_setup_iomems(struct platform_device *pdev,
+static int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
struct plda_pcie_rp *port)
{
void __iomem *bridge_base_addr = port->bridge_addr;
- struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
struct resource_entry *entry;
u64 pci_addr;
u32 index = 1;
@@ -1018,6 +1017,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
{
struct device *dev = cfg->parent;
struct platform_device *pdev = to_platform_device(dev);
+ struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
void __iomem *bridge_base_addr =
port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
int ret;
@@ -1031,7 +1031,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
mc_pcie_enable_msi(port, cfg->win);
/* Configure non-config space outbound ranges */
- ret = plda_pcie_setup_iomems(pdev, &port->plda);
+ ret = plda_pcie_setup_iomems(bridge, &port->plda);
if (ret)
return ret;
--
2.17.1
^ permalink raw reply related
* [PATCH v16 09/22] PCI: microchip: Move setup functions to pcie-plda-host.c
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Move setup functions to common pcie-plda-host.c. So these two functions
can be re-used.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
MAINTAINERS | 1 +
drivers/pci/controller/plda/Kconfig | 4 +
drivers/pci/controller/plda/Makefile | 1 +
.../pci/controller/plda/pcie-microchip-host.c | 59 ---------------
drivers/pci/controller/plda/pcie-plda-host.c | 73 +++++++++++++++++++
drivers/pci/controller/plda/pcie-plda.h | 5 ++
6 files changed, 84 insertions(+), 59 deletions(-)
create mode 100644 drivers/pci/controller/plda/pcie-plda-host.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 1fa4d61291f9..d85d9db38efa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16951,6 +16951,7 @@ M: Daire McNamara <daire.mcnamara@microchip.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
+F: drivers/pci/controller/plda/pcie-plda-host.c
F: drivers/pci/controller/plda/pcie-plda.h
PCI DRIVER FOR RENESAS R-CAR
diff --git a/drivers/pci/controller/plda/Kconfig b/drivers/pci/controller/plda/Kconfig
index 5cb3be4fc98c..e54a82ee94f5 100644
--- a/drivers/pci/controller/plda/Kconfig
+++ b/drivers/pci/controller/plda/Kconfig
@@ -3,10 +3,14 @@
menu "PLDA-based PCIe controllers"
depends on PCI
+config PCIE_PLDA_HOST
+ bool
+
config PCIE_MICROCHIP_HOST
tristate "Microchip AXI PCIe controller"
depends on PCI_MSI && OF
select PCI_HOST_COMMON
+ select PCIE_PLDA_HOST
help
Say Y here if you want kernel to support the Microchip AXI PCIe
Host Bridge driver.
diff --git a/drivers/pci/controller/plda/Makefile b/drivers/pci/controller/plda/Makefile
index e1a265cbf91c..4340ab007f44 100644
--- a/drivers/pci/controller/plda/Makefile
+++ b/drivers/pci/controller/plda/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PCIE_PLDA_HOST) += pcie-plda-host.o
obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 805870aed61d..573ad31c578a 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -838,65 +838,6 @@ static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
return mc_allocate_msi_domains(port);
}
-static void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
- phys_addr_t axi_addr, phys_addr_t pci_addr,
- size_t size)
-{
- u32 atr_sz = ilog2(size) - 1;
- u32 val;
-
- if (index == 0)
- val = PCIE_CONFIG_INTERFACE;
- else
- val = PCIE_TX_RX_INTERFACE;
-
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_TRSL_PARAM);
-
- val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
- ATR_IMPL_ENABLE;
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_SRCADDR_PARAM);
-
- val = upper_32_bits(axi_addr);
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_SRC_ADDR);
-
- val = lower_32_bits(pci_addr);
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
-
- val = upper_32_bits(pci_addr);
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
-
- val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
- val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
- writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
- writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
-}
-
-static int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
- struct plda_pcie_rp *port)
-{
- void __iomem *bridge_base_addr = port->bridge_addr;
- struct resource_entry *entry;
- u64 pci_addr;
- u32 index = 1;
-
- resource_list_for_each_entry(entry, &bridge->windows) {
- if (resource_type(entry->res) == IORESOURCE_MEM) {
- pci_addr = entry->res->start - entry->offset;
- plda_pcie_setup_window(bridge_base_addr, index,
- entry->res->start, pci_addr,
- resource_size(entry->res));
- index++;
- }
- }
-
- return 0;
-}
-
static inline void mc_clear_secs(struct mc_pcie *port)
{
void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
new file mode 100644
index 000000000000..05ea68baebfb
--- /dev/null
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLDA PCIe XpressRich host controller driver
+ *
+ * Copyright (C) 2023 Microchip Co. Ltd
+ *
+ * Author: Daire McNamara <daire.mcnamara@microchip.com>
+ */
+
+#include <linux/pci-ecam.h>
+
+#include "pcie-plda.h"
+
+void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
+ phys_addr_t axi_addr, phys_addr_t pci_addr,
+ size_t size)
+{
+ u32 atr_sz = ilog2(size) - 1;
+ u32 val;
+
+ if (index == 0)
+ val = PCIE_CONFIG_INTERFACE;
+ else
+ val = PCIE_TX_RX_INTERFACE;
+
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_TRSL_PARAM);
+
+ val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
+ ATR_IMPL_ENABLE;
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_SRCADDR_PARAM);
+
+ val = upper_32_bits(axi_addr);
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_SRC_ADDR);
+
+ val = lower_32_bits(pci_addr);
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
+
+ val = upper_32_bits(pci_addr);
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
+
+ val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
+ val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
+ writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
+ writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
+}
+EXPORT_SYMBOL_GPL(plda_pcie_setup_window);
+
+int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
+ struct plda_pcie_rp *port)
+{
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ struct resource_entry *entry;
+ u64 pci_addr;
+ u32 index = 1;
+
+ resource_list_for_each_entry(entry, &bridge->windows) {
+ if (resource_type(entry->res) == IORESOURCE_MEM) {
+ pci_addr = entry->res->start - entry->offset;
+ plda_pcie_setup_window(bridge_base_addr, index,
+ entry->res->start, pci_addr,
+ resource_size(entry->res));
+ index++;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 9ca66916c609..e277a5452b5d 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -126,4 +126,9 @@ struct plda_pcie_rp {
void __iomem *bridge_addr;
};
+void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
+ phys_addr_t axi_addr, phys_addr_t pci_addr,
+ size_t size);
+int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
+ struct plda_pcie_rp *port);
#endif
--
2.17.1
^ permalink raw reply related
* [PATCH v16 03/22] PCI: microchip: Move PLDA IP register macros to pcie-plda.h
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Move PLDA PCIe host controller IP registers macros to pcie-plda.h,
including bridge registers and PLDA IRQ event number.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
MAINTAINERS | 1 +
.../pci/controller/plda/pcie-microchip-host.c | 108 +++---------------
drivers/pci/controller/plda/pcie-plda.h | 108 ++++++++++++++++++
3 files changed, 125 insertions(+), 92 deletions(-)
create mode 100644 drivers/pci/controller/plda/pcie-plda.h
diff --git a/MAINTAINERS b/MAINTAINERS
index dd158cc7b009..1fa4d61291f9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16951,6 +16951,7 @@ M: Daire McNamara <daire.mcnamara@microchip.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
+F: drivers/pci/controller/plda/pcie-plda.h
PCI DRIVER FOR RENESAS R-CAR
M: Marek Vasut <marek.vasut+renesas@gmail.com>
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index cb09a8137e25..d9030d550482 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include "../../pci.h"
+#include "pcie-plda.h"
/* Number of MSI IRQs */
#define MC_MAX_NUM_MSI_IRQS 32
@@ -30,84 +31,6 @@
#define MC_PCIE_BRIDGE_ADDR (MC_PCIE1_BRIDGE_ADDR)
#define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR)
-/* PCIe Bridge Phy Regs */
-#define PCIE_PCI_IRQ_DW0 0xa8
-#define MSIX_CAP_MASK BIT(31)
-#define NUM_MSI_MSGS_MASK GENMASK(6, 4)
-#define NUM_MSI_MSGS_SHIFT 4
-
-#define IMASK_LOCAL 0x180
-#define DMA_END_ENGINE_0_MASK 0x00000000u
-#define DMA_END_ENGINE_0_SHIFT 0
-#define DMA_END_ENGINE_1_MASK 0x00000000u
-#define DMA_END_ENGINE_1_SHIFT 1
-#define DMA_ERROR_ENGINE_0_MASK 0x00000100u
-#define DMA_ERROR_ENGINE_0_SHIFT 8
-#define DMA_ERROR_ENGINE_1_MASK 0x00000200u
-#define DMA_ERROR_ENGINE_1_SHIFT 9
-#define A_ATR_EVT_POST_ERR_MASK 0x00010000u
-#define A_ATR_EVT_POST_ERR_SHIFT 16
-#define A_ATR_EVT_FETCH_ERR_MASK 0x00020000u
-#define A_ATR_EVT_FETCH_ERR_SHIFT 17
-#define A_ATR_EVT_DISCARD_ERR_MASK 0x00040000u
-#define A_ATR_EVT_DISCARD_ERR_SHIFT 18
-#define A_ATR_EVT_DOORBELL_MASK 0x00000000u
-#define A_ATR_EVT_DOORBELL_SHIFT 19
-#define P_ATR_EVT_POST_ERR_MASK 0x00100000u
-#define P_ATR_EVT_POST_ERR_SHIFT 20
-#define P_ATR_EVT_FETCH_ERR_MASK 0x00200000u
-#define P_ATR_EVT_FETCH_ERR_SHIFT 21
-#define P_ATR_EVT_DISCARD_ERR_MASK 0x00400000u
-#define P_ATR_EVT_DISCARD_ERR_SHIFT 22
-#define P_ATR_EVT_DOORBELL_MASK 0x00000000u
-#define P_ATR_EVT_DOORBELL_SHIFT 23
-#define PM_MSI_INT_INTA_MASK 0x01000000u
-#define PM_MSI_INT_INTA_SHIFT 24
-#define PM_MSI_INT_INTB_MASK 0x02000000u
-#define PM_MSI_INT_INTB_SHIFT 25
-#define PM_MSI_INT_INTC_MASK 0x04000000u
-#define PM_MSI_INT_INTC_SHIFT 26
-#define PM_MSI_INT_INTD_MASK 0x08000000u
-#define PM_MSI_INT_INTD_SHIFT 27
-#define PM_MSI_INT_INTX_MASK 0x0f000000u
-#define PM_MSI_INT_INTX_SHIFT 24
-#define PM_MSI_INT_MSI_MASK 0x10000000u
-#define PM_MSI_INT_MSI_SHIFT 28
-#define PM_MSI_INT_AER_EVT_MASK 0x20000000u
-#define PM_MSI_INT_AER_EVT_SHIFT 29
-#define PM_MSI_INT_EVENTS_MASK 0x40000000u
-#define PM_MSI_INT_EVENTS_SHIFT 30
-#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u
-#define PM_MSI_INT_SYS_ERR_SHIFT 31
-#define NUM_LOCAL_EVENTS 15
-#define ISTATUS_LOCAL 0x184
-#define IMASK_HOST 0x188
-#define ISTATUS_HOST 0x18c
-#define IMSI_ADDR 0x190
-#define ISTATUS_MSI 0x194
-
-/* PCIe Master table init defines */
-#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u
-#define ATR0_PCIE_ATR_SIZE 0x25
-#define ATR0_PCIE_ATR_SIZE_SHIFT 1
-#define ATR0_PCIE_WIN0_SRC_ADDR 0x604u
-#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB 0x608u
-#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW 0x60cu
-#define ATR0_PCIE_WIN0_TRSL_PARAM 0x610u
-
-/* PCIe AXI slave table init defines */
-#define ATR0_AXI4_SLV0_SRCADDR_PARAM 0x800u
-#define ATR_SIZE_SHIFT 1
-#define ATR_IMPL_ENABLE 1
-#define ATR0_AXI4_SLV0_SRC_ADDR 0x804u
-#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB 0x808u
-#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW 0x80cu
-#define ATR0_AXI4_SLV0_TRSL_PARAM 0x810u
-#define PCIE_TX_RX_INTERFACE 0x00000000u
-#define PCIE_CONFIG_INTERFACE 0x00000001u
-
-#define ATR_ENTRY_SIZE 32
-
/* PCIe Controller Phy Regs */
#define SEC_ERROR_EVENT_CNT 0x20
#define DED_ERROR_EVENT_CNT 0x24
@@ -179,20 +102,21 @@
#define EVENT_LOCAL_DMA_END_ENGINE_1 12
#define EVENT_LOCAL_DMA_ERROR_ENGINE_0 13
#define EVENT_LOCAL_DMA_ERROR_ENGINE_1 14
-#define EVENT_LOCAL_A_ATR_EVT_POST_ERR 15
-#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR 16
-#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR 17
-#define EVENT_LOCAL_A_ATR_EVT_DOORBELL 18
-#define EVENT_LOCAL_P_ATR_EVT_POST_ERR 19
-#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR 20
-#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR 21
-#define EVENT_LOCAL_P_ATR_EVT_DOORBELL 22
-#define EVENT_LOCAL_PM_MSI_INT_INTX 23
-#define EVENT_LOCAL_PM_MSI_INT_MSI 24
-#define EVENT_LOCAL_PM_MSI_INT_AER_EVT 25
-#define EVENT_LOCAL_PM_MSI_INT_EVENTS 26
-#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR 27
-#define NUM_EVENTS 28
+#define NUM_MC_EVENTS 15
+#define EVENT_LOCAL_A_ATR_EVT_POST_ERR (NUM_MC_EVENTS + PLDA_AXI_POST_ERR)
+#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR (NUM_MC_EVENTS + PLDA_AXI_FETCH_ERR)
+#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR (NUM_MC_EVENTS + PLDA_AXI_DISCARD_ERR)
+#define EVENT_LOCAL_A_ATR_EVT_DOORBELL (NUM_MC_EVENTS + PLDA_AXI_DOORBELL)
+#define EVENT_LOCAL_P_ATR_EVT_POST_ERR (NUM_MC_EVENTS + PLDA_PCIE_POST_ERR)
+#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR (NUM_MC_EVENTS + PLDA_PCIE_FETCH_ERR)
+#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR (NUM_MC_EVENTS + PLDA_PCIE_DISCARD_ERR)
+#define EVENT_LOCAL_P_ATR_EVT_DOORBELL (NUM_MC_EVENTS + PLDA_PCIE_DOORBELL)
+#define EVENT_LOCAL_PM_MSI_INT_INTX (NUM_MC_EVENTS + PLDA_INTX)
+#define EVENT_LOCAL_PM_MSI_INT_MSI (NUM_MC_EVENTS + PLDA_MSI)
+#define EVENT_LOCAL_PM_MSI_INT_AER_EVT (NUM_MC_EVENTS + PLDA_AER_EVENT)
+#define EVENT_LOCAL_PM_MSI_INT_EVENTS (NUM_MC_EVENTS + PLDA_MISC_EVENTS)
+#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR (NUM_MC_EVENTS + PLDA_SYS_ERR)
+#define NUM_EVENTS (NUM_MC_EVENTS + PLDA_INT_EVENT_NUM)
#define PCIE_EVENT_CAUSE(x, s) \
[EVENT_PCIE_ ## x] = { __stringify(x), s }
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
new file mode 100644
index 000000000000..65e0f3b72184
--- /dev/null
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PLDA PCIe host controller driver
+ */
+
+#ifndef _PCIE_PLDA_H
+#define _PCIE_PLDA_H
+
+/* PCIe Bridge Phy Regs */
+#define PCIE_PCI_IRQ_DW0 0xa8
+#define MSIX_CAP_MASK BIT(31)
+#define NUM_MSI_MSGS_MASK GENMASK(6, 4)
+#define NUM_MSI_MSGS_SHIFT 4
+
+#define IMASK_LOCAL 0x180
+#define DMA_END_ENGINE_0_MASK 0x00000000u
+#define DMA_END_ENGINE_0_SHIFT 0
+#define DMA_END_ENGINE_1_MASK 0x00000000u
+#define DMA_END_ENGINE_1_SHIFT 1
+#define DMA_ERROR_ENGINE_0_MASK 0x00000100u
+#define DMA_ERROR_ENGINE_0_SHIFT 8
+#define DMA_ERROR_ENGINE_1_MASK 0x00000200u
+#define DMA_ERROR_ENGINE_1_SHIFT 9
+#define A_ATR_EVT_POST_ERR_MASK 0x00010000u
+#define A_ATR_EVT_POST_ERR_SHIFT 16
+#define A_ATR_EVT_FETCH_ERR_MASK 0x00020000u
+#define A_ATR_EVT_FETCH_ERR_SHIFT 17
+#define A_ATR_EVT_DISCARD_ERR_MASK 0x00040000u
+#define A_ATR_EVT_DISCARD_ERR_SHIFT 18
+#define A_ATR_EVT_DOORBELL_MASK 0x00000000u
+#define A_ATR_EVT_DOORBELL_SHIFT 19
+#define P_ATR_EVT_POST_ERR_MASK 0x00100000u
+#define P_ATR_EVT_POST_ERR_SHIFT 20
+#define P_ATR_EVT_FETCH_ERR_MASK 0x00200000u
+#define P_ATR_EVT_FETCH_ERR_SHIFT 21
+#define P_ATR_EVT_DISCARD_ERR_MASK 0x00400000u
+#define P_ATR_EVT_DISCARD_ERR_SHIFT 22
+#define P_ATR_EVT_DOORBELL_MASK 0x00000000u
+#define P_ATR_EVT_DOORBELL_SHIFT 23
+#define PM_MSI_INT_INTA_MASK 0x01000000u
+#define PM_MSI_INT_INTA_SHIFT 24
+#define PM_MSI_INT_INTB_MASK 0x02000000u
+#define PM_MSI_INT_INTB_SHIFT 25
+#define PM_MSI_INT_INTC_MASK 0x04000000u
+#define PM_MSI_INT_INTC_SHIFT 26
+#define PM_MSI_INT_INTD_MASK 0x08000000u
+#define PM_MSI_INT_INTD_SHIFT 27
+#define PM_MSI_INT_INTX_MASK 0x0f000000u
+#define PM_MSI_INT_INTX_SHIFT 24
+#define PM_MSI_INT_MSI_MASK 0x10000000u
+#define PM_MSI_INT_MSI_SHIFT 28
+#define PM_MSI_INT_AER_EVT_MASK 0x20000000u
+#define PM_MSI_INT_AER_EVT_SHIFT 29
+#define PM_MSI_INT_EVENTS_MASK 0x40000000u
+#define PM_MSI_INT_EVENTS_SHIFT 30
+#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u
+#define PM_MSI_INT_SYS_ERR_SHIFT 31
+#define NUM_LOCAL_EVENTS 15
+#define ISTATUS_LOCAL 0x184
+#define IMASK_HOST 0x188
+#define ISTATUS_HOST 0x18c
+#define IMSI_ADDR 0x190
+#define ISTATUS_MSI 0x194
+
+/* PCIe Master table init defines */
+#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u
+#define ATR0_PCIE_ATR_SIZE 0x25
+#define ATR0_PCIE_ATR_SIZE_SHIFT 1
+#define ATR0_PCIE_WIN0_SRC_ADDR 0x604u
+#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB 0x608u
+#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW 0x60cu
+#define ATR0_PCIE_WIN0_TRSL_PARAM 0x610u
+
+/* PCIe AXI slave table init defines */
+#define ATR0_AXI4_SLV0_SRCADDR_PARAM 0x800u
+#define ATR_SIZE_SHIFT 1
+#define ATR_IMPL_ENABLE 1
+#define ATR0_AXI4_SLV0_SRC_ADDR 0x804u
+#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB 0x808u
+#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW 0x80cu
+#define ATR0_AXI4_SLV0_TRSL_PARAM 0x810u
+#define PCIE_TX_RX_INTERFACE 0x00000000u
+#define PCIE_CONFIG_INTERFACE 0x00000001u
+
+#define ATR_ENTRY_SIZE 32
+
+enum plda_int_event {
+ PLDA_AXI_POST_ERR,
+ PLDA_AXI_FETCH_ERR,
+ PLDA_AXI_DISCARD_ERR,
+ PLDA_AXI_DOORBELL,
+ PLDA_PCIE_POST_ERR,
+ PLDA_PCIE_FETCH_ERR,
+ PLDA_PCIE_DISCARD_ERR,
+ PLDA_PCIE_DOORBELL,
+ PLDA_INTX,
+ PLDA_MSI,
+ PLDA_AER_EVENT,
+ PLDA_MISC_EVENTS,
+ PLDA_SYS_ERR,
+ PLDA_INT_EVENT_NUM
+};
+
+#define PLDA_NUM_DMA_EVENTS 16
+
+#define PLDA_MAX_EVENT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
+
+#endif
--
2.17.1
^ permalink raw reply related
* [PATCH v16 11/22] PCI: microchip: Add num_events field to struct plda_pcie_rp
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
The number of events is different across platforms. In order to share
interrupt processing code, add a variable that defines the number of
events so that it can be set per-platform instead of hardcoding it.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 8 +++++---
drivers/pci/controller/plda/pcie-plda.h | 1 +
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 18bc352db389..0a5cd8b214cd 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -653,7 +653,7 @@ static void plda_handle_event(struct irq_desc *desc)
events = mc_get_events(port);
- for_each_set_bit(bit, &events, NUM_EVENTS)
+ for_each_set_bit(bit, &events, port->num_events)
generic_handle_domain_irq(port->event_domain, bit);
chained_irq_exit(chip, desc);
@@ -816,7 +816,8 @@ static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
return -EINVAL;
}
- port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
+ port->event_domain = irq_domain_add_linear(pcie_intc_node,
+ port->num_events,
&plda_event_domain_ops,
port);
if (!port->event_domain) {
@@ -920,7 +921,7 @@ static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_r
if (irq < 0)
return -ENODEV;
- for (i = 0; i < NUM_EVENTS; i++) {
+ for (i = 0; i < port->num_events; i++) {
event_irq = irq_create_mapping(port->event_domain, i);
if (!event_irq) {
dev_err(dev, "failed to map hwirq %d\n", i);
@@ -1012,6 +1013,7 @@ static int mc_host_probe(struct platform_device *pdev)
bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
plda->bridge_addr = bridge_base_addr;
+ plda->num_events = NUM_EVENTS;
/* Allow enabling MSI by disabling MSI-X */
val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index e277a5452b5d..f7e900b395f8 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -124,6 +124,7 @@ struct plda_pcie_rp {
raw_spinlock_t lock;
struct plda_msi msi;
void __iomem *bridge_addr;
+ int num_events;
};
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
--
2.17.1
^ permalink raw reply related
* [PATCH v16 07/22] PCI: microchip: Rename two setup functions
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Rename two setup functions to plda prefix. Prepare to re-use these two
setup functions.
Since two setup functions names are similar, rename mc_pcie_setup_windows()
to plda_pcie_setup_iomems().
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 24 +++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index a554a56cc0e8..9b367927cd32 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -838,9 +838,9 @@ static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
return mc_allocate_msi_domains(port);
}
-static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
- phys_addr_t axi_addr, phys_addr_t pci_addr,
- size_t size)
+static void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
+ phys_addr_t axi_addr, phys_addr_t pci_addr,
+ size_t size)
{
u32 atr_sz = ilog2(size) - 1;
u32 val;
@@ -876,8 +876,8 @@ static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
}
-static int mc_pcie_setup_windows(struct platform_device *pdev,
- struct plda_pcie_rp *port)
+static int plda_pcie_setup_iomems(struct platform_device *pdev,
+ struct plda_pcie_rp *port)
{
void __iomem *bridge_base_addr = port->bridge_addr;
struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
@@ -888,9 +888,9 @@ static int mc_pcie_setup_windows(struct platform_device *pdev,
resource_list_for_each_entry(entry, &bridge->windows) {
if (resource_type(entry->res) == IORESOURCE_MEM) {
pci_addr = entry->res->start - entry->offset;
- mc_pcie_setup_window(bridge_base_addr, index,
- entry->res->start, pci_addr,
- resource_size(entry->res));
+ plda_pcie_setup_window(bridge_base_addr, index,
+ entry->res->start, pci_addr,
+ resource_size(entry->res));
index++;
}
}
@@ -1023,15 +1023,15 @@ static int mc_platform_init(struct pci_config_window *cfg)
int ret;
/* Configure address translation table 0 for PCIe config space */
- mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
- cfg->res.start,
- resource_size(&cfg->res));
+ plda_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
+ cfg->res.start,
+ resource_size(&cfg->res));
/* Need some fixups in config space */
mc_pcie_enable_msi(port, cfg->win);
/* Configure non-config space outbound ranges */
- ret = mc_pcie_setup_windows(pdev, &port->plda);
+ ret = plda_pcie_setup_iomems(pdev, &port->plda);
if (ret)
return ret;
--
2.17.1
^ permalink raw reply related
* [PATCH v16 10/22] PCI: microchip: Rename interrupt related functions
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Rename mc_* to plda_* for IRQ functions and related IRQ domain ops data
instances.
MSI, INTx interrupt code and IRQ init code are all can be re-used.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 109 +++++++++---------
1 file changed, 57 insertions(+), 52 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 573ad31c578a..18bc352db389 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -318,7 +318,7 @@ static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
}
-static void mc_handle_msi(struct irq_desc *desc)
+static void plda_handle_msi(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -346,7 +346,7 @@ static void mc_handle_msi(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
-static void mc_msi_bottom_irq_ack(struct irq_data *data)
+static void plda_msi_bottom_irq_ack(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -355,7 +355,7 @@ static void mc_msi_bottom_irq_ack(struct irq_data *data)
writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
}
-static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
phys_addr_t addr = port->msi.vector_phy;
@@ -368,21 +368,23 @@ static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
(int)data->hwirq, msg->address_hi, msg->address_lo);
}
-static int mc_msi_set_affinity(struct irq_data *irq_data,
- const struct cpumask *mask, bool force)
+static int plda_msi_set_affinity(struct irq_data *irq_data,
+ const struct cpumask *mask, bool force)
{
return -EINVAL;
}
-static struct irq_chip mc_msi_bottom_irq_chip = {
- .name = "Microchip MSI",
- .irq_ack = mc_msi_bottom_irq_ack,
- .irq_compose_msi_msg = mc_compose_msi_msg,
- .irq_set_affinity = mc_msi_set_affinity,
+static struct irq_chip plda_msi_bottom_irq_chip = {
+ .name = "PLDA MSI",
+ .irq_ack = plda_msi_bottom_irq_ack,
+ .irq_compose_msi_msg = plda_compose_msi_msg,
+ .irq_set_affinity = plda_msi_set_affinity,
};
-static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs, void *args)
+static int plda_irq_msi_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs,
+ void *args)
{
struct plda_pcie_rp *port = domain->host_data;
struct plda_msi *msi = &port->msi;
@@ -397,7 +399,7 @@ static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
set_bit(bit, msi->used);
- irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip,
+ irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
domain->host_data, handle_edge_irq, NULL, NULL);
mutex_unlock(&msi->lock);
@@ -405,8 +407,9 @@ static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
return 0;
}
-static void mc_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs)
+static void plda_irq_msi_domain_free(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs)
{
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
@@ -423,24 +426,24 @@ static void mc_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops msi_domain_ops = {
- .alloc = mc_irq_msi_domain_alloc,
- .free = mc_irq_msi_domain_free,
+ .alloc = plda_irq_msi_domain_alloc,
+ .free = plda_irq_msi_domain_free,
};
-static struct irq_chip mc_msi_irq_chip = {
- .name = "Microchip PCIe MSI",
+static struct irq_chip plda_msi_irq_chip = {
+ .name = "PLDA PCIe MSI",
.irq_ack = irq_chip_ack_parent,
.irq_mask = pci_msi_mask_irq,
.irq_unmask = pci_msi_unmask_irq,
};
-static struct msi_domain_info mc_msi_domain_info = {
+static struct msi_domain_info plda_msi_domain_info = {
.flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
MSI_FLAG_PCI_MSIX),
- .chip = &mc_msi_irq_chip,
+ .chip = &plda_msi_irq_chip,
};
-static int mc_allocate_msi_domains(struct plda_pcie_rp *port)
+static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
@@ -455,7 +458,8 @@ static int mc_allocate_msi_domains(struct plda_pcie_rp *port)
return -ENOMEM;
}
- msi->msi_domain = pci_msi_create_irq_domain(fwnode, &mc_msi_domain_info,
+ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
+ &plda_msi_domain_info,
msi->dev_domain);
if (!msi->msi_domain) {
dev_err(dev, "failed to create MSI domain\n");
@@ -466,7 +470,7 @@ static int mc_allocate_msi_domains(struct plda_pcie_rp *port)
return 0;
}
-static void mc_handle_intx(struct irq_desc *desc)
+static void plda_handle_intx(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -493,7 +497,7 @@ static void mc_handle_intx(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
-static void mc_ack_intx_irq(struct irq_data *data)
+static void plda_ack_intx_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -502,7 +506,7 @@ static void mc_ack_intx_irq(struct irq_data *data)
writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
}
-static void mc_mask_intx_irq(struct irq_data *data)
+static void plda_mask_intx_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -517,7 +521,7 @@ static void mc_mask_intx_irq(struct irq_data *data)
raw_spin_unlock_irqrestore(&port->lock, flags);
}
-static void mc_unmask_intx_irq(struct irq_data *data)
+static void plda_unmask_intx_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -532,24 +536,24 @@ static void mc_unmask_intx_irq(struct irq_data *data)
raw_spin_unlock_irqrestore(&port->lock, flags);
}
-static struct irq_chip mc_intx_irq_chip = {
- .name = "Microchip PCIe INTx",
- .irq_ack = mc_ack_intx_irq,
- .irq_mask = mc_mask_intx_irq,
- .irq_unmask = mc_unmask_intx_irq,
+static struct irq_chip plda_intx_irq_chip = {
+ .name = "PLDA PCIe INTx",
+ .irq_ack = plda_ack_intx_irq,
+ .irq_mask = plda_mask_intx_irq,
+ .irq_unmask = plda_unmask_intx_irq,
};
-static int mc_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
+static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
{
- irq_set_chip_and_handler(irq, &mc_intx_irq_chip, handle_level_irq);
+ irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
return 0;
}
static const struct irq_domain_ops intx_domain_ops = {
- .map = mc_pcie_intx_map,
+ .map = plda_pcie_intx_map,
};
static inline u32 reg_to_event(u32 reg, struct event_map field)
@@ -609,7 +613,7 @@ static u32 local_events(struct mc_pcie *port)
return val;
}
-static u32 get_events(struct plda_pcie_rp *port)
+static u32 mc_get_events(struct plda_pcie_rp *port)
{
struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
u32 events = 0;
@@ -638,7 +642,7 @@ static irqreturn_t mc_event_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void mc_handle_event(struct irq_desc *desc)
+static void plda_handle_event(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
unsigned long events;
@@ -647,7 +651,7 @@ static void mc_handle_event(struct irq_desc *desc)
chained_irq_enter(chip, desc);
- events = get_events(port);
+ events = mc_get_events(port);
for_each_set_bit(bit, &events, NUM_EVENTS)
generic_handle_domain_irq(port->event_domain, bit);
@@ -741,8 +745,8 @@ static struct irq_chip mc_event_irq_chip = {
.irq_unmask = mc_unmask_event_irq,
};
-static int mc_pcie_event_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
+static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
{
irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
@@ -750,8 +754,8 @@ static int mc_pcie_event_map(struct irq_domain *domain, unsigned int irq,
return 0;
}
-static const struct irq_domain_ops event_domain_ops = {
- .map = mc_pcie_event_map,
+static const struct irq_domain_ops plda_event_domain_ops = {
+ .map = plda_pcie_event_map,
};
static inline void mc_pcie_deinit_clk(void *data)
@@ -799,7 +803,7 @@ static int mc_pcie_init_clks(struct device *dev)
return 0;
}
-static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
+static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
struct device_node *node = dev->of_node;
@@ -813,7 +817,8 @@ static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
}
port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
- &event_domain_ops, port);
+ &plda_event_domain_ops,
+ port);
if (!port->event_domain) {
dev_err(dev, "failed to get event domain\n");
of_node_put(pcie_intc_node);
@@ -835,7 +840,7 @@ static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
of_node_put(pcie_intc_node);
raw_spin_lock_init(&port->lock);
- return mc_allocate_msi_domains(port);
+ return plda_allocate_msi_domains(port);
}
static inline void mc_clear_secs(struct mc_pcie *port)
@@ -898,14 +903,14 @@ static void mc_disable_interrupts(struct mc_pcie *port)
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
}
-static int mc_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
+static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
{
struct device *dev = &pdev->dev;
int irq;
int i, intx_irq, msi_irq, event_irq;
int ret;
- ret = mc_pcie_init_irq_domains(port);
+ ret = plda_pcie_init_irq_domains(port);
if (ret) {
dev_err(dev, "failed creating IRQ domains\n");
return ret;
@@ -938,7 +943,7 @@ static int mc_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp
}
/* Plug the INTx chained handler */
- irq_set_chained_handler_and_data(intx_irq, mc_handle_intx, port);
+ irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
msi_irq = irq_create_mapping(port->event_domain,
EVENT_LOCAL_PM_MSI_INT_MSI);
@@ -946,10 +951,10 @@ static int mc_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp
return -ENXIO;
/* Plug the MSI chained handler */
- irq_set_chained_handler_and_data(msi_irq, mc_handle_msi, port);
+ irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
/* Plug the main event chained handler */
- irq_set_chained_handler_and_data(irq, mc_handle_event, port);
+ irq_set_chained_handler_and_data(irq, plda_handle_event, port);
return 0;
}
@@ -977,7 +982,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
return ret;
/* Address translation is up; safe to enable interrupts */
- ret = mc_init_interrupts(pdev, &port->plda);
+ ret = plda_init_interrupts(pdev, &port->plda);
if (ret)
return ret;
--
2.17.1
^ permalink raw reply related
* [PATCH v16 12/22] PCI: microchip: Add request_event_irq() callback function
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
plda,xpressrich3-axi-common.yaml) showed, PLDA PCIe contains an interrupt
controller. Microchip Polarfire PCIe add some PCIe interrupts base on
PLDA interrupt controller.
Microchip Polarfire PCIe additional intrerrupts:
(defined in drivers/pci/controller/plda/pcie-microchip-host.c)
EVENT_PCIE_L2_EXIT
EVENT_PCIE_HOTRST_EXIT
EVENT_PCIE_DLUP_EXIT
EVENT_SEC_TX_RAM_SEC_ERR
EVENT_SEC_RX_RAM_SEC_ERR
....
Both code of request interrupts and mc_event_handler() contain
additional interrupts symbol names, these can not be re-used. So add a
new plda_event_handler() functions, which implements PLDA interrupt
defalt handler, add request_event_irq() callback function to compat
Microchip Polorfire PCIe additional interrupts.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 31 ++++++++++++++++---
drivers/pci/controller/plda/pcie-plda.h | 5 +++
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 0a5cd8b214cd..bf5ce33ee275 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -642,6 +642,11 @@ static irqreturn_t mc_event_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t plda_event_handler(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
static void plda_handle_event(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
@@ -803,6 +808,17 @@ static int mc_pcie_init_clks(struct device *dev)
return 0;
}
+static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq,
+ int event)
+{
+ return devm_request_irq(plda->dev, event_irq, mc_event_handler,
+ 0, event_cause[event].sym, plda);
+}
+
+static const struct plda_event mc_event = {
+ .request_event_irq = mc_request_event_irq,
+};
+
static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
@@ -904,7 +920,9 @@ static void mc_disable_interrupts(struct mc_pcie *port)
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
}
-static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
+static int plda_init_interrupts(struct platform_device *pdev,
+ struct plda_pcie_rp *port,
+ const struct plda_event *event)
{
struct device *dev = &pdev->dev;
int irq;
@@ -928,8 +946,13 @@ static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_r
return -ENXIO;
}
- ret = devm_request_irq(dev, event_irq, mc_event_handler,
- 0, event_cause[i].sym, port);
+ if (event->request_event_irq)
+ ret = event->request_event_irq(port, event_irq, i);
+ else
+ ret = devm_request_irq(dev, event_irq,
+ plda_event_handler,
+ 0, NULL, port);
+
if (ret) {
dev_err(dev, "failed to request IRQ %d\n", event_irq);
return ret;
@@ -983,7 +1006,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
return ret;
/* Address translation is up; safe to enable interrupts */
- ret = plda_init_interrupts(pdev, &port->plda);
+ ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
if (ret)
return ret;
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index f7e900b395f8..935686bba837 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -127,6 +127,11 @@ struct plda_pcie_rp {
int num_events;
};
+struct plda_event {
+ int (*request_event_irq)(struct plda_pcie_rp *pcie,
+ int event_irq, int event);
+};
+
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
phys_addr_t axi_addr, phys_addr_t pci_addr,
size_t size);
--
2.17.1
^ permalink raw reply related
* [PATCH v16 06/22] PCI: microchip: Move PCIe host data structures to plda-pcie.h
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Move the common data structures definition to head file becauce these two
data structures can be re-used.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 20 ------------------
drivers/pci/controller/plda/pcie-plda.h | 21 +++++++++++++++++++
2 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index df0736f688ce..a554a56cc0e8 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -21,9 +21,6 @@
#include "../../pci.h"
#include "pcie-plda.h"
-/* Number of MSI IRQs */
-#define PLDA_MAX_NUM_MSI_IRQS 32
-
/* PCIe Bridge Phy and Controller Phy offsets */
#define MC_PCIE1_BRIDGE_ADDR 0x00008000u
#define MC_PCIE1_CTRL_ADDR 0x0000a000u
@@ -179,23 +176,6 @@ struct event_map {
u32 event_bit;
};
-struct plda_msi {
- struct mutex lock; /* Protect used bitmap */
- struct irq_domain *msi_domain;
- struct irq_domain *dev_domain;
- u32 num_vectors;
- u64 vector_phy;
- DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
-};
-
-struct plda_pcie_rp {
- struct device *dev;
- struct irq_domain *intx_domain;
- struct irq_domain *event_domain;
- raw_spinlock_t lock;
- struct plda_msi msi;
- void __iomem *bridge_addr;
-};
struct mc_pcie {
struct plda_pcie_rp plda;
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 65e0f3b72184..9ca66916c609 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -6,6 +6,9 @@
#ifndef _PCIE_PLDA_H
#define _PCIE_PLDA_H
+/* Number of MSI IRQs */
+#define PLDA_MAX_NUM_MSI_IRQS 32
+
/* PCIe Bridge Phy Regs */
#define PCIE_PCI_IRQ_DW0 0xa8
#define MSIX_CAP_MASK BIT(31)
@@ -105,4 +108,22 @@ enum plda_int_event {
#define PLDA_MAX_EVENT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
+struct plda_msi {
+ struct mutex lock; /* Protect used bitmap */
+ struct irq_domain *msi_domain;
+ struct irq_domain *dev_domain;
+ u32 num_vectors;
+ u64 vector_phy;
+ DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
+};
+
+struct plda_pcie_rp {
+ struct device *dev;
+ struct irq_domain *intx_domain;
+ struct irq_domain *event_domain;
+ raw_spinlock_t lock;
+ struct plda_msi msi;
+ void __iomem *bridge_addr;
+};
+
#endif
--
2.17.1
^ permalink raw reply related
* [PATCH v16 13/22] PCI: microchip: Add INTx and MSI event num to struct plda_event
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
The INTx and MSI interrupt event num is different across platforms, so
add two event num fields in struct plda_event.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 6 ++++--
drivers/pci/controller/plda/pcie-plda.h | 2 ++
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index bf5ce33ee275..8a51d3aa7e88 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -817,6 +817,8 @@ static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq,
static const struct plda_event mc_event = {
.request_event_irq = mc_request_event_irq,
+ .intx_event = EVENT_LOCAL_PM_MSI_INT_INTX,
+ .msi_event = EVENT_LOCAL_PM_MSI_INT_MSI,
};
static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
@@ -960,7 +962,7 @@ static int plda_init_interrupts(struct platform_device *pdev,
}
intx_irq = irq_create_mapping(port->event_domain,
- EVENT_LOCAL_PM_MSI_INT_INTX);
+ event->intx_event);
if (!intx_irq) {
dev_err(dev, "failed to map INTx interrupt\n");
return -ENXIO;
@@ -970,7 +972,7 @@ static int plda_init_interrupts(struct platform_device *pdev,
irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
msi_irq = irq_create_mapping(port->event_domain,
- EVENT_LOCAL_PM_MSI_INT_MSI);
+ event->msi_event);
if (!msi_irq)
return -ENXIO;
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 935686bba837..89172ce18237 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -130,6 +130,8 @@ struct plda_pcie_rp {
struct plda_event {
int (*request_event_irq)(struct plda_pcie_rp *pcie,
int event_irq, int event);
+ int intx_event;
+ int msi_event;
};
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
--
2.17.1
^ permalink raw reply related
* [PATCH v16 14/22] PCI: microchip: Add get_events() callback and add PLDA get_event()
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
plda,xpressrich3-axi-common.yaml) showed, PLDA PCIe contains an interrupt
controller.
PolarFire implements its own PCIe interrupts, additional to the regular
PCIe interrupts, due to lack of an MSI controller, so the interrupt to
event number mapping is different to the PLDA regular interrupts,
necessitating a custom get_events() implementation.
Microchip Polarfire PCIe additional intrerrupts:
(defined in drivers/pci/controller/plda/pcie-microchip-host.c)
EVENT_PCIE_L2_EXIT
EVENT_PCIE_HOTRST_EXIT
EVENT_PCIE_DLUP_EXIT
EVENT_SEC_TX_RAM_SEC_ERR
EVENT_SEC_RX_RAM_SEC_ERR
....
plda_get_events() adds interrupt register to PLDA event num mapping codes.
All The PLDA interrupts can be seen in new added graph.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 35 ++++++++++++++++++-
drivers/pci/controller/plda/pcie-plda.h | 32 +++++++++++++++++
2 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 8a51d3aa7e88..b3df373a2141 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -626,6 +626,26 @@ static u32 mc_get_events(struct plda_pcie_rp *port)
return events;
}
+static u32 plda_get_events(struct plda_pcie_rp *port)
+{
+ u32 events, val, origin;
+
+ origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
+
+ /* MSI event and sys events */
+ val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT;
+ events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1);
+
+ /* INTx events */
+ if (origin & PM_MSI_INT_INTX_MASK)
+ events |= BIT(PM_MSI_INT_INTX_SHIFT);
+
+ /* remains are same with register */
+ events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0);
+
+ return events;
+}
+
static irqreturn_t mc_event_handler(int irq, void *dev_id)
{
struct plda_pcie_rp *port = dev_id;
@@ -656,7 +676,7 @@ static void plda_handle_event(struct irq_desc *desc)
chained_irq_enter(chip, desc);
- events = mc_get_events(port);
+ events = port->event_ops->get_events(port);
for_each_set_bit(bit, &events, port->num_events)
generic_handle_domain_irq(port->event_domain, bit);
@@ -750,6 +770,10 @@ static struct irq_chip mc_event_irq_chip = {
.irq_unmask = mc_unmask_event_irq,
};
+static const struct plda_event_ops plda_event_ops = {
+ .get_events = plda_get_events,
+};
+
static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq)
{
@@ -815,6 +839,10 @@ static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq,
0, event_cause[event].sym, plda);
}
+static const struct plda_event_ops mc_event_ops = {
+ .get_events = mc_get_events,
+};
+
static const struct plda_event mc_event = {
.request_event_irq = mc_request_event_irq,
.intx_event = EVENT_LOCAL_PM_MSI_INT_INTX,
@@ -931,6 +959,9 @@ static int plda_init_interrupts(struct platform_device *pdev,
int i, intx_irq, msi_irq, event_irq;
int ret;
+ if (!port->event_ops)
+ port->event_ops = &plda_event_ops;
+
ret = plda_pcie_init_irq_domains(port);
if (ret) {
dev_err(dev, "failed creating IRQ domains\n");
@@ -1007,6 +1038,8 @@ static int mc_platform_init(struct pci_config_window *cfg)
if (ret)
return ret;
+ port->plda.event_ops = &mc_event_ops;
+
/* Address translation is up; safe to enable interrupts */
ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
if (ret)
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 89172ce18237..e0e5e7cc8434 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -58,6 +58,7 @@
#define PM_MSI_INT_EVENTS_SHIFT 30
#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u
#define PM_MSI_INT_SYS_ERR_SHIFT 31
+#define SYS_AND_MSI_MASK GENMASK(31, 28)
#define NUM_LOCAL_EVENTS 15
#define ISTATUS_LOCAL 0x184
#define IMASK_HOST 0x188
@@ -108,6 +109,36 @@ enum plda_int_event {
#define PLDA_MAX_EVENT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
+/*
+ * PLDA interrupt register
+ *
+ * 31 27 23 15 7 0
+ * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
+ * |12|11|10|9| intx |7|6|5|4|3|2|1|0| DMA error | DMA end |
+ * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
+ * bit 0-7 DMA interrupt end : reserved for vendor implement
+ * bit 8-15 DMA error : reserved for vendor implement
+ * 0: AXI post error (PLDA_AXI_POST_ERR)
+ * 1: AXI fetch error (PLDA_AXI_FETCH_ERR)
+ * 2: AXI discard error (PLDA_AXI_DISCARD_ERR)
+ * 3: AXI doorbell (PLDA_PCIE_DOORBELL)
+ * 4: PCIe post error (PLDA_PCIE_POST_ERR)
+ * 5: PCIe fetch error (PLDA_PCIE_FETCH_ERR)
+ * 6: PCIe discard error (PLDA_PCIE_DISCARD_ERR)
+ * 7: PCIe doorbell (PLDA_PCIE_DOORBELL)
+ * 8: 4 INTx interruts (PLDA_INTX)
+ * 9: MSI interrupt (PLDA_MSI)
+ * 10: AER event (PLDA_AER_EVENT)
+ * 11: PM/LTR/Hotplug (PLDA_MISC_EVENTS)
+ * 12: System error (PLDA_SYS_ERR)
+ */
+
+struct plda_pcie_rp;
+
+struct plda_event_ops {
+ u32 (*get_events)(struct plda_pcie_rp *pcie);
+};
+
struct plda_msi {
struct mutex lock; /* Protect used bitmap */
struct irq_domain *msi_domain;
@@ -123,6 +154,7 @@ struct plda_pcie_rp {
struct irq_domain *event_domain;
raw_spinlock_t lock;
struct plda_msi msi;
+ const struct plda_event_ops *event_ops;
void __iomem *bridge_addr;
int num_events;
};
--
2.17.1
^ permalink raw reply related
* [PATCH v16 15/22] PCI: microchip: Add event irqchip field to host port and add PLDA irqchip
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
plda,xpressrich3-axi-common.yaml) showed, PLDA PCIe contains an interrupt
controller.
Microchip PolarFire PCIE event IRQs includes PLDA interrupts and
Polarfire additional interrupts. The interrupt irqchip ops includes
ack/mask/unmask interrupt ops, which will write correct registers.
Microchip Polarfire PCIe additional interrupts require to write Polarfire
SoC self-defined registers. So Microchip PCIe event irqchip ops can not
be re-used.
Microchip Polarfire PCIe additional intrerrupts:
(defined in drivers/pci/controller/plda/pcie-microchip-host.c)
EVENT_PCIE_L2_EXIT
EVENT_PCIE_HOTRST_EXIT
EVENT_PCIE_DLUP_EXIT
EVENT_SEC_TX_RAM_SEC_ERR
EVENT_SEC_RX_RAM_SEC_ERR
....
To support PLDA its own event IRQ process, implements PLDA irqchip ops and
add event irqchip field to struct pcie_plda_rp.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 66 ++++++++++++++++++-
drivers/pci/controller/plda/pcie-plda.h | 34 +++++-----
2 files changed, 84 insertions(+), 16 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index b3df373a2141..beaf5c27da84 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -770,6 +770,64 @@ static struct irq_chip mc_event_irq_chip = {
.irq_unmask = mc_unmask_event_irq,
};
+static u32 plda_hwirq_to_mask(int hwirq)
+{
+ u32 mask;
+
+ /* hwirq 23 - 0 are the same with register */
+ if (hwirq < EVENT_PM_MSI_INT_INTX)
+ mask = BIT(hwirq);
+ else if (hwirq == EVENT_PM_MSI_INT_INTX)
+ mask = PM_MSI_INT_INTX_MASK;
+ else
+ mask = BIT(hwirq + PCI_NUM_INTX - 1);
+
+ return mask;
+}
+
+static void plda_ack_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+
+ writel_relaxed(plda_hwirq_to_mask(data->hwirq),
+ port->bridge_addr + ISTATUS_LOCAL);
+}
+
+static void plda_mask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val &= ~mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static void plda_unmask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val |= mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static struct irq_chip plda_event_irq_chip = {
+ .name = "PLDA PCIe EVENT",
+ .irq_ack = plda_ack_event_irq,
+ .irq_mask = plda_mask_event_irq,
+ .irq_unmask = plda_unmask_event_irq,
+};
+
static const struct plda_event_ops plda_event_ops = {
.get_events = plda_get_events,
};
@@ -777,7 +835,9 @@ static const struct plda_event_ops plda_event_ops = {
static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq)
{
- irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
+ struct plda_pcie_rp *port = (void *)domain->host_data;
+
+ irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
return 0;
@@ -962,6 +1022,9 @@ static int plda_init_interrupts(struct platform_device *pdev,
if (!port->event_ops)
port->event_ops = &plda_event_ops;
+ if (!port->event_irq_chip)
+ port->event_irq_chip = &plda_event_irq_chip;
+
ret = plda_pcie_init_irq_domains(port);
if (ret) {
dev_err(dev, "failed creating IRQ domains\n");
@@ -1039,6 +1102,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
return ret;
port->plda.event_ops = &mc_event_ops;
+ port->plda.event_irq_chip = &mc_event_irq_chip;
/* Address translation is up; safe to enable interrupts */
ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index e0e5e7cc8434..0e5157eb3a32 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -107,6 +107,8 @@ enum plda_int_event {
#define PLDA_NUM_DMA_EVENTS 16
+#define EVENT_PM_MSI_INT_INTX (PLDA_NUM_DMA_EVENTS + PLDA_INTX)
+#define EVENT_PM_MSI_INT_MSI (PLDA_NUM_DMA_EVENTS + PLDA_MSI)
#define PLDA_MAX_EVENT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
/*
@@ -116,21 +118,22 @@ enum plda_int_event {
* +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
* |12|11|10|9| intx |7|6|5|4|3|2|1|0| DMA error | DMA end |
* +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
- * bit 0-7 DMA interrupt end : reserved for vendor implement
- * bit 8-15 DMA error : reserved for vendor implement
- * 0: AXI post error (PLDA_AXI_POST_ERR)
- * 1: AXI fetch error (PLDA_AXI_FETCH_ERR)
- * 2: AXI discard error (PLDA_AXI_DISCARD_ERR)
- * 3: AXI doorbell (PLDA_PCIE_DOORBELL)
- * 4: PCIe post error (PLDA_PCIE_POST_ERR)
- * 5: PCIe fetch error (PLDA_PCIE_FETCH_ERR)
- * 6: PCIe discard error (PLDA_PCIE_DISCARD_ERR)
- * 7: PCIe doorbell (PLDA_PCIE_DOORBELL)
- * 8: 4 INTx interruts (PLDA_INTX)
- * 9: MSI interrupt (PLDA_MSI)
- * 10: AER event (PLDA_AER_EVENT)
- * 11: PM/LTR/Hotplug (PLDA_MISC_EVENTS)
- * 12: System error (PLDA_SYS_ERR)
+ * event bit
+ * 0-7 (0-7) DMA interrupt end : reserved for vendor implement
+ * 8-15 (8-15) DMA error : reserved for vendor implement
+ * 16 (16) AXI post error (PLDA_AXI_POST_ERR)
+ * 17 (17) AXI fetch error (PLDA_AXI_FETCH_ERR)
+ * 18 (18) AXI discard error (PLDA_AXI_DISCARD_ERR)
+ * 19 (19) AXI doorbell (PLDA_PCIE_DOORBELL)
+ * 20 (20) PCIe post error (PLDA_PCIE_POST_ERR)
+ * 21 (21) PCIe fetch error (PLDA_PCIE_FETCH_ERR)
+ * 22 (22) PCIe discard error (PLDA_PCIE_DISCARD_ERR)
+ * 23 (23) PCIe doorbell (PLDA_PCIE_DOORBELL)
+ * 24 (27-24) INTx interruts (PLDA_INTX)
+ * 25 (28): MSI interrupt (PLDA_MSI)
+ * 26 (29): AER event (PLDA_AER_EVENT)
+ * 27 (30): PM/LTR/Hotplug (PLDA_MISC_EVENTS)
+ * 28 (31): System error (PLDA_SYS_ERR)
*/
struct plda_pcie_rp;
@@ -155,6 +158,7 @@ struct plda_pcie_rp {
raw_spinlock_t lock;
struct plda_msi msi;
const struct plda_event_ops *event_ops;
+ const struct irq_chip *event_irq_chip;
void __iomem *bridge_addr;
int num_events;
};
--
2.17.1
^ permalink raw reply related
* [PATCH v16 16/22] PCI: microchip: Move IRQ functions to pcie-plda-host.c
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Move IRQ related functions to common file pcie-plda-host.c
The re-use code including MSI, INTx, event interrupts and IRQ init
functions.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 467 -----------------
drivers/pci/controller/plda/pcie-plda-host.c | 473 ++++++++++++++++++
drivers/pci/controller/plda/pcie-plda.h | 3 +
3 files changed, 476 insertions(+), 467 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index beaf5c27da84..105964306b71 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -318,244 +318,6 @@ static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
}
-static void plda_handle_msi(struct irq_desc *desc)
-{
- struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct device *dev = port->dev;
- struct plda_msi *msi = &port->msi;
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long status;
- u32 bit;
- int ret;
-
- chained_irq_enter(chip, desc);
-
- status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
- if (status & PM_MSI_INT_MSI_MASK) {
- writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
- status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
- for_each_set_bit(bit, &status, msi->num_vectors) {
- ret = generic_handle_domain_irq(msi->dev_domain, bit);
- if (ret)
- dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
- bit);
- }
- }
-
- chained_irq_exit(chip, desc);
-}
-
-static void plda_msi_bottom_irq_ack(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- u32 bitpos = data->hwirq;
-
- writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
-}
-
-static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- phys_addr_t addr = port->msi.vector_phy;
-
- msg->address_lo = lower_32_bits(addr);
- msg->address_hi = upper_32_bits(addr);
- msg->data = data->hwirq;
-
- dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
- (int)data->hwirq, msg->address_hi, msg->address_lo);
-}
-
-static int plda_msi_set_affinity(struct irq_data *irq_data,
- const struct cpumask *mask, bool force)
-{
- return -EINVAL;
-}
-
-static struct irq_chip plda_msi_bottom_irq_chip = {
- .name = "PLDA MSI",
- .irq_ack = plda_msi_bottom_irq_ack,
- .irq_compose_msi_msg = plda_compose_msi_msg,
- .irq_set_affinity = plda_msi_set_affinity,
-};
-
-static int plda_irq_msi_domain_alloc(struct irq_domain *domain,
- unsigned int virq,
- unsigned int nr_irqs,
- void *args)
-{
- struct plda_pcie_rp *port = domain->host_data;
- struct plda_msi *msi = &port->msi;
- unsigned long bit;
-
- mutex_lock(&msi->lock);
- bit = find_first_zero_bit(msi->used, msi->num_vectors);
- if (bit >= msi->num_vectors) {
- mutex_unlock(&msi->lock);
- return -ENOSPC;
- }
-
- set_bit(bit, msi->used);
-
- irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
- domain->host_data, handle_edge_irq, NULL, NULL);
-
- mutex_unlock(&msi->lock);
-
- return 0;
-}
-
-static void plda_irq_msi_domain_free(struct irq_domain *domain,
- unsigned int virq,
- unsigned int nr_irqs)
-{
- struct irq_data *d = irq_domain_get_irq_data(domain, virq);
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
- struct plda_msi *msi = &port->msi;
-
- mutex_lock(&msi->lock);
-
- if (test_bit(d->hwirq, msi->used))
- __clear_bit(d->hwirq, msi->used);
- else
- dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
-
- mutex_unlock(&msi->lock);
-}
-
-static const struct irq_domain_ops msi_domain_ops = {
- .alloc = plda_irq_msi_domain_alloc,
- .free = plda_irq_msi_domain_free,
-};
-
-static struct irq_chip plda_msi_irq_chip = {
- .name = "PLDA PCIe MSI",
- .irq_ack = irq_chip_ack_parent,
- .irq_mask = pci_msi_mask_irq,
- .irq_unmask = pci_msi_unmask_irq,
-};
-
-static struct msi_domain_info plda_msi_domain_info = {
- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
- MSI_FLAG_PCI_MSIX),
- .chip = &plda_msi_irq_chip,
-};
-
-static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
-{
- struct device *dev = port->dev;
- struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
- struct plda_msi *msi = &port->msi;
-
- mutex_init(&port->msi.lock);
-
- msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
- &msi_domain_ops, port);
- if (!msi->dev_domain) {
- dev_err(dev, "failed to create IRQ domain\n");
- return -ENOMEM;
- }
-
- msi->msi_domain = pci_msi_create_irq_domain(fwnode,
- &plda_msi_domain_info,
- msi->dev_domain);
- if (!msi->msi_domain) {
- dev_err(dev, "failed to create MSI domain\n");
- irq_domain_remove(msi->dev_domain);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void plda_handle_intx(struct irq_desc *desc)
-{
- struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct device *dev = port->dev;
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long status;
- u32 bit;
- int ret;
-
- chained_irq_enter(chip, desc);
-
- status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
- if (status & PM_MSI_INT_INTX_MASK) {
- status &= PM_MSI_INT_INTX_MASK;
- status >>= PM_MSI_INT_INTX_SHIFT;
- for_each_set_bit(bit, &status, PCI_NUM_INTX) {
- ret = generic_handle_domain_irq(port->intx_domain, bit);
- if (ret)
- dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
- bit);
- }
- }
-
- chained_irq_exit(chip, desc);
-}
-
-static void plda_ack_intx_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-
- writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
-}
-
-static void plda_mask_intx_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long flags;
- u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
- u32 val;
-
- raw_spin_lock_irqsave(&port->lock, flags);
- val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
- val &= ~mask;
- writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
- raw_spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void plda_unmask_intx_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long flags;
- u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
- u32 val;
-
- raw_spin_lock_irqsave(&port->lock, flags);
- val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
- val |= mask;
- writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
- raw_spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static struct irq_chip plda_intx_irq_chip = {
- .name = "PLDA PCIe INTx",
- .irq_ack = plda_ack_intx_irq,
- .irq_mask = plda_mask_intx_irq,
- .irq_unmask = plda_unmask_intx_irq,
-};
-
-static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
- irq_set_chip_data(irq, domain->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops intx_domain_ops = {
- .map = plda_pcie_intx_map,
-};
-
static inline u32 reg_to_event(u32 reg, struct event_map field)
{
return (reg & field.reg_mask) ? BIT(field.event_bit) : 0;
@@ -626,26 +388,6 @@ static u32 mc_get_events(struct plda_pcie_rp *port)
return events;
}
-static u32 plda_get_events(struct plda_pcie_rp *port)
-{
- u32 events, val, origin;
-
- origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
-
- /* MSI event and sys events */
- val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT;
- events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1);
-
- /* INTx events */
- if (origin & PM_MSI_INT_INTX_MASK)
- events |= BIT(PM_MSI_INT_INTX_SHIFT);
-
- /* remains are same with register */
- events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0);
-
- return events;
-}
-
static irqreturn_t mc_event_handler(int irq, void *dev_id)
{
struct plda_pcie_rp *port = dev_id;
@@ -662,28 +404,6 @@ static irqreturn_t mc_event_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static irqreturn_t plda_event_handler(int irq, void *dev_id)
-{
- return IRQ_HANDLED;
-}
-
-static void plda_handle_event(struct irq_desc *desc)
-{
- struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
- unsigned long events;
- u32 bit;
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- chained_irq_enter(chip, desc);
-
- events = port->event_ops->get_events(port);
-
- for_each_set_bit(bit, &events, port->num_events)
- generic_handle_domain_irq(port->event_domain, bit);
-
- chained_irq_exit(chip, desc);
-}
-
static void mc_ack_event_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
@@ -770,83 +490,6 @@ static struct irq_chip mc_event_irq_chip = {
.irq_unmask = mc_unmask_event_irq,
};
-static u32 plda_hwirq_to_mask(int hwirq)
-{
- u32 mask;
-
- /* hwirq 23 - 0 are the same with register */
- if (hwirq < EVENT_PM_MSI_INT_INTX)
- mask = BIT(hwirq);
- else if (hwirq == EVENT_PM_MSI_INT_INTX)
- mask = PM_MSI_INT_INTX_MASK;
- else
- mask = BIT(hwirq + PCI_NUM_INTX - 1);
-
- return mask;
-}
-
-static void plda_ack_event_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-
- writel_relaxed(plda_hwirq_to_mask(data->hwirq),
- port->bridge_addr + ISTATUS_LOCAL);
-}
-
-static void plda_mask_event_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- u32 mask, val;
-
- mask = plda_hwirq_to_mask(data->hwirq);
-
- raw_spin_lock(&port->lock);
- val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
- val &= ~mask;
- writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
- raw_spin_unlock(&port->lock);
-}
-
-static void plda_unmask_event_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- u32 mask, val;
-
- mask = plda_hwirq_to_mask(data->hwirq);
-
- raw_spin_lock(&port->lock);
- val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
- val |= mask;
- writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
- raw_spin_unlock(&port->lock);
-}
-
-static struct irq_chip plda_event_irq_chip = {
- .name = "PLDA PCIe EVENT",
- .irq_ack = plda_ack_event_irq,
- .irq_mask = plda_mask_event_irq,
- .irq_unmask = plda_unmask_event_irq,
-};
-
-static const struct plda_event_ops plda_event_ops = {
- .get_events = plda_get_events,
-};
-
-static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- struct plda_pcie_rp *port = (void *)domain->host_data;
-
- irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq);
- irq_set_chip_data(irq, domain->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops plda_event_domain_ops = {
- .map = plda_pcie_event_map,
-};
-
static inline void mc_pcie_deinit_clk(void *data)
{
struct clk *clk = data;
@@ -909,47 +552,6 @@ static const struct plda_event mc_event = {
.msi_event = EVENT_LOCAL_PM_MSI_INT_MSI,
};
-static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
-{
- struct device *dev = port->dev;
- struct device_node *node = dev->of_node;
- struct device_node *pcie_intc_node;
-
- /* Setup INTx */
- pcie_intc_node = of_get_next_child(node, NULL);
- if (!pcie_intc_node) {
- dev_err(dev, "failed to find PCIe Intc node\n");
- return -EINVAL;
- }
-
- port->event_domain = irq_domain_add_linear(pcie_intc_node,
- port->num_events,
- &plda_event_domain_ops,
- port);
- if (!port->event_domain) {
- dev_err(dev, "failed to get event domain\n");
- of_node_put(pcie_intc_node);
- return -ENOMEM;
- }
-
- irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
-
- port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
- &intx_domain_ops, port);
- if (!port->intx_domain) {
- dev_err(dev, "failed to get an INTx IRQ domain\n");
- of_node_put(pcie_intc_node);
- return -ENOMEM;
- }
-
- irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
-
- of_node_put(pcie_intc_node);
- raw_spin_lock_init(&port->lock);
-
- return plda_allocate_msi_domains(port);
-}
-
static inline void mc_clear_secs(struct mc_pcie *port)
{
void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
@@ -1010,75 +612,6 @@ static void mc_disable_interrupts(struct mc_pcie *port)
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
}
-static int plda_init_interrupts(struct platform_device *pdev,
- struct plda_pcie_rp *port,
- const struct plda_event *event)
-{
- struct device *dev = &pdev->dev;
- int irq;
- int i, intx_irq, msi_irq, event_irq;
- int ret;
-
- if (!port->event_ops)
- port->event_ops = &plda_event_ops;
-
- if (!port->event_irq_chip)
- port->event_irq_chip = &plda_event_irq_chip;
-
- ret = plda_pcie_init_irq_domains(port);
- if (ret) {
- dev_err(dev, "failed creating IRQ domains\n");
- return ret;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return -ENODEV;
-
- for (i = 0; i < port->num_events; i++) {
- event_irq = irq_create_mapping(port->event_domain, i);
- if (!event_irq) {
- dev_err(dev, "failed to map hwirq %d\n", i);
- return -ENXIO;
- }
-
- if (event->request_event_irq)
- ret = event->request_event_irq(port, event_irq, i);
- else
- ret = devm_request_irq(dev, event_irq,
- plda_event_handler,
- 0, NULL, port);
-
- if (ret) {
- dev_err(dev, "failed to request IRQ %d\n", event_irq);
- return ret;
- }
- }
-
- intx_irq = irq_create_mapping(port->event_domain,
- event->intx_event);
- if (!intx_irq) {
- dev_err(dev, "failed to map INTx interrupt\n");
- return -ENXIO;
- }
-
- /* Plug the INTx chained handler */
- irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
-
- msi_irq = irq_create_mapping(port->event_domain,
- event->msi_event);
- if (!msi_irq)
- return -ENXIO;
-
- /* Plug the MSI chained handler */
- irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
-
- /* Plug the main event chained handler */
- irq_set_chained_handler_and_data(irq, plda_handle_event, port);
-
- return 0;
-}
-
static int mc_platform_init(struct pci_config_window *cfg)
{
struct device *dev = cfg->parent;
diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
index 05ea68baebfb..98c51e594efe 100644
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -7,10 +7,483 @@
* Author: Daire McNamara <daire.mcnamara@microchip.com>
*/
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+#include <linux/pci_regs.h>
#include <linux/pci-ecam.h>
#include "pcie-plda.h"
+static void plda_handle_msi(struct irq_desc *desc)
+{
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct device *dev = port->dev;
+ struct plda_msi *msi = &port->msi;
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long status;
+ u32 bit;
+ int ret;
+
+ chained_irq_enter(chip, desc);
+
+ status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
+ if (status & PM_MSI_INT_MSI_MASK) {
+ writel_relaxed(status & PM_MSI_INT_MSI_MASK,
+ bridge_base_addr + ISTATUS_LOCAL);
+ status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
+ for_each_set_bit(bit, &status, msi->num_vectors) {
+ ret = generic_handle_domain_irq(msi->dev_domain, bit);
+ if (ret)
+ dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
+ bit);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void plda_msi_bottom_irq_ack(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ u32 bitpos = data->hwirq;
+
+ writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
+}
+
+static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ phys_addr_t addr = port->msi.vector_phy;
+
+ msg->address_lo = lower_32_bits(addr);
+ msg->address_hi = upper_32_bits(addr);
+ msg->data = data->hwirq;
+
+ dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
+ (int)data->hwirq, msg->address_hi, msg->address_lo);
+}
+
+static int plda_msi_set_affinity(struct irq_data *irq_data,
+ const struct cpumask *mask, bool force)
+{
+ return -EINVAL;
+}
+
+static struct irq_chip plda_msi_bottom_irq_chip = {
+ .name = "PLDA MSI",
+ .irq_ack = plda_msi_bottom_irq_ack,
+ .irq_compose_msi_msg = plda_compose_msi_msg,
+ .irq_set_affinity = plda_msi_set_affinity,
+};
+
+static int plda_irq_msi_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs,
+ void *args)
+{
+ struct plda_pcie_rp *port = domain->host_data;
+ struct plda_msi *msi = &port->msi;
+ unsigned long bit;
+
+ mutex_lock(&msi->lock);
+ bit = find_first_zero_bit(msi->used, msi->num_vectors);
+ if (bit >= msi->num_vectors) {
+ mutex_unlock(&msi->lock);
+ return -ENOSPC;
+ }
+
+ set_bit(bit, msi->used);
+
+ irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
+ domain->host_data, handle_edge_irq, NULL, NULL);
+
+ mutex_unlock(&msi->lock);
+
+ return 0;
+}
+
+static void plda_irq_msi_domain_free(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
+ struct plda_msi *msi = &port->msi;
+
+ mutex_lock(&msi->lock);
+
+ if (test_bit(d->hwirq, msi->used))
+ __clear_bit(d->hwirq, msi->used);
+ else
+ dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
+
+ mutex_unlock(&msi->lock);
+}
+
+static const struct irq_domain_ops msi_domain_ops = {
+ .alloc = plda_irq_msi_domain_alloc,
+ .free = plda_irq_msi_domain_free,
+};
+
+static struct irq_chip plda_msi_irq_chip = {
+ .name = "PLDA PCIe MSI",
+ .irq_ack = irq_chip_ack_parent,
+ .irq_mask = pci_msi_mask_irq,
+ .irq_unmask = pci_msi_unmask_irq,
+};
+
+static struct msi_domain_info plda_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_PCI_MSIX),
+ .chip = &plda_msi_irq_chip,
+};
+
+static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
+{
+ struct device *dev = port->dev;
+ struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
+ struct plda_msi *msi = &port->msi;
+
+ mutex_init(&port->msi.lock);
+
+ msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
+ &msi_domain_ops, port);
+ if (!msi->dev_domain) {
+ dev_err(dev, "failed to create IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
+ &plda_msi_domain_info,
+ msi->dev_domain);
+ if (!msi->msi_domain) {
+ dev_err(dev, "failed to create MSI domain\n");
+ irq_domain_remove(msi->dev_domain);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void plda_handle_intx(struct irq_desc *desc)
+{
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct device *dev = port->dev;
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long status;
+ u32 bit;
+ int ret;
+
+ chained_irq_enter(chip, desc);
+
+ status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
+ if (status & PM_MSI_INT_INTX_MASK) {
+ status &= PM_MSI_INT_INTX_MASK;
+ status >>= PM_MSI_INT_INTX_SHIFT;
+ for_each_set_bit(bit, &status, PCI_NUM_INTX) {
+ ret = generic_handle_domain_irq(port->intx_domain, bit);
+ if (ret)
+ dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
+ bit);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void plda_ack_intx_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
+
+ writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
+}
+
+static void plda_mask_intx_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long flags;
+ u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
+ u32 val;
+
+ raw_spin_lock_irqsave(&port->lock, flags);
+ val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
+ val &= ~mask;
+ writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
+ raw_spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void plda_unmask_intx_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long flags;
+ u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
+ u32 val;
+
+ raw_spin_lock_irqsave(&port->lock, flags);
+ val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
+ val |= mask;
+ writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
+ raw_spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static struct irq_chip plda_intx_irq_chip = {
+ .name = "PLDA PCIe INTx",
+ .irq_ack = plda_ack_intx_irq,
+ .irq_mask = plda_mask_intx_irq,
+ .irq_unmask = plda_unmask_intx_irq,
+};
+
+static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+ .map = plda_pcie_intx_map,
+};
+
+static u32 plda_get_events(struct plda_pcie_rp *port)
+{
+ u32 events, val, origin;
+
+ origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
+
+ /* MSI event and sys events */
+ val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT;
+ events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1);
+
+ /* INTx events */
+ if (origin & PM_MSI_INT_INTX_MASK)
+ events |= BIT(PM_MSI_INT_INTX_SHIFT);
+
+ /* remains are same with register */
+ events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0);
+
+ return events;
+}
+
+static irqreturn_t plda_event_handler(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+static void plda_handle_event(struct irq_desc *desc)
+{
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
+ unsigned long events;
+ u32 bit;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
+
+ events = port->event_ops->get_events(port);
+
+ for_each_set_bit(bit, &events, port->num_events)
+ generic_handle_domain_irq(port->event_domain, bit);
+
+ chained_irq_exit(chip, desc);
+}
+
+static u32 plda_hwirq_to_mask(int hwirq)
+{
+ u32 mask;
+
+ /* hwirq 23 - 0 are the same with register */
+ if (hwirq < EVENT_PM_MSI_INT_INTX)
+ mask = BIT(hwirq);
+ else if (hwirq == EVENT_PM_MSI_INT_INTX)
+ mask = PM_MSI_INT_INTX_MASK;
+ else
+ mask = BIT(hwirq + PCI_NUM_INTX - 1);
+
+ return mask;
+}
+
+static void plda_ack_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+
+ writel_relaxed(plda_hwirq_to_mask(data->hwirq),
+ port->bridge_addr + ISTATUS_LOCAL);
+}
+
+static void plda_mask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val &= ~mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static void plda_unmask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val |= mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static struct irq_chip plda_event_irq_chip = {
+ .name = "PLDA PCIe EVENT",
+ .irq_ack = plda_ack_event_irq,
+ .irq_mask = plda_mask_event_irq,
+ .irq_unmask = plda_unmask_event_irq,
+};
+
+static const struct plda_event_ops plda_event_ops = {
+ .get_events = plda_get_events,
+};
+
+static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct plda_pcie_rp *port = (void *)domain->host_data;
+
+ irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops plda_event_domain_ops = {
+ .map = plda_pcie_event_map,
+};
+
+static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
+{
+ struct device *dev = port->dev;
+ struct device_node *node = dev->of_node;
+ struct device_node *pcie_intc_node;
+
+ /* Setup INTx */
+ pcie_intc_node = of_get_next_child(node, NULL);
+ if (!pcie_intc_node) {
+ dev_err(dev, "failed to find PCIe Intc node\n");
+ return -EINVAL;
+ }
+
+ port->event_domain = irq_domain_add_linear(pcie_intc_node,
+ port->num_events,
+ &plda_event_domain_ops,
+ port);
+ if (!port->event_domain) {
+ dev_err(dev, "failed to get event domain\n");
+ of_node_put(pcie_intc_node);
+ return -ENOMEM;
+ }
+
+ irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
+
+ port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+ &intx_domain_ops, port);
+ if (!port->intx_domain) {
+ dev_err(dev, "failed to get an INTx IRQ domain\n");
+ of_node_put(pcie_intc_node);
+ return -ENOMEM;
+ }
+
+ irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
+
+ of_node_put(pcie_intc_node);
+ raw_spin_lock_init(&port->lock);
+
+ return plda_allocate_msi_domains(port);
+}
+
+int plda_init_interrupts(struct platform_device *pdev,
+ struct plda_pcie_rp *port,
+ const struct plda_event *event)
+{
+ struct device *dev = &pdev->dev;
+ int irq;
+ int i, intx_irq, msi_irq, event_irq;
+ int ret;
+
+ if (!port->event_ops)
+ port->event_ops = &plda_event_ops;
+
+ if (!port->event_irq_chip)
+ port->event_irq_chip = &plda_event_irq_chip;
+
+ ret = plda_pcie_init_irq_domains(port);
+ if (ret) {
+ dev_err(dev, "failed creating IRQ domains\n");
+ return ret;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENODEV;
+
+ for (i = 0; i < port->num_events; i++) {
+ event_irq = irq_create_mapping(port->event_domain, i);
+ if (!event_irq) {
+ dev_err(dev, "failed to map hwirq %d\n", i);
+ return -ENXIO;
+ }
+
+ if (event->request_event_irq)
+ ret = event->request_event_irq(port, event_irq, i);
+ else
+ ret = devm_request_irq(dev, event_irq,
+ plda_event_handler,
+ 0, NULL, port);
+
+ if (ret) {
+ dev_err(dev, "failed to request IRQ %d\n", event_irq);
+ return ret;
+ }
+ }
+
+ intx_irq = irq_create_mapping(port->event_domain,
+ event->intx_event);
+ if (!intx_irq) {
+ dev_err(dev, "failed to map INTx interrupt\n");
+ return -ENXIO;
+ }
+
+ /* Plug the INTx chained handler */
+ irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
+
+ msi_irq = irq_create_mapping(port->event_domain,
+ event->msi_event);
+ if (!msi_irq)
+ return -ENXIO;
+
+ /* Plug the MSI chained handler */
+ irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
+
+ /* Plug the main event chained handler */
+ irq_set_chained_handler_and_data(irq, plda_handle_event, port);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(plda_init_interrupts);
+
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
phys_addr_t axi_addr, phys_addr_t pci_addr,
size_t size)
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 0e5157eb3a32..eb9e6f304985 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -170,6 +170,9 @@ struct plda_event {
int msi_event;
};
+int plda_init_interrupts(struct platform_device *pdev,
+ struct plda_pcie_rp *port,
+ const struct plda_event *event);
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
phys_addr_t axi_addr, phys_addr_t pci_addr,
size_t size);
--
2.17.1
^ permalink raw reply related
* [PATCH v16 17/22] PCI: plda: Add event bitmap field to struct plda_pcie_rp
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
PLDA DMA interrupts are not all implemented, The non-implemented
interrupts should be masked. So add a bitmap field to mask the non-
implemented interrupts.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 1 +
drivers/pci/controller/plda/pcie-plda-host.c | 6 ++++--
drivers/pci/controller/plda/pcie-plda.h | 1 +
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 105964306b71..48f60a04b740 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -636,6 +636,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
port->plda.event_ops = &mc_event_ops;
port->plda.event_irq_chip = &mc_event_irq_chip;
+ port->plda.events_bitmap = GENMASK(NUM_EVENTS - 1, 0);
/* Address translation is up; safe to enable interrupts */
ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
index 98c51e594efe..a040e7e5492f 100644
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -290,6 +290,7 @@ static void plda_handle_event(struct irq_desc *desc)
events = port->event_ops->get_events(port);
+ events &= port->events_bitmap;
for_each_set_bit(bit, &events, port->num_events)
generic_handle_domain_irq(port->event_domain, bit);
@@ -420,8 +421,9 @@ int plda_init_interrupts(struct platform_device *pdev,
{
struct device *dev = &pdev->dev;
int irq;
- int i, intx_irq, msi_irq, event_irq;
+ int intx_irq, msi_irq, event_irq;
int ret;
+ u32 i;
if (!port->event_ops)
port->event_ops = &plda_event_ops;
@@ -439,7 +441,7 @@ int plda_init_interrupts(struct platform_device *pdev,
if (irq < 0)
return -ENODEV;
- for (i = 0; i < port->num_events; i++) {
+ for_each_set_bit(i, &port->events_bitmap, port->num_events) {
event_irq = irq_create_mapping(port->event_domain, i);
if (!event_irq) {
dev_err(dev, "failed to map hwirq %d\n", i);
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index eb9e6f304985..c3d8c141e44d 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -160,6 +160,7 @@ struct plda_pcie_rp {
const struct plda_event_ops *event_ops;
const struct irq_chip *event_irq_chip;
void __iomem *bridge_addr;
+ unsigned long events_bitmap;
int num_events;
};
--
2.17.1
^ permalink raw reply related
* [PATCH v16 18/22] PCI: plda: Add host init/deinit and map bus functions
From: Minda Chen @ 2024-03-28 9:18 UTC (permalink / raw)
To: Lorenzo Pieralisi, Conor Dooley, Krzysztof Wilczyński,
Rob Herring, Bjorn Helgaas, Thomas Gleixner, Daire McNamara,
Emil Renner Berthing, Krzysztof Kozlowski
Cc: devicetree, linux-kernel, linux-riscv, linux-pci, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Philipp Zabel, Mason Huo, Leyfoon Tan,
Kevin Xie, Minda Chen
In-Reply-To: <20240328091835.14797-1-minda.chen@starfivetech.com>
Add PLDA host plda_pcie_host_init()/plda_pcie_host_deinit() and map bus
function. So vendor can use it to init PLDA PCIe host core.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Mason Huo <mason.huo@starfivetech.com>
---
drivers/pci/controller/plda/pcie-plda-host.c | 131 +++++++++++++++++--
drivers/pci/controller/plda/pcie-plda.h | 22 ++++
2 files changed, 139 insertions(+), 14 deletions(-)
diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
index a040e7e5492f..a18923d7cea6 100644
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -3,6 +3,7 @@
* PLDA PCIe XpressRich host controller driver
*
* Copyright (C) 2023 Microchip Co. Ltd
+ * StarFive Co. Ltd
*
* Author: Daire McNamara <daire.mcnamara@microchip.com>
*/
@@ -15,6 +16,15 @@
#include "pcie-plda.h"
+void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+ int where)
+{
+ struct plda_pcie_rp *pcie = bus->sysdata;
+
+ return pcie->config_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
+}
+EXPORT_SYMBOL_GPL(plda_pcie_map_bus);
+
static void plda_handle_msi(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
@@ -420,9 +430,7 @@ int plda_init_interrupts(struct platform_device *pdev,
const struct plda_event *event)
{
struct device *dev = &pdev->dev;
- int irq;
- int intx_irq, msi_irq, event_irq;
- int ret;
+ int event_irq, ret;
u32 i;
if (!port->event_ops)
@@ -437,8 +445,8 @@ int plda_init_interrupts(struct platform_device *pdev,
return ret;
}
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
+ port->irq = platform_get_irq(pdev, 0);
+ if (port->irq < 0)
return -ENODEV;
for_each_set_bit(i, &port->events_bitmap, port->num_events) {
@@ -461,26 +469,26 @@ int plda_init_interrupts(struct platform_device *pdev,
}
}
- intx_irq = irq_create_mapping(port->event_domain,
- event->intx_event);
- if (!intx_irq) {
+ port->intx_irq = irq_create_mapping(port->event_domain,
+ event->intx_event);
+ if (!port->intx_irq) {
dev_err(dev, "failed to map INTx interrupt\n");
return -ENXIO;
}
/* Plug the INTx chained handler */
- irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
+ irq_set_chained_handler_and_data(port->intx_irq, plda_handle_intx, port);
- msi_irq = irq_create_mapping(port->event_domain,
- event->msi_event);
- if (!msi_irq)
+ port->msi_irq = irq_create_mapping(port->event_domain,
+ event->msi_event);
+ if (!port->msi_irq)
return -ENXIO;
/* Plug the MSI chained handler */
- irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
+ irq_set_chained_handler_and_data(port->msi_irq, plda_handle_msi, port);
/* Plug the main event chained handler */
- irq_set_chained_handler_and_data(irq, plda_handle_event, port);
+ irq_set_chained_handler_and_data(port->irq, plda_handle_event, port);
return 0;
}
@@ -546,3 +554,98 @@ int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
return 0;
}
EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
+
+static void plda_pcie_irq_domain_deinit(struct plda_pcie_rp *pcie)
+{
+ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
+ irq_set_chained_handler_and_data(pcie->msi_irq, NULL, NULL);
+ irq_set_chained_handler_and_data(pcie->intx_irq, NULL, NULL);
+
+ irq_domain_remove(pcie->msi.msi_domain);
+ irq_domain_remove(pcie->msi.dev_domain);
+
+ irq_domain_remove(pcie->intx_domain);
+ irq_domain_remove(pcie->event_domain);
+}
+
+int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
+ const struct plda_event *plda_event)
+{
+ struct device *dev = port->dev;
+ struct pci_host_bridge *bridge;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *cfg_res;
+ int ret;
+
+ pdev = to_platform_device(dev);
+
+ port->bridge_addr =
+ devm_platform_ioremap_resource_byname(pdev, "apb");
+
+ if (IS_ERR(port->bridge_addr))
+ return dev_err_probe(dev, PTR_ERR(port->bridge_addr),
+ "failed to map reg memory\n");
+
+ cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
+ if (!cfg_res)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get config memory\n");
+
+ port->config_base = devm_ioremap_resource(dev, cfg_res);
+ if (IS_ERR(port->config_base))
+ return dev_err_probe(dev, PTR_ERR(port->config_base),
+ "failed to map config memory\n");
+
+ bridge = devm_pci_alloc_host_bridge(dev, 0);
+ if (!bridge)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to alloc bridge\n");
+
+ if (port->host_ops && port->host_ops->host_init) {
+ ret = port->host_ops->host_init(port);
+ if (ret)
+ return ret;
+ }
+
+ port->bridge = bridge;
+ plda_pcie_setup_window(port->bridge_addr, 0, cfg_res->start, 0,
+ resource_size(cfg_res));
+ plda_pcie_setup_iomems(bridge, port);
+ plda_set_default_msi(&port->msi);
+ ret = plda_init_interrupts(pdev, port, plda_event);
+ if (ret)
+ goto err_host;
+
+ /* Set default bus ops */
+ bridge->ops = ops;
+ bridge->sysdata = port;
+
+ ret = pci_host_probe(bridge);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "failed to probe pci host\n");
+ goto err_probe;
+ }
+
+ return ret;
+
+err_probe:
+ plda_pcie_irq_domain_deinit(port);
+err_host:
+ if (port->host_ops && port->host_ops->host_deinit)
+ port->host_ops->host_deinit(port);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(plda_pcie_host_init);
+
+void plda_pcie_host_deinit(struct plda_pcie_rp *port)
+{
+ pci_stop_root_bus(port->bridge->bus);
+ pci_remove_root_bus(port->bridge->bus);
+
+ plda_pcie_irq_domain_deinit(port);
+
+ if (port->host_ops && port->host_ops->host_deinit)
+ port->host_ops->host_deinit(port);
+}
+EXPORT_SYMBOL_GPL(plda_pcie_host_deinit);
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index c3d8c141e44d..52f4cacf7917 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -142,6 +142,11 @@ struct plda_event_ops {
u32 (*get_events)(struct plda_pcie_rp *pcie);
};
+struct plda_pcie_host_ops {
+ int (*host_init)(struct plda_pcie_rp *pcie);
+ void (*host_deinit)(struct plda_pcie_rp *pcie);
+};
+
struct plda_msi {
struct mutex lock; /* Protect used bitmap */
struct irq_domain *msi_domain;
@@ -153,14 +158,20 @@ struct plda_msi {
struct plda_pcie_rp {
struct device *dev;
+ struct pci_host_bridge *bridge;
struct irq_domain *intx_domain;
struct irq_domain *event_domain;
raw_spinlock_t lock;
struct plda_msi msi;
const struct plda_event_ops *event_ops;
const struct irq_chip *event_irq_chip;
+ const struct plda_pcie_host_ops *host_ops;
void __iomem *bridge_addr;
+ void __iomem *config_base;
unsigned long events_bitmap;
+ int irq;
+ int msi_irq;
+ int intx_irq;
int num_events;
};
@@ -171,6 +182,8 @@ struct plda_event {
int msi_event;
};
+void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+ int where);
int plda_init_interrupts(struct platform_device *pdev,
struct plda_pcie_rp *port,
const struct plda_event *event);
@@ -179,4 +192,13 @@ void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
size_t size);
int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
struct plda_pcie_rp *port);
+int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
+ const struct plda_event *plda_event);
+void plda_pcie_host_deinit(struct plda_pcie_rp *pcie);
+
+static inline void plda_set_default_msi(struct plda_msi *msi)
+{
+ msi->vector_phy = IMSI_ADDR;
+ msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS;
+}
#endif
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- 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