lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <21f0aa62-464f-4d8d-b8d7-5a4455179534@riscstar.com>
Date: Tue, 18 Nov 2025 08:11:53 -0600
From: Alex Elder <elder@...cstar.com>
To: Neil Armstrong <neil.armstrong@...aro.org>, vkoul@...nel.org,
 kishon@...nel.org
Cc: p.zabel@...gutronix.de, dlan@...too.org, aurelien@...el32.net,
 guodong@...cstar.com, linux-phy@...ts.infradead.org,
 spacemit@...ts.linux.dev, linux-riscv@...ts.infradead.org,
 linux-kernel@...r.kernel.org, Junzhong Pan <panjunzhong@...ux.spacemit.com>
Subject: Re: [PATCH v6 4/7] phy: spacemit: Introduce PCIe/combo PHY

On 11/18/25 2:56 AM, Neil Armstrong wrote:
> On 11/13/25 22:45, Alex Elder wrote:
>> Introduce a driver that supports three PHYs found on the SpacemiT
>> K1 SoC.  The first PHY is a combo PHY that can be configured for
>> use for either USB 3 or PCIe.  The other two PHYs support PCIe
>> only.
>>
>> All three PHYs must be programmed with an 8 bit receiver termination
>> value, which must be determined dynamically.  Only the combo PHY is
>> able to determine this value.  The combo PHY performs a special
>> calibration step at probe time to discover this, and that value is
>> used to program each PHY that operates in PCIe mode.  The combo
>> PHY must therefore be probed before either of the PCIe-only PHYs
>> will be used.
>>
>> Each PHY has an internal PLL driven from an external oscillator.
>> This PLL started when the PHY is first initialized, and stays
>> on thereafter.
>>
>> During normal operation, the USB or PCIe driver using the PHY must
>> ensure (other) clocks and resets are set up properly.
>>
>> However PCIe mode clocks are enabled and resets are de-asserted
>> temporarily by this driver to perform the calibration step on the
>> combo PHY.
>>
>> Tested-by: Junzhong Pan <panjunzhong@...ux.spacemit.com>
>> Signed-off-by: Alex Elder <elder@...cstar.com>
>> ---

. . .

