On Fri, Jan 09, 2026 at 11:29:49AM +0800, Shawn Lin wrote:
> Rockchip platforms provide a 64x4 bytes debug FIFO to trace the
> LTSSM history. Any LTSSM change will be recorded. It's userful
> for debug purpose, for example link failure, etc.
> 
> Signed-off-by: Shawn Lin <[email protected]>
> ---
> 
> Changes in v2:
> - use tracepoint
> 
>  drivers/pci/controller/dwc/pcie-dw-rockchip.c | 92 
> +++++++++++++++++++++++++++
>  1 file changed, 92 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c 
> b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> index 352f513..be9639aa 100644
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -22,6 +22,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
>  #include <linux/reset.h>
> +#include <linux/workqueue.h>
> +#include <trace/events/pci_controller.h>
>  
>  #include "../../pci.h"
>  #include "pcie-designware.h"
> @@ -73,6 +75,18 @@
>  #define  PCIE_CLIENT_CDM_RASDES_TBA_L1_1     BIT(4)
>  #define  PCIE_CLIENT_CDM_RASDES_TBA_L1_2     BIT(5)
>  
> +/* Debug FIFO information */
> +#define PCIE_CLIENT_DBG_FIFO_MODE_CON        0x310
> +#define  PCIE_CLIENT_DBG_EN          0xffff0007
> +#define  PCIE_CLIENT_DBG_DIS         0xffff0000
> +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0      0x320
> +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1      0x324
> +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0      0x328
> +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1      0x32c
> +#define  PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
> +#define PCIE_CLIENT_DBG_FIFO_STATUS  0x350
> +#define PCIE_DBG_LTSSM_HISTORY_CNT   64
> +
>  /* Hot Reset Control Register */
>  #define PCIE_CLIENT_HOT_RESET_CTRL   0x180
>  #define  PCIE_LTSSM_APP_DLY2_EN              BIT(1)
> @@ -96,6 +110,7 @@ struct rockchip_pcie {
>       struct irq_domain *irq_domain;
>       const struct rockchip_pcie_of_data *data;
>       bool supports_clkreq;
> +     struct delayed_work trace_work;
>  };
>  
>  struct rockchip_pcie_of_data {
> @@ -206,6 +221,79 @@ static enum dw_pcie_ltssm rockchip_pcie_get_ltssm(struct 
> dw_pcie *pci)
>       return rockchip_pcie_get_ltssm_reg(rockchip) & PCIE_LTSSM_STATUS_MASK;
>  }
>  
> +#ifdef CONFIG_TRACING
> +static void rockchip_pcie_ltssm_trace_work(struct work_struct *work)
> +{
> +     struct rockchip_pcie *rockchip = container_of(work, struct 
> rockchip_pcie,
> +                                             trace_work.work);
> +     struct dw_pcie *pci = &rockchip->pci;
> +     enum dw_pcie_ltssm state;
> +     u32 val, rate, l1ss, loop, prev_val = DW_PCIE_LTSSM_UNKNOWN;

Reverse Xmas order please.

> +
> +     for (loop = 0; loop < PCIE_DBG_LTSSM_HISTORY_CNT; loop++) {

s/loop/i?

> +             val = rockchip_pcie_readl_apb(rockchip, 
> PCIE_CLIENT_DBG_FIFO_STATUS);
> +             rate = (val & GENMASK(22, 20)) >> 20;
> +             l1ss = (val & GENMASK(10, 8)) >> 8;
> +             val &= PCIE_LTSSM_STATUS_MASK;

Can you use FIELD_ macros here?

> +
> +             /* Two consecutive identical LTSSM means invalid subsequent 
> data */

Interesting. Does the hardware maintain a counter to track the reads? So once
you break out of the loop and read it after 5s, you'll start from where you left
i.e., the duplicate entry or from the start of the counter again?

> +             if ((loop > 0 && val == prev_val) || val > 
> DW_PCIE_LTSSM_RCVRY_EQ3)
> +                     break;
> +
> +             state = prev_val = val;
> +             if (val == DW_PCIE_LTSSM_L1_IDLE) {
> +                     if (l1ss == 2)
> +                             state = DW_PCIE_LTSSM_L1_2;
> +                     else if (l1ss == 1)
> +                             state = DW_PCIE_LTSSM_L1_1;

I believe L1.0 is not supported.

> +             }
> +
> +             trace_pcie_ltssm_state_transition(dev_name(pci->dev),
> +                                     dw_pcie_ltssm_status_string(state),
> +                                     ((rate + 1) > pci->max_link_speed) ?
> +                                     PCI_SPEED_UNKNOWN : PCIE_SPEED_2_5GT + 
> rate);
> +     }
> +
> +     schedule_delayed_work(&rockchip->trace_work, msecs_to_jiffies(5000));
> +}
> +
> +static void rockchip_pcie_ltssm_trace(struct rockchip_pcie *rockchip,
> +                                   bool en)

s/en/enable

- Mani

-- 
மணிவண்ணன் சதாசிவம்

Reply via email to