> Date: Fri, 14 Jul 2023 23:30:43 +0200
> From: Marek Vasut <[email protected]>

Hi Marek,

Your suggestions are reasonable, but would make the driver deviate
further from its Linux equivalent:

  
https://github.com/AsahiLinux/linux/blob/asahi/drivers/usb/host/xhci-pci-asmedia.c

Right now I can actually easily diff the two drivers to pick up
improvements.  Changing things the way you suggest would make that
harder.

Cheers,

Mark


> On 7/14/23 22:43, Mark Kettenis wrote:
> > The ASMedia XHCI controller found on some of the Apple Silicon
> > machines needs firmware to operate.  Use the file system
> > firmware loader interface to read the firmware and load it
> > onto the controller.  This allows keyboards connected to the
> > type-A ports on these machines to function in U-Boot.
> > 
> > Signed-off-by: Mark Kettenis <[email protected]>
> > ---
> >   MAINTAINERS                         |   1 +
> >   drivers/usb/host/Kconfig            |  11 +
> >   drivers/usb/host/Makefile           |   1 +
> >   drivers/usb/host/xhci-pci-asmedia.c | 394 ++++++++++++++++++++++++++++
> >   drivers/usb/host/xhci-pci.c         |   9 +
> >   include/usb/xhci.h                  |   3 +
> >   6 files changed, 419 insertions(+)
> >   create mode 100644 drivers/usb/host/xhci-pci-asmedia.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 2477923a52..0acf04fff8 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -124,6 +124,7 @@ F:      drivers/iommu/apple_dart.c
> >   F:        drivers/nvme/nvme_apple.c
> >   F:        drivers/pci/pcie_apple.c
> >   F:        drivers/pinctrl/pinctrl-apple.c
> > +F: drivers/usb/host/xhci-pci-asmedia.c
> >   F:        drivers/watchdog/apple_wdt.c
> >   F:        include/configs/apple.h
> >   
> > diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> > index 1a883babf4..ad8dfabeeb 100644
> > --- a/drivers/usb/host/Kconfig
> > +++ b/drivers/usb/host/Kconfig
> > @@ -95,6 +95,17 @@ config USB_XHCI_PCI
> >     help
> >       Enables support for the PCI-based xHCI controller.
> >   
> > +config USB_XHCI_PCI_ASMEDIA
> > +   bool "Support for ASMedia xHCI USB controller"
> > +   depends on USB_XHCI_PCI
> > +   default y if ARCH_APPLE
> > +   imply FS_LOADER
> > +   help
> > +     Enables support for loading firmware for the ASMedia xHCI
> > +     controller.  This is needed on Apple Silicon machines that
> > +     contain ASMedia xHCI controllers without the full USB
> > +     firmware.
> > +
> >   config USB_XHCI_RCAR
> >     bool "Renesas RCar USB 3.0 support"
> >     default y
> > diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> > index 8dad36f936..2aa2d80263 100644
> > --- a/drivers/usb/host/Makefile
> > +++ b/drivers/usb/host/Makefile
> > @@ -52,6 +52,7 @@ obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o
> >   obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
> >   obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
> >   obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
> > +obj-$(CONFIG_USB_XHCI_PCI_ASMEDIA) += xhci-pci-asmedia.o
> >   obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o
> >   obj-$(CONFIG_USB_XHCI_STI) += dwc3-sti-glue.o
> >   obj-$(CONFIG_USB_XHCI_OCTEON) += dwc3-octeon-glue.o
> > diff --git a/drivers/usb/host/xhci-pci-asmedia.c 
> > b/drivers/usb/host/xhci-pci-asmedia.c
> > new file mode 100644
> > index 0000000000..cc1d25bde2
> > --- /dev/null
> > +++ b/drivers/usb/host/xhci-pci-asmedia.c
> > @@ -0,0 +1,394 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR MIT
> > +/*
> > + * ASMedia xHCI firmware loader
> > + * Copyright (C) The Asahi Linux Contributors
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device_compat.h>
> > +#include <fs_loader.h>
> > +#include <linux/iopoll.h>
> > +#include <pci.h>
> > +#include <usb.h>
> > +#include <usb/xhci.h>
> > +
> > +/* Configuration space registers */
> > +#define ASMT_CFG_CONTROL           0xe0
> > +#define ASMT_CFG_CONTROL_WRITE             BIT(1)
> > +#define ASMT_CFG_CONTROL_READ              BIT(0)
> > +
> > +#define ASMT_CFG_SRAM_ADDR         0xe2
> > +
> > +#define ASMT_CFG_SRAM_ACCESS               0xef
> > +#define ASMT_CFG_SRAM_ACCESS_READ  BIT(6)
> > +#define ASMT_CFG_SRAM_ACCESS_ENABLE        BIT(7)
> > +
> > +#define ASMT_CFG_DATA_READ0                0xf0
> > +#define ASMT_CFG_DATA_READ1                0xf4
> > +
> > +#define ASMT_CFG_DATA_WRITE0               0xf8
> > +#define ASMT_CFG_DATA_WRITE1               0xfc
> > +
> > +#define ASMT_CMD_GET_FWVER         0x8000060840
> > +#define ASMT_FWVER_ROM                     0x010250090816
> > +
> > +/* BAR0 registers */
> > +#define ASMT_REG_ADDR                      0x3000
> > +
> > +#define ASMT_REG_WDATA                     0x3004
> > +#define ASMT_REG_RDATA                     0x3008
> > +
> > +#define ASMT_REG_STATUS                    0x3009
> > +#define ASMT_REG_STATUS_BUSY               BIT(7)
> > +
> > +#define ASMT_REG_CODE_WDATA                0x3010
> > +#define ASMT_REG_CODE_RDATA                0x3018
> > +
> > +#define ASMT_MMIO_CPU_MISC         0x500e
> > +#define ASMT_MMIO_CPU_MISC_CODE_RAM_WR     BIT(0)
> > +
> > +#define ASMT_MMIO_CPU_MODE_NEXT            0x5040
> > +#define ASMT_MMIO_CPU_MODE_CUR             0x5041
> > +
> > +#define ASMT_MMIO_CPU_MODE_RAM             BIT(0)
> > +#define ASMT_MMIO_CPU_MODE_HALFSPEED       BIT(1)
> > +
> > +#define ASMT_MMIO_CPU_EXEC_CTRL            0x5042
> > +#define ASMT_MMIO_CPU_EXEC_CTRL_RESET      BIT(0)
> > +#define ASMT_MMIO_CPU_EXEC_CTRL_HALT       BIT(1)
> > +
> > +#define TIMEOUT_USEC                       10000
> > +#define RESET_TIMEOUT_USEC         500000
> > +
> > +static int asmedia_mbox_tx(struct udevice *pdev, u64 data)
> > +{
> > +   u8 op;
> > +   int i;
> > +
> > +   for (i = 0; i < TIMEOUT_USEC; i++) {
> > +           dm_pci_read_config8(pdev, ASMT_CFG_CONTROL, &op);
> > +           if (!(op & ASMT_CFG_CONTROL_WRITE))
> > +                   break;
> > +           udelay(1);
> 
> Would it be possible to use the wait_for_bit*() here ?
> Or read*poll*timeout() ?
> 
> > +   }
> > +
> > +   if (op & ASMT_CFG_CONTROL_WRITE) {
> > +           dev_err(pdev,
> > +                   "Timed out on mailbox tx: 0x%llx\n",
> > +                   data);
> > +           return -ETIMEDOUT;
> > +   }
> > +
> > +   dm_pci_write_config32(pdev, ASMT_CFG_DATA_WRITE0, data);
> > +   dm_pci_write_config32(pdev, ASMT_CFG_DATA_WRITE1, data >> 32);
> > +   dm_pci_write_config8(pdev, ASMT_CFG_CONTROL,
> > +                        ASMT_CFG_CONTROL_WRITE);
> 
> [...]
> 
> > +static u8 asmedia_read_reg(struct udevice *pdev, struct xhci_hccr *hccr,
> > +                      u16 addr)
> > +{
> > +   void __iomem *regs = (void *)hccr;
> > +   u8 status;
> > +   int ret;
> > +
> > +   ret = readb_poll_sleep_timeout(regs + ASMT_REG_STATUS, status,
> > +                                  !(status & ASMT_REG_STATUS_BUSY),
> > +                                  1000, TIMEOUT_USEC);
> > +
> > +   if (ret) {
> > +           dev_err(pdev,
> > +                   "Read reg wait timed out ([%04x])\n", addr);
> > +           return ~0;
> 
> It might make sense to return the value as parameter, and make return 
> value of this function into integer, so error codes can be returned that 
> way.
> 
> [...]
> 

Reply via email to