From: Josua Mayer <josua@solid-run.com>
To: Vinod Koul <vkoul@kernel.org>
Cc: Kishon Vijay Abraham I <kishon@kernel.org>,
Andrew Lunn <andrew@lunn.ch>,
Gregory Clement <gregory.clement@bootlin.com>,
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Russell King <linux@armlinux.org.uk>,
Konstantin Porotchkin <kostap@marvell.com>,
Yazan Shhady <yazan.shhady@solid-run.com>,
"linux-phy@lists.infradead.org" <linux-phy@lists.infradead.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>
Subject: Re: [PATCH RFC v3 5/6] phy: mvebu-cp110-utmi: add support for armada-380 utmi phys
Date: Thu, 25 Jul 2024 08:38:17 +0000 [thread overview]
Message-ID: <f4835ad8-08c1-49f0-ae85-4f870ad90a8e@solid-run.com> (raw)
In-Reply-To: <ZqH0KDVjCILr3A6r@matsya>
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@solid-run.com>
>> ---
>> 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.
From what I could find the registers accessed by utmi driver
are not accessed by other drivers.
I am adding raw register access as an alternative,
to keep supporting old device-tree specifying syscon handle.
I considered writing helper functions for the if-not-error-syscon-else-raw,
but between set_bits, clear_bits, global and per-port regs
would have ended up with too many.
>
>>
>> for (i = 0; i < UTMI_PHY_PORTS; i++) {
>> - int test = regmap_test_bits(utmi->syscon,
>> - SYSCON_UTMI_CFG_REG(i),
>> - UTMI_PHY_CFG_PU_MASK);
>> + if (!utmi->ports[i])
>> + continue;
>> +
>> + if (!IS_ERR(utmi->ports[i]->regs_cfg))
>> + reg = readl(utmi->ports[i]->regs_cfg);
>> + else
>> + regmap_read(utmi->syscon, SYSCON_UTMI_CFG_REG(i), ®);
>> + int test = reg & UTMI_PHY_CFG_PU_MASK;
>> /* skip PLL shutdown if there are active UTMI PHY ports */
>> if (test != 0)
>> return 0;
>> }
>>
>> /* PLL Power down if all UTMI PHYs are down */
>> - regmap_clear_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>> + if (!IS_ERR(utmi->regs_usb)) {
>> + reg = readl(utmi->regs_usb);
>> + reg &= ~(USB_CFG_PLL_MASK);
>> + writel(reg, utmi->regs_usb);
>> + } else
>> + regmap_clear_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>>
>> return 0;
>> }
>> @@ -191,8 +219,15 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> struct mvebu_cp110_utmi_port *port = phy_get_drvdata(phy);
>> struct mvebu_cp110_utmi *utmi = port->priv;
>> struct device *dev = &phy->dev;
>> + const void *match;
>> + enum mvebu_cp110_utmi_type type;
>> int ret;
>> u32 reg;
>> + u32 sel;
>> +
>> + match = device_get_match_data(utmi->dev);
>> + if (match)
>> + type = (enum mvebu_cp110_utmi_type)(uintptr_t)match;
>>
>> /* It is necessary to power off UTMI before configuration */
>> ret = mvebu_cp110_utmi_phy_power_off(phy);
>> @@ -208,16 +243,45 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> * to UTMI0 or to UTMI1 PHY port, but not to both.
>> */
>> if (port->dr_mode == USB_DR_MODE_PERIPHERAL) {
>> - regmap_update_bits(utmi->syscon, SYSCON_USB_CFG_REG,
>> - USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK,
>> - USB_CFG_DEVICE_EN_MASK |
>> - (port->id << USB_CFG_DEVICE_MUX_OFFSET));
>> + switch (type) {
>> + case A380_UTMI:
>> + /*
>> + * A380 muxes between ports 0/2:
>> + * - 0: Device mode on Port 2
>> + * - 1: Device mode on Port 0
>> + */
>> + if (port->id == 1)
>> + return -EINVAL;
>> + sel = !!(port->id == 0);
>> + break;
>> + case CP110_UTMI:
>> + /*
>> + * CP110 muxes between ports 0/1:
>> + * - 0: Device mode on Port 0
>> + * - 1: Device mode on Port 1
>> + */
>> + sel = port->id;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> + if (!IS_ERR(utmi->regs_usb)) {
>> + reg = readl(utmi->regs_usb);
>> + reg &= ~(USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK);
>> + reg |= USB_CFG_DEVICE_EN_MASK;
>> + reg |= (sel << USB_CFG_DEVICE_MUX_OFFSET);
>> + writel(reg, utmi->regs_usb);
>> + } else
>> + regmap_update_bits(utmi->syscon, SYSCON_USB_CFG_REG,
>> + USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK,
>> + USB_CFG_DEVICE_EN_MASK |
>> + (sel << USB_CFG_DEVICE_MUX_OFFSET));
>> }
>>
>> /* Set Test suspendm mode and enable Test UTMI select */
>> - reg = readl(PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + reg = readl(port->regs + UTMI_CTRL_STATUS0_REG);
>> reg |= SUSPENDM | TEST_SEL;
>> - writel(reg, PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + writel(reg, port->regs + UTMI_CTRL_STATUS0_REG);
>>
>> /* Wait for UTMI power down */
>> mdelay(1);
>> @@ -226,16 +290,21 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> mvebu_cp110_utmi_port_setup(port);
>>
>> /* Power UP UTMI PHY */
>> - regmap_set_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_set_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id),
>> + UTMI_PHY_CFG_PU_MASK);
>>
>> /* Disable Test UTMI select */
>> - reg = readl(PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + reg = readl(port->regs + UTMI_CTRL_STATUS0_REG);
>> reg &= ~TEST_SEL;
>> - writel(reg, PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + writel(reg, port->regs + UTMI_CTRL_STATUS0_REG);
>>
>> /* Wait for impedance calibration */
>> - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_CAL_CTRL_REG, reg,
>> + ret = readl_poll_timeout(port->regs + UTMI_CAL_CTRL_REG, reg,
>> reg & IMPCAL_DONE,
>> PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
>> if (ret) {
>> @@ -244,7 +313,7 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> }
>>
>> /* Wait for PLL calibration */
>> - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_CAL_CTRL_REG, reg,
>> + ret = readl_poll_timeout(port->regs + UTMI_CAL_CTRL_REG, reg,
>> reg & PLLCAL_DONE,
>> PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
>> if (ret) {
>> @@ -253,7 +322,7 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> }
>>
>> /* Wait for PLL ready */
>> - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_PLL_CTRL_REG, reg,
>> + ret = readl_poll_timeout(port->regs + UTMI_PLL_CTRL_REG, reg,
>> reg & PLL_RDY,
>> PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
>> if (ret) {
>> @@ -262,7 +331,12 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> }
>>
>> /* PLL Power up */
>> - regmap_set_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>> + if (!IS_ERR(utmi->regs_usb)) {
>> + reg = readl(utmi->regs_usb);
>> + reg |= USB_CFG_PLL_MASK;
>> + writel(reg, utmi->regs_usb);
>> + } else
>> + regmap_set_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>>
>> return 0;
>> }
>> @@ -274,7 +348,8 @@ static const struct phy_ops mvebu_cp110_utmi_phy_ops = {
>> };
>>
>> static const struct of_device_id mvebu_cp110_utmi_of_match[] = {
>> - { .compatible = "marvell,cp110-utmi-phy" },
>> + { .compatible = "marvell,a38x-utmi-phy", .data = (void *)A380_UTMI },
>> + { .compatible = "marvell,cp110-utmi-phy", .data = (void *)CP110_UTMI },
> Cast to void * are not required to be done
Ack.
>
>> {},
>> };
>> MODULE_DEVICE_TABLE(of, mvebu_cp110_utmi_of_match);
>> @@ -285,6 +360,10 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
>> struct mvebu_cp110_utmi *utmi;
>> struct phy_provider *provider;
>> struct device_node *child;
>> + void __iomem *regs_utmi;
>> + void __iomem *regs_utmi_cfg;
>> + const void *match;
>> + enum mvebu_cp110_utmi_type type;
>> u32 usb_devices = 0;
>>
>> utmi = devm_kzalloc(dev, sizeof(*utmi), GFP_KERNEL);
>> @@ -293,18 +372,44 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
>>
>> utmi->dev = dev;
>>
>> + match = device_get_match_data(dev);
>> + if (match)
>> + type = (enum mvebu_cp110_utmi_type)(uintptr_t)match;
>> +
>> + /* Get UTMI memory region */
>> + regs_utmi = devm_platform_ioremap_resource(pdev, 0);
>> + if (IS_ERR(regs_utmi)) {
>> + dev_err(dev, "Failed to map utmi regs\n");
>> + return PTR_ERR(regs_utmi);
>> + }
>> +
>> + /* Get usb config region */
>> + utmi->regs_usb = devm_platform_ioremap_resource_byname(pdev, "usb-cfg");
>> + if (IS_ERR(utmi->regs_usb) && PTR_ERR(utmi->regs_usb) != -EINVAL) {
>> + dev_err(dev, "Failed to map usb config regs\n");
>> + return PTR_ERR(utmi->regs_usb);
>> + }
>> +
>> + /* Get utmi config region */
>> + regs_utmi_cfg = devm_platform_ioremap_resource_byname(pdev, "utmi-cfg");
>> + if (IS_ERR(regs_utmi_cfg) && PTR_ERR(regs_utmi_cfg) != -EINVAL) {
>> + dev_err(dev, "Failed to map usb config regs\n");
>> + return PTR_ERR(regs_utmi_cfg);
>> + }
>> +
>> /* Get system controller region */
>> utmi->syscon = syscon_regmap_lookup_by_phandle(dev->of_node,
>> "marvell,system-controller");
>> - if (IS_ERR(utmi->syscon)) {
>> - dev_err(dev, "Missing UTMI system controller\n");
>> + if (IS_ERR(utmi->syscon) && PTR_ERR(utmi->syscon) != -ENODEV) {
>> + dev_err(dev, "Failed to get system controller\n");
>> return PTR_ERR(utmi->syscon);
>> }
>>
>> - /* Get UTMI memory region */
>> - utmi->regs = devm_platform_ioremap_resource(pdev, 0);
>> - if (IS_ERR(utmi->regs))
>> - return PTR_ERR(utmi->regs);
>> + if (IS_ERR(utmi->syscon) &&
>> + (IS_ERR(utmi->regs_usb) || IS_ERR(regs_utmi_cfg))) {
>> + dev_err(dev, "Missing utmi system controller or config regs");
>> + return -EINVAL;
>> + }
>>
>> for_each_available_child_of_node(dev->of_node, child) {
>> struct mvebu_cp110_utmi_port *port;
>> @@ -326,6 +431,24 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
>> return -ENOMEM;
>> }
>>
>> + utmi->ports[port_id] = port;
>> +
>> + /* Get port memory region */
>> + switch (type) {
>> + case A380_UTMI:
>> + port->regs = regs_utmi + port_id * 0x1000;
>> + break;
>> + case CP110_UTMI:
>> + port->regs = regs_utmi + port_id * 0x2000;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + /* assign utmi cfg reg */
>> + if (!IS_ERR(regs_utmi_cfg))
>> + port->regs_cfg = regs_utmi_cfg + port_id * 4;
>> +
>> port->dr_mode = of_usb_get_dr_mode_by_phy(child, -1);
>> if ((port->dr_mode != USB_DR_MODE_HOST) &&
>> (port->dr_mode != USB_DR_MODE_PERIPHERAL)) {
>>
>> --
>> 2.43.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
WARNING: multiple messages have this Message-ID (diff)
From: Josua Mayer <josua@solid-run.com>
To: Vinod Koul <vkoul@kernel.org>
Cc: Kishon Vijay Abraham I <kishon@kernel.org>,
Andrew Lunn <andrew@lunn.ch>,
Gregory Clement <gregory.clement@bootlin.com>,
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Russell King <linux@armlinux.org.uk>,
Konstantin Porotchkin <kostap@marvell.com>,
Yazan Shhady <yazan.shhady@solid-run.com>,
"linux-phy@lists.infradead.org" <linux-phy@lists.infradead.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>
Subject: Re: [PATCH RFC v3 5/6] phy: mvebu-cp110-utmi: add support for armada-380 utmi phys
Date: Thu, 25 Jul 2024 08:38:17 +0000 [thread overview]
Message-ID: <f4835ad8-08c1-49f0-ae85-4f870ad90a8e@solid-run.com> (raw)
In-Reply-To: <ZqH0KDVjCILr3A6r@matsya>
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@solid-run.com>
>> ---
>> 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.
From what I could find the registers accessed by utmi driver
are not accessed by other drivers.
I am adding raw register access as an alternative,
to keep supporting old device-tree specifying syscon handle.
I considered writing helper functions for the if-not-error-syscon-else-raw,
but between set_bits, clear_bits, global and per-port regs
would have ended up with too many.
>
>>
>> for (i = 0; i < UTMI_PHY_PORTS; i++) {
>> - int test = regmap_test_bits(utmi->syscon,
>> - SYSCON_UTMI_CFG_REG(i),
>> - UTMI_PHY_CFG_PU_MASK);
>> + if (!utmi->ports[i])
>> + continue;
>> +
>> + if (!IS_ERR(utmi->ports[i]->regs_cfg))
>> + reg = readl(utmi->ports[i]->regs_cfg);
>> + else
>> + regmap_read(utmi->syscon, SYSCON_UTMI_CFG_REG(i), ®);
>> + int test = reg & UTMI_PHY_CFG_PU_MASK;
>> /* skip PLL shutdown if there are active UTMI PHY ports */
>> if (test != 0)
>> return 0;
>> }
>>
>> /* PLL Power down if all UTMI PHYs are down */
>> - regmap_clear_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>> + if (!IS_ERR(utmi->regs_usb)) {
>> + reg = readl(utmi->regs_usb);
>> + reg &= ~(USB_CFG_PLL_MASK);
>> + writel(reg, utmi->regs_usb);
>> + } else
>> + regmap_clear_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>>
>> return 0;
>> }
>> @@ -191,8 +219,15 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> struct mvebu_cp110_utmi_port *port = phy_get_drvdata(phy);
>> struct mvebu_cp110_utmi *utmi = port->priv;
>> struct device *dev = &phy->dev;
>> + const void *match;
>> + enum mvebu_cp110_utmi_type type;
>> int ret;
>> u32 reg;
>> + u32 sel;
>> +
>> + match = device_get_match_data(utmi->dev);
>> + if (match)
>> + type = (enum mvebu_cp110_utmi_type)(uintptr_t)match;
>>
>> /* It is necessary to power off UTMI before configuration */
>> ret = mvebu_cp110_utmi_phy_power_off(phy);
>> @@ -208,16 +243,45 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> * to UTMI0 or to UTMI1 PHY port, but not to both.
>> */
>> if (port->dr_mode == USB_DR_MODE_PERIPHERAL) {
>> - regmap_update_bits(utmi->syscon, SYSCON_USB_CFG_REG,
>> - USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK,
>> - USB_CFG_DEVICE_EN_MASK |
>> - (port->id << USB_CFG_DEVICE_MUX_OFFSET));
>> + switch (type) {
>> + case A380_UTMI:
>> + /*
>> + * A380 muxes between ports 0/2:
>> + * - 0: Device mode on Port 2
>> + * - 1: Device mode on Port 0
>> + */
>> + if (port->id == 1)
>> + return -EINVAL;
>> + sel = !!(port->id == 0);
>> + break;
>> + case CP110_UTMI:
>> + /*
>> + * CP110 muxes between ports 0/1:
>> + * - 0: Device mode on Port 0
>> + * - 1: Device mode on Port 1
>> + */
>> + sel = port->id;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> + if (!IS_ERR(utmi->regs_usb)) {
>> + reg = readl(utmi->regs_usb);
>> + reg &= ~(USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK);
>> + reg |= USB_CFG_DEVICE_EN_MASK;
>> + reg |= (sel << USB_CFG_DEVICE_MUX_OFFSET);
>> + writel(reg, utmi->regs_usb);
>> + } else
>> + regmap_update_bits(utmi->syscon, SYSCON_USB_CFG_REG,
>> + USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK,
>> + USB_CFG_DEVICE_EN_MASK |
>> + (sel << USB_CFG_DEVICE_MUX_OFFSET));
>> }
>>
>> /* Set Test suspendm mode and enable Test UTMI select */
>> - reg = readl(PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + reg = readl(port->regs + UTMI_CTRL_STATUS0_REG);
>> reg |= SUSPENDM | TEST_SEL;
>> - writel(reg, PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + writel(reg, port->regs + UTMI_CTRL_STATUS0_REG);
>>
>> /* Wait for UTMI power down */
>> mdelay(1);
>> @@ -226,16 +290,21 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> mvebu_cp110_utmi_port_setup(port);
>>
>> /* Power UP UTMI PHY */
>> - regmap_set_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_set_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id),
>> + UTMI_PHY_CFG_PU_MASK);
>>
>> /* Disable Test UTMI select */
>> - reg = readl(PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + reg = readl(port->regs + UTMI_CTRL_STATUS0_REG);
>> reg &= ~TEST_SEL;
>> - writel(reg, PORT_REGS(port) + UTMI_CTRL_STATUS0_REG);
>> + writel(reg, port->regs + UTMI_CTRL_STATUS0_REG);
>>
>> /* Wait for impedance calibration */
>> - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_CAL_CTRL_REG, reg,
>> + ret = readl_poll_timeout(port->regs + UTMI_CAL_CTRL_REG, reg,
>> reg & IMPCAL_DONE,
>> PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
>> if (ret) {
>> @@ -244,7 +313,7 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> }
>>
>> /* Wait for PLL calibration */
>> - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_CAL_CTRL_REG, reg,
>> + ret = readl_poll_timeout(port->regs + UTMI_CAL_CTRL_REG, reg,
>> reg & PLLCAL_DONE,
>> PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
>> if (ret) {
>> @@ -253,7 +322,7 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> }
>>
>> /* Wait for PLL ready */
>> - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_PLL_CTRL_REG, reg,
>> + ret = readl_poll_timeout(port->regs + UTMI_PLL_CTRL_REG, reg,
>> reg & PLL_RDY,
>> PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
>> if (ret) {
>> @@ -262,7 +331,12 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy)
>> }
>>
>> /* PLL Power up */
>> - regmap_set_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>> + if (!IS_ERR(utmi->regs_usb)) {
>> + reg = readl(utmi->regs_usb);
>> + reg |= USB_CFG_PLL_MASK;
>> + writel(reg, utmi->regs_usb);
>> + } else
>> + regmap_set_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK);
>>
>> return 0;
>> }
>> @@ -274,7 +348,8 @@ static const struct phy_ops mvebu_cp110_utmi_phy_ops = {
>> };
>>
>> static const struct of_device_id mvebu_cp110_utmi_of_match[] = {
>> - { .compatible = "marvell,cp110-utmi-phy" },
>> + { .compatible = "marvell,a38x-utmi-phy", .data = (void *)A380_UTMI },
>> + { .compatible = "marvell,cp110-utmi-phy", .data = (void *)CP110_UTMI },
> Cast to void * are not required to be done
Ack.
>
>> {},
>> };
>> MODULE_DEVICE_TABLE(of, mvebu_cp110_utmi_of_match);
>> @@ -285,6 +360,10 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
>> struct mvebu_cp110_utmi *utmi;
>> struct phy_provider *provider;
>> struct device_node *child;
>> + void __iomem *regs_utmi;
>> + void __iomem *regs_utmi_cfg;
>> + const void *match;
>> + enum mvebu_cp110_utmi_type type;
>> u32 usb_devices = 0;
>>
>> utmi = devm_kzalloc(dev, sizeof(*utmi), GFP_KERNEL);
>> @@ -293,18 +372,44 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
>>
>> utmi->dev = dev;
>>
>> + match = device_get_match_data(dev);
>> + if (match)
>> + type = (enum mvebu_cp110_utmi_type)(uintptr_t)match;
>> +
>> + /* Get UTMI memory region */
>> + regs_utmi = devm_platform_ioremap_resource(pdev, 0);
>> + if (IS_ERR(regs_utmi)) {
>> + dev_err(dev, "Failed to map utmi regs\n");
>> + return PTR_ERR(regs_utmi);
>> + }
>> +
>> + /* Get usb config region */
>> + utmi->regs_usb = devm_platform_ioremap_resource_byname(pdev, "usb-cfg");
>> + if (IS_ERR(utmi->regs_usb) && PTR_ERR(utmi->regs_usb) != -EINVAL) {
>> + dev_err(dev, "Failed to map usb config regs\n");
>> + return PTR_ERR(utmi->regs_usb);
>> + }
>> +
>> + /* Get utmi config region */
>> + regs_utmi_cfg = devm_platform_ioremap_resource_byname(pdev, "utmi-cfg");
>> + if (IS_ERR(regs_utmi_cfg) && PTR_ERR(regs_utmi_cfg) != -EINVAL) {
>> + dev_err(dev, "Failed to map usb config regs\n");
>> + return PTR_ERR(regs_utmi_cfg);
>> + }
>> +
>> /* Get system controller region */
>> utmi->syscon = syscon_regmap_lookup_by_phandle(dev->of_node,
>> "marvell,system-controller");
>> - if (IS_ERR(utmi->syscon)) {
>> - dev_err(dev, "Missing UTMI system controller\n");
>> + if (IS_ERR(utmi->syscon) && PTR_ERR(utmi->syscon) != -ENODEV) {
>> + dev_err(dev, "Failed to get system controller\n");
>> return PTR_ERR(utmi->syscon);
>> }
>>
>> - /* Get UTMI memory region */
>> - utmi->regs = devm_platform_ioremap_resource(pdev, 0);
>> - if (IS_ERR(utmi->regs))
>> - return PTR_ERR(utmi->regs);
>> + if (IS_ERR(utmi->syscon) &&
>> + (IS_ERR(utmi->regs_usb) || IS_ERR(regs_utmi_cfg))) {
>> + dev_err(dev, "Missing utmi system controller or config regs");
>> + return -EINVAL;
>> + }
>>
>> for_each_available_child_of_node(dev->of_node, child) {
>> struct mvebu_cp110_utmi_port *port;
>> @@ -326,6 +431,24 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
>> return -ENOMEM;
>> }
>>
>> + utmi->ports[port_id] = port;
>> +
>> + /* Get port memory region */
>> + switch (type) {
>> + case A380_UTMI:
>> + port->regs = regs_utmi + port_id * 0x1000;
>> + break;
>> + case CP110_UTMI:
>> + port->regs = regs_utmi + port_id * 0x2000;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + /* assign utmi cfg reg */
>> + if (!IS_ERR(regs_utmi_cfg))
>> + port->regs_cfg = regs_utmi_cfg + port_id * 4;
>> +
>> port->dr_mode = of_usb_get_dr_mode_by_phy(child, -1);
>> if ((port->dr_mode != USB_DR_MODE_HOST) &&
>> (port->dr_mode != USB_DR_MODE_PERIPHERAL)) {
>>
>> --
>> 2.43.0
next prev parent reply other threads:[~2024-07-25 8:38 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-20 14:19 [PATCH RFC v3 0/6] phy: mvebu-cp110-utmi: add support for armada-380 utmi phys Josua Mayer
2024-07-20 14:19 ` Josua Mayer
2024-07-20 14:19 ` [PATCH RFC v3 1/6] arm: dts: marvell: armada-388-clearfog: enable third usb on m.2/mpcie Josua Mayer
2024-07-20 14:19 ` Josua Mayer
2024-07-20 14:19 ` [PATCH RFC v3 2/6] arm: dts: marvell: armada-388-clearfog-base: add rfkill for m.2 Josua Mayer
2024-07-20 14:19 ` Josua Mayer
2024-07-20 14:19 ` [PATCH RFC v3 3/6] dt-bindings: phy: cp110-utmi-phy: add compatible string for armada-38x Josua Mayer
2024-07-20 14:19 ` Josua Mayer
2024-07-21 9:31 ` Krzysztof Kozlowski
2024-07-21 9:31 ` Krzysztof Kozlowski
2024-07-22 15:05 ` Josua Mayer
2024-07-22 15:05 ` Josua Mayer
2024-07-22 15:14 ` Josua Mayer
2024-07-22 15:14 ` Josua Mayer
2024-07-22 15:17 ` Krzysztof Kozlowski
2024-07-22 15:17 ` Krzysztof Kozlowski
2024-07-22 15:31 ` Josua Mayer
2024-07-22 15:31 ` Josua Mayer
2024-07-22 15:45 ` Krzysztof Kozlowski
2024-07-22 15:45 ` Krzysztof Kozlowski
2024-07-22 15:49 ` Josua Mayer
2024-07-22 15:49 ` Josua Mayer
2024-07-20 14:19 ` [PATCH RFC v3 4/6] arm: dts: marvell: armada-38x: add description for usb phys Josua Mayer
2024-07-20 14:19 ` Josua Mayer
2024-07-20 14:19 ` [PATCH RFC v3 5/6] phy: mvebu-cp110-utmi: add support for armada-380 utmi phys Josua Mayer
2024-07-20 14:19 ` Josua Mayer
2024-07-25 6:43 ` Vinod Koul
2024-07-25 6:43 ` Vinod Koul
2024-07-25 8:38 ` Josua Mayer [this message]
2024-07-25 8:38 ` Josua Mayer
2024-07-25 11:03 ` Vinod Koul
2024-07-25 11:03 ` Vinod Koul
2024-07-20 14:19 ` [PATCH RFC v3 6/6] arm: dts: marvell: armada-388-clearfog: add description for usb phys Josua Mayer
2024-07-20 14:19 ` Josua Mayer
2024-07-23 2:57 ` [PATCH RFC v3 0/6] phy: mvebu-cp110-utmi: add support for armada-380 utmi phys Rob Herring (Arm)
2024-07-23 2:57 ` Rob Herring (Arm)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f4835ad8-08c1-49f0-ae85-4f870ad90a8e@solid-run.com \
--to=josua@solid-run.com \
--cc=andrew@lunn.ch \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gregory.clement@bootlin.com \
--cc=kishon@kernel.org \
--cc=kostap@marvell.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux@armlinux.org.uk \
--cc=robh@kernel.org \
--cc=sebastian.hesselbarth@gmail.com \
--cc=vkoul@kernel.org \
--cc=yazan.shhady@solid-run.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.