Re: [PATCH RFC v3 5/6] phy: mvebu-cp110-utmi: add support for armada-380 utmi phys

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am 25.07.24 um 08:43 schrieb Vinod Koul:
> On 20-07-24, 16:19, Josua Mayer wrote:
>> Armada 380 has similar USB-2.0 PHYs as CP-110. The differences are:
>> - register base addresses
>> - gap between port registers
>> - number of ports: 388 has three, cp110 two
>> - device-mode mux bit refers to different ports
>> - syscon register's base address (offsets identical)
>> - armada-8k uses syscon for various drivers, a38x not
>>
>> Differentiation uses of_match_data with distinct compatible strings.
>>
>> Add support for Armada 380 PHYs by partially restructuting the driver:
>> - Port register pointers are moved to the per-port private data.
>> - Add armada-38x-specific compatible string and store enum value in
>>   of_match_data for differentiation.
>> - Add support for optional regs usb-cfg and utmi-cfg, to be used instead
>>   of syscon.
>>
>> Signed-off-by: Josua Mayer <josua@xxxxxxxxxxxxx>
>> ---
>>  drivers/phy/marvell/phy-mvebu-cp110-utmi.c | 209 +++++++++++++++++++++++------
>>  1 file changed, 166 insertions(+), 43 deletions(-)
>>
>> diff --git a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
>> index 4922a5f3327d..4341923e85bc 100644
>> --- a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
>> +++ b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
>> @@ -19,7 +19,7 @@
>>  #include <linux/usb/of.h>
>>  #include <linux/usb/otg.h>
>>  
>> -#define UTMI_PHY_PORTS				2
>> +#define UTMI_PHY_PORTS				3
>>  
>>  /* CP110 UTMI register macro definetions */
>>  #define SYSCON_USB_CFG_REG			0x420
>> @@ -76,32 +76,44 @@
>>  #define PLL_LOCK_DELAY_US			10000
>>  #define PLL_LOCK_TIMEOUT_US			1000000
>>  
>> -#define PORT_REGS(p)				((p)->priv->regs + (p)->id * 0x1000)
>> +enum mvebu_cp110_utmi_type {
>> +	/* 0 is reserved to avoid clashing with NULL */
>> +	A380_UTMI = 1,
>> +	CP110_UTMI = 2,
>> +};
>> +
>> +struct mvebu_cp110_utmi_port;
> why forward declare and not move the structs instead?
Seemed like the smaller change / more readable as diff.
I can move the struct instead!
>
>>  
>>  /**
>>   * struct mvebu_cp110_utmi - PHY driver data
>>   *
>> - * @regs: PHY registers
>> + * @regs_usb: USB configuration register
>>   * @syscon: Regmap with system controller registers
>>   * @dev: device driver handle
>>   * @ops: phy ops
>> + * @ports: phy object for each port
>>   */
>>  struct mvebu_cp110_utmi {
>> -	void __iomem *regs;
>> +	void __iomem *regs_usb;
>>  	struct regmap *syscon;
>>  	struct device *dev;
>>  	const struct phy_ops *ops;
>> +	struct mvebu_cp110_utmi_port *ports[UTMI_PHY_PORTS];
>>  };
>>  
>>  /**
>>   * struct mvebu_cp110_utmi_port - PHY port data
>>   *
>> + * @regs: PHY registers
>> + * @regs_cfg: PHY config register
>>   * @priv: PHY driver data
>>   * @id: PHY port ID
>>   * @dr_mode: PHY connection: USB_DR_MODE_HOST or USB_DR_MODE_PERIPHERAL
>>   */
>>  struct mvebu_cp110_utmi_port {
>>  	struct mvebu_cp110_utmi *priv;
>> +	void __iomem *regs;
>> +	void __iomem *regs_cfg;
>>  	u32 id;
>>  	enum usb_dr_mode dr_mode;
>>  };
>> @@ -118,47 +130,47 @@ static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
>>  	 * The crystal used for all platform boards is now 25MHz.
>>  	 * See the functional specification for details.
>>  	 */
>> -	reg = readl(PORT_REGS(port) + UTMI_PLL_CTRL_REG);
>> +	reg = readl(port->regs + UTMI_PLL_CTRL_REG);
> why not handle this as a preparatory patch for this? Helps in review

Will do!