>> diff --git a/drivers/phy/phy-spacemit-k1-pcie.c b/drivers/phy/phy- 
>> spacemit-k1-pcie.c
>> new file mode 100644
>> index 0000000000000..75477bea7f700
>> --- /dev/null
>> +++ b/drivers/phy/phy-spacemit-k1-pcie.c
>> @@ -0,0 +1,670 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * SpacemiT K1 PCIe and PCIe/USB 3 combo PHY driver
>> + *
>> + * Copyright (C) 2025 by RISCstar Solutions Corporation.  All rights 
>> reserved.
>> + */
>> +
>> +#include <linux/bitfield.h>
>> +#include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/module.h>
>> +#include <linux/phy/phy.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include <linux/reset.h>
>> +
>> +#include <dt-bindings/phy/phy.h>
>> +
>> +/*
>> + * Three PCIe ports are supported in the SpacemiT K1 SoC, and this 
>> driver
>> + * supports their PHYs.
>> + *
>> + * The PHY for PCIe port A is different from the PHYs for ports B and C:
>> + * - It has one lane, while ports B and C have two
>> + * - It is a combo PHY can be used for PCIe or USB 3
>> + * - It can automatically calibrate PCIe TX and RX termination settings
>> + *
>> + * The PHY functionality for PCIe ports B and C is identical:
>> + * - They have two PCIe lanes (but can be restricted to 1 via device 
>> tree)
>> + * - They are used for PCIe only
>> + * - They are configured using TX and RX values computed for port A
>> + *
>> + * A given board is designed to use the combo PHY for either PCIe or 
>> USB 3.
>> + * Whether the combo PHY is configured for PCIe or USB 3 is specified in
>> + * device tree using a phandle plus an argument.  The argument indicates
>> + * the type (either PHY_TYPE_PCIE or PHY_TYPE_USB3).
>> + *
>> + * Each PHY has a reset that it gets and deasserts during 
>> initialization.
>> + * Each depends also on other clocks and resets provided by the 
>> controller
>> + * hardware (PCIe or USB) it is associated with.  The controller drivers
>> + * are required to enable any clocks and de-assert any resets that 
>> affect
>> + * PHY operation.  In addition each PHY implements an internal PLL, 
>> driven
>> + * by an external (24 MHz) oscillator.
>> + *
>> + * PCIe PHYs must be programmed with RX and TX calibration values.  The
>> + * combo PHY is the only one that can determine these values.  They are
>> + * determined by temporarily enabling the combo PHY in PCIe mode at 
>> probe
>> + * time (if necessary).  This calibration only needs to be done once, 
>> and
>> + * when it has completed the TX and RX values are saved.
>> + *
>> + * To allow the combo PHY to be enabled for calibration, the resets and
>> + * clocks it uses in PCIe mode must be supplied.
>> + */
>> +
>> +struct k1_pcie_phy {
>> +    struct device *dev;        /* PHY provider device */
>> +    struct phy *phy;
>> +    void __iomem *regs;
>> +    u32 pcie_lanes;            /* Max (1 or 2) unless limited by DT */
>> +    struct clk *pll;
>> +    struct clk_hw pll_hw;        /* Private PLL clock */
>> +
>> +    /* The remaining fields are only used for the combo PHY */
>> +    u32 type;            /* PHY_TYPE_PCIE or PHY_TYPE_USB3 */
>> +    struct regmap *pmu;        /* MMIO regmap (no errors) */
>> +};
>> +
>> +#define CALIBRATION_TIMEOUT        500000    /* For combo PHY (usec) */
>> +#define PLL_TIMEOUT            500000    /* For PHY PLL lock (usec) */
>> +#define POLL_DELAY            500    /* Time between polls (usec) */
>> +
>> +/* Selecting the combo PHY operating mode requires APMU regmap access */
>> +#define SYSCON_APMU            "spacemit,apmu"
>> +
>> +/* PMU space, for selecting between PCIe and USB 3 mode (combo PHY 
>> only) */
>> +
>> +#define PMUA_USB_PHY_CTRL0            0x0110
>> +#define COMBO_PHY_SEL            BIT(3)    /* 0: PCIe; 1: USB 3 */
>> +
>> +#define PCIE_CLK_RES_CTRL            0x03cc
>> +#define PCIE_APP_HOLD_PHY_RST        BIT(30)
>> +
>> +/* PHY register space */
>> +
>> +/* Offset between lane 0 and lane 1 registers when there are two */
>> +#define PHY_LANE_OFFSET                0x0400
>> +
>> +/* PHY PLL configuration */
>> +#define PCIE_PU_ADDR_CLK_CFG            0x0008
>> +#define PLL_READY            BIT(0)        /* read-only */
>> +#define CFG_INTERNAL_TIMER_ADJ        GENMASK(10, 7)
>> +#define TIMER_ADJ_USB        0x2
>> +#define TIMER_ADJ_PCIE        0x6
>> +#define CFG_SW_PHY_INIT_DONE        BIT(11)    /* We set after PLL 
>> config */
>> +
>> +#define PCIE_RC_DONE_STATUS            0x0018
>> +#define CFG_FORCE_RCV_RETRY        BIT(10)        /* Used for PCIe */
>> +
>> +/* PCIe PHY lane calibration; assumes 24MHz input clock */
>> +#define PCIE_RC_CAL_REG2            0x0020
>> +#define RC_CAL_TOGGLE            BIT(22)
>> +#define CLKSEL                GENMASK(31, 29)
>> +#define CLKSEL_24M        0x3
>> +
>> +/* Additional PHY PLL configuration (USB 3 and PCIe) */
>> +#define PCIE_PU_PLL_1                0x0048
>> +#define REF_100_WSSC            BIT(12)    /* 1: input is 100MHz, SSC */
>> +#define FREF_SEL            GENMASK(15, 13)
>> +#define FREF_24M        0x1
>> +#define SSC_DEP_SEL            GENMASK(19, 16)
>> +#define SSC_DEP_NONE        0x0
>> +#define SSC_DEP_5000PPM        0xa
>> +
>> +/* PCIe PHY configuration */
>> +#define PCIE_PU_PLL_2                0x004c
>> +#define GEN_REF100            BIT(4)    /* 1: generate 100MHz clk */
>> +
>> +#define PCIE_RX_REG1                0x0050
>> +#define EN_RTERM            BIT(3)
>> +#define AFE_RTERM_REG            GENMASK(11, 8)
>> +
>> +#define PCIE_RX_REG2                0x0054
>> +#define RX_RTERM_SEL            BIT(5)    /* 0: use AFE_RTERM_REG 
>> value */
>> +
>> +#define PCIE_LTSSM_DIS_ENTRY            0x005c
>> +#define CFG_REFCLK_MODE            GENMASK(9, 8)
>> +#define RFCLK_MODE_DRIVER    0x1
>> +#define OVRD_REFCLK_MODE        BIT(10)    /* 1: use CFG_RFCLK_MODE */
>> +
>> +#define PCIE_TX_REG1                0x0064
>> +#define TX_RTERM_REG            GENMASK(15, 12)
>> +#define TX_RTERM_SEL            BIT(25)    /* 1: use TX_RTERM_REG */
>> +
>> +/* Zeroed for the combo PHY operating in USB mode */
>> +#define USB3_TEST_CTRL                0x0068
>> +
>> +/* PHY calibration values, determined by the combo PHY at probe time */
>> +#define PCIE_RCAL_RESULT            0x0084    /* Port A PHY only */
>> +#define RTERM_VALUE_RX            GENMASK(3, 0)
>> +#define RTERM_VALUE_TX            GENMASK(7, 4)
>> +#define R_TUNE_DONE            BIT(10)
>> +
>> +static u32 k1_phy_rterm = ~0;     /* Invalid initial value */
> 
> This global variable would have deserved a comment explaining
> why the value is global, instead the reason is only present in the
> commit message....

The (somewhat strange) overall scheme is described in a comment
block at the top of the file.  But I think you're right, a short
comment could at least refer back to that, and say "this is
where the calibration value is held" or something.

>> +/* Save the RX and TX receiver termination values */
>> +static void k1_phy_rterm_set(u32 val)
>> +{
>> +    k1_phy_rterm = val & (RTERM_VALUE_RX | RTERM_VALUE_TX);
>> +}
>> +
>> +static bool k1_phy_rterm_valid(void)
>> +{
>> +    /* Valid if no bits outside those we care about are set */
>> +    return !(k1_phy_rterm & ~(RTERM_VALUE_RX | RTERM_VALUE_TX));
>> +}

. . .

>> +module_platform_driver(k1_pcie_phy_driver);
>> +
>> +MODULE_DESCRIPTION("SpacemiT K1 PCIe and USB 3 PHY driver");
>> +MODULE_LICENSE("GPL");
> 
> The code is quite hard to read, with pleny of useless comments
> when the actual comments we needs are either in the wrong place
> or just missing.

I think the way this calibration works is unusual and a bit
confusing, and I might have gone too far trying to explain it.

It would be more helpful for you to provide examples of what
comments you think are useless, and where there are things that
would benefit from better explanation (as you did for the lack
of a comment for the k1_phy_rterm value).  I want very much to
make things better, but your statement offers no guidance on
what you're looking for.

> Anyway, no big comment on the code or the API usage, all looks good:
> 
> Reviewed-by: Neil Armstrong <neil.armstrong@...aro.org>

Thank you very much for reviewing this Neil.

					-Alex

> Thanks,
> Neil
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