Re: [PATCH v2 2/2] usb: gadget: udc: add Axiado AX3000 and AX3005 UDC driver

From: Petar Stepanovic

Date: Thu Oct 15 2026 - 04:34:43 EST



On 8/24/2026 5:33 PM, Philipp Zabel wrote:
> On Mo, 2026-08-17 at 22:57 -0700, Naveen Kumar Rajgiri Bassappa wrote:
>> Add a driver for the USB device controller integrated into the Axiado
>> AX3000 and AX3005 SoCs.
>>
>> The controller is based on the Corigine USB 3.1 device IP core and uses an
>> xHCI-like programming model with a command ring, an event ring, and
>> per-endpoint transfer rings composed of Transfer Request Blocks (TRBs).
>>
>> The driver implements the USB gadget and endpoint operations, including
>> endpoint enable and disable, request queue and dequeue, halt and wedge
>> handling, and standard endpoint 0 control requests.
>>
>> It supports High-Speed and SuperSpeed operation, control, bulk,
>> interrupt, and isochronous transfers, and scatter-gather requests.
>>
>> Signed-off-by: Naveen Kumar Rajgiri Bassappa <rbnaveenkumar@xxxxxxxxxx>
>> ---
>> MAINTAINERS | 2 +
>> drivers/usb/gadget/udc/Kconfig | 14 +
>> drivers/usb/gadget/udc/Makefile | 1 +
>> drivers/usb/gadget/udc/crg_udc.c | 4491 ++++++++++++++++++++++++++++++++++++++
>> drivers/usb/gadget/udc/crg_udc.h | 355 +++
>> 5 files changed, 4863 insertions(+)
>>
> [...]
>> diff --git a/drivers/usb/gadget/udc/crg_udc.c b/drivers/usb/gadget/udc/crg_udc.c
>> new file mode 100644
>> index 000000000000..bb3ed394d984
>> --- /dev/null
>> +++ b/drivers/usb/gadget/udc/crg_udc.c
>> @@ -0,0 +1,4491 @@
> [...]
>> +static int crg_udc_init_hw(struct crg_gadget_dev *crg_udc)
>> +{
>> + struct device *dev = crg_udc->dev;
>> + int ret;
>> +
>> + crg_udc->clk = devm_clk_get_optional(dev, NULL);
>> + if (IS_ERR(crg_udc->clk))
>> + return dev_err_probe(dev, PTR_ERR(crg_udc->clk),
>> + "failed to get clock\n");
>> +
>> + ret = clk_prepare_enable(crg_udc->clk);
>> + if (ret)
>> + return dev_err_probe(dev, ret, "failed to enable clock\n");
>> +
>> + ret = devm_add_action_or_reset(dev, crg_udc_clk_disable, crg_udc->clk);
>> + if (ret)
>> + return ret;
>> +
>> + crg_udc->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
>> + if (IS_ERR(crg_udc->rst))
>> + return dev_err_probe(dev, PTR_ERR(crg_udc->rst),
>> + "failed to get reset\n");
>> +
>> + ret = reset_control_deassert(crg_udc->rst);
>> + if (ret)
>> + return dev_err_probe(dev, ret, "failed to deassert reset\n");
>> +
>> + ret = devm_add_action_or_reset(dev, crg_udc_reset_assert, crg_udc->rst);
>> + if (ret)
>> + return ret;
> This looks like it could be simplified with
> devm_reset_control_get_optional_exclusive_deasserted()
>
Agreed. We'll use devm_reset_control_get_optional_exclusive_deasserted() in the next revision.

Best regards,
Petar Stepanovic