>
>>  	reg &= ~(PLL_REFDIV_MASK | PLL_FBDIV_MASK | PLL_SEL_LPFR_MASK);
>>  	reg |= (PLL_REFDIV_VAL << PLL_REFDIV_OFFSET) |
>>  	       (PLL_FBDIV_VAL << PLL_FBDIV_OFFSET);
>> -	writel(reg, PORT_REGS(port) + UTMI_PLL_CTRL_REG);
>> +	writel(reg, port->regs + UTMI_PLL_CTRL_REG);
>>  
>>  	/* Impedance Calibration Threshold Setting */
>> -	reg = readl(PORT_REGS(port) + UTMI_CAL_CTRL_REG);
>> +	reg = readl(port->regs + UTMI_CAL_CTRL_REG);
>>  	reg &= ~IMPCAL_VTH_MASK;
>>  	reg |= IMPCAL_VTH_VAL << IMPCAL_VTH_OFFSET;
>> -	writel(reg, PORT_REGS(port) + UTMI_CAL_CTRL_REG);
>> +	writel(reg, port->regs + UTMI_CAL_CTRL_REG);
>>  
>>  	/* Set LS TX driver strength coarse control */
>> -	reg = readl(PORT_REGS(port) + UTMI_TX_CH_CTRL_REG);
>> +	reg = readl(port->regs + UTMI_TX_CH_CTRL_REG);
>>  	reg &= ~TX_AMP_MASK;
>>  	reg |= TX_AMP_VAL << TX_AMP_OFFSET;
>> -	writel(reg, PORT_REGS(port) + UTMI_TX_CH_CTRL_REG);
>> +	writel(reg, port->regs + UTMI_TX_CH_CTRL_REG);
>>  
>>  	/* Disable SQ and enable analog squelch detect */
>> -	reg = readl(PORT_REGS(port) + UTMI_RX_CH_CTRL0_REG);
>> +	reg = readl(port->regs + UTMI_RX_CH_CTRL0_REG);
>>  	reg &= ~SQ_DET_EN;
>>  	reg |= SQ_ANA_DTC_SEL;
>> -	writel(reg, PORT_REGS(port) + UTMI_RX_CH_CTRL0_REG);
>> +	writel(reg, port->regs + UTMI_RX_CH_CTRL0_REG);
>>  
>>  	/*
>>  	 * Set External squelch calibration number and
>>  	 * enable the External squelch calibration
>>  	 */
>> -	reg = readl(PORT_REGS(port) + UTMI_RX_CH_CTRL1_REG);
>> +	reg = readl(port->regs + UTMI_RX_CH_CTRL1_REG);
>>  	reg &= ~SQ_AMP_CAL_MASK;
>>  	reg |= (SQ_AMP_CAL_VAL << SQ_AMP_CAL_OFFSET) | SQ_AMP_CAL_EN;
>> -	writel(reg, PORT_REGS(port) + UTMI_RX_CH_CTRL1_REG);
>> +	writel(reg, port->regs + UTMI_RX_CH_CTRL1_REG);
>>  
>>  	/*
>>  	 * Set Control VDAT Reference Voltage - 0.325V and
>>  	 * Control VSRC Reference Voltage - 0.6V
>>  	 */
>> -	reg = readl(PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG);
>> +	reg = readl(port->regs + UTMI_CHGDTC_CTRL_REG);
>>  	reg &= ~(VDAT_MASK | VSRC_MASK);
>>  	reg |= (VDAT_VAL << VDAT_OFFSET) | (VSRC_VAL << VSRC_OFFSET);
>> -	writel(reg, PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG);
>> +	writel(reg, port->regs + UTMI_CHGDTC_CTRL_REG);
>>  }
>>  
>>  static int mvebu_cp110_utmi_phy_power_off(struct phy *phy)
>> @@ -166,22 +178,38 @@ static int mvebu_cp110_utmi_phy_power_off(struct phy *phy)
>>  	struct mvebu_cp110_utmi_port *port = phy_get_drvdata(phy);
>>  	struct mvebu_cp110_utmi *utmi = port->priv;
>>  	int i;
>> +	int reg;
>>  
>>  	/* Power down UTMI PHY port */
>> -	regmap_clear_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id),
>> -			  UTMI_PHY_CFG_PU_MASK);
>> +	if (!IS_ERR(port->regs_cfg)) {
>> +		reg = readl(port->regs_cfg);
>> +		reg &= ~(UTMI_PHY_CFG_PU_MASK);
>> +		writel(reg, port->regs_cfg);
>> +	} else
>> +		regmap_clear_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id),
>> +				  UTMI_PHY_CFG_PU_MASK);
> why are we doing both raw register read/write and regmap ops... that
> does not sound correct to me
Indeed.

The next question would be why for Armada 8K / CP110 syscon was chosen.

[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux