From: Sascha Hauer <s.hauer@pengutronix.de>
To: Barebox List <barebox@lists.infradead.org>
Subject: [PATCH 17/42] usb: gadget: fsl_udc: Add PBL image loading support
Date: Mon, 17 Feb 2020 13:45:58 +0100 [thread overview]
Message-ID: <20200217124623.14520-18-s.hauer@pengutronix.de> (raw)
In-Reply-To: <20200217124623.14520-1-s.hauer@pengutronix.de>
For boards that do the RAM setup in code we can up to now only download
the PBL part to SRAM. This patch adds support for downloading the rest
of the image after the RAM has been configured.
The ROM is nice enough to leave the USB controller initialized after a
download, so we don't have to reinitialize it, but can simply continue to
use the controller. Like all two-staged loading processes on i.MX this
needs board support, it will only work when a board calls
imx_barebox_load_usb() or one of the SoC specific variants.
This needs the host counterpart in imx-usb-loader which is done in the
next patch.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/usb/Makefile | 2 +-
drivers/usb/gadget/Kconfig | 3 +
drivers/usb/gadget/Makefile | 1 +
drivers/usb/gadget/fsl_udc_pbl.c | 210 +++++++++++++++++++++++++++++++
include/soc/fsl/fsl_udc.h | 6 +
5 files changed, 221 insertions(+), 1 deletion(-)
create mode 100644 drivers/usb/gadget/fsl_udc_pbl.c
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 9e98099502..64d4bddad4 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -2,9 +2,9 @@ obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_IMX_CHIPIDEA) += imx/
obj-$(CONFIG_USB_DWC3) += dwc3/
obj-$(CONFIG_USB_MUSB) += musb/
-obj-$(CONFIG_USB_GADGET) += gadget/
obj-$(CONFIG_USB_STORAGE) += storage/
obj-y += host/
obj-y += otg/
+obj-y += gadget/
obj-$(CONFIG_USB) += misc/
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 9d6a262038..3c1d7e6f18 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -15,6 +15,9 @@ config USB_GADGET_DRIVER_ARC
default y
select USB_GADGET_DUALSPEED
+config USB_GADGET_DRIVER_ARC_PBL
+ bool
+
config USB_GADGET_DRIVER_AT91
bool
prompt "at91 gadget driver"
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 9ef594575b..27673fcf0e 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -4,5 +4,6 @@ obj-$(CONFIG_USB_GADGET_SERIAL) += u_serial.o serial.o f_serial.o f_acm.o
obj-$(CONFIG_USB_GADGET_DFU) += dfu.o
obj-$(CONFIG_USB_GADGET_FASTBOOT) += f_fastboot.o
obj-$(CONFIG_USB_GADGET_DRIVER_ARC) += fsl_udc.o
+pbl-$(CONFIG_USB_GADGET_DRIVER_ARC_PBL) += fsl_udc_pbl.o
obj-$(CONFIG_USB_GADGET_DRIVER_AT91) += at91_udc.o
obj-$(CONFIG_USB_GADGET_DRIVER_PXA27X) += pxa27x_udc.o
diff --git a/drivers/usb/gadget/fsl_udc_pbl.c b/drivers/usb/gadget/fsl_udc_pbl.c
new file mode 100644
index 0000000000..978adf0667
--- /dev/null
+++ b/drivers/usb/gadget/fsl_udc_pbl.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <common.h>
+#include <usb/ch9.h>
+#include <soc/fsl/fsl_udc.h>
+#include <mach/imx8mm-regs.h>
+
+static void fsl_queue_td(struct usb_dr_device *dr, struct ep_td_struct *dtd,
+ int ep_is_in)
+{
+ int ep_index = 0;
+ int i = ep_index * 2 + ep_is_in;
+ u32 bitmask;
+ volatile struct ep_queue_head *dQH =
+ (void *)(unsigned long)readl(&dr->endpointlistaddr);
+ unsigned long td_dma = (unsigned long)dtd;
+
+ dQH = &dQH[i];
+
+ bitmask = ep_is_in ? (1 << (ep_index + 16)) : (1 << (ep_index));
+
+ dQH->next_dtd_ptr = cpu_to_le32(td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK);
+
+ dQH->size_ioc_int_sts &= cpu_to_le32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
+ | EP_QUEUE_HEAD_STATUS_HALT));
+
+ writel(bitmask, &dr->endpointprime);
+}
+
+static struct ep_td_struct dtd_data __attribute__((aligned(64)));
+static struct ep_td_struct dtd_status __attribute__((aligned(64)));
+
+static int fsl_ep_queue(struct usb_dr_device *dr, struct ep_td_struct *dtd,
+ void *buf, int len)
+{
+ u32 swap_temp;
+
+ memset(dtd, 0, sizeof(*dtd));
+
+ /* Clear reserved field */
+ swap_temp = cpu_to_le32(dtd->size_ioc_sts);
+ swap_temp &= ~DTD_RESERVED_FIELDS;
+ dtd->size_ioc_sts = cpu_to_le32(swap_temp);
+
+ swap_temp = (unsigned long)buf;
+ dtd->buff_ptr0 = cpu_to_le32(swap_temp);
+ dtd->buff_ptr1 = cpu_to_le32(swap_temp + 0x1000);
+ dtd->buff_ptr2 = cpu_to_le32(swap_temp + 0x2000);
+ dtd->buff_ptr3 = cpu_to_le32(swap_temp + 0x3000);
+ dtd->buff_ptr4 = cpu_to_le32(swap_temp + 0x4000);
+
+ /* Fill in the transfer size; set active bit */
+ swap_temp = ((len << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE) | DTD_IOC;
+
+ writel(cpu_to_le32(swap_temp), &dtd->size_ioc_sts);
+
+ dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE);
+
+ fsl_queue_td(dr, dtd, len ? 0 : 1);
+
+ return 0;
+}
+
+enum state {
+ state_init = 0,
+ state_expect_command,
+ state_transfer_data,
+ state_complete,
+};
+
+#define MAX_TRANSFER_SIZE 2048
+
+static enum state state;
+static uint8_t databuf[MAX_TRANSFER_SIZE] __attribute__((aligned(64)));
+static int actual;
+static int to_transfer;
+static void *image;
+
+static void tripwire_handler(struct usb_dr_device *dr, u8 ep_num)
+{
+ uint32_t val;
+ struct ep_queue_head *qh;
+ struct ep_queue_head *dQH = (void *)(unsigned long)readl(&dr->endpointlistaddr);
+ struct usb_ctrlrequest *ctrl;
+
+ qh = &dQH[ep_num * 2];
+
+ val = readl(&dr->endptsetupstat);
+ val |= 1 << ep_num;
+ writel(val, &dr->endptsetupstat);
+
+ do {
+ val = readl(&dr->usbcmd);
+ val |= USB_CMD_SUTW;
+ writel(val, &dr->usbcmd);
+
+ ctrl = (void *)qh->setup_buffer;
+ if ((ctrl->wValue & 0xff) == 1)
+ state = state_expect_command;
+
+ } while (!(readl(&dr->usbcmd) & USB_CMD_SUTW));
+
+ val = readl(&dr->usbcmd);
+ val &= ~USB_CMD_SUTW;
+ writel(val, &dr->usbcmd);
+
+ fsl_ep_queue(dr, &dtd_data, databuf, MAX_TRANSFER_SIZE);
+}
+
+static void dtd_complete_irq(struct usb_dr_device *dr)
+{
+ struct ep_td_struct *dtd = &dtd_data;
+ u32 bit_pos;
+ int len;
+
+ /* Clear the bits in the register */
+ bit_pos = readl(&dr->endptcomplete);
+ writel(bit_pos, &dr->endptcomplete);
+
+ if (!(bit_pos & 1))
+ return;
+
+ len = MAX_TRANSFER_SIZE -
+ (le32_to_cpu(dtd->size_ioc_sts) >> DTD_LENGTH_BIT_POS);
+
+ if (state == state_expect_command) {
+ state = state_transfer_data;
+ to_transfer = databuf[8] << 24 |
+ databuf[9] << 16 |
+ databuf[10] << 8 |
+ databuf[11];
+ } else {
+ memcpy(image + actual, &databuf[1], len - 1);
+ actual += len - 1;
+ to_transfer -= len - 1;
+
+ if (to_transfer == 0)
+ state = state_complete;
+ }
+
+ fsl_ep_queue(dr, &dtd_status, NULL, 0);
+}
+
+static int usb_irq(struct usb_dr_device *dr)
+{
+ uint32_t irq_src = readl(&dr->usbsts);
+
+ irq_src &= ~0x80;
+
+ if (!irq_src)
+ return -EAGAIN;
+
+ /* Clear notification bits */
+ writel(irq_src, &dr->usbsts);
+
+ /* USB Interrupt */
+ if (irq_src & USB_STS_INT) {
+ /* Setup package, we only support ep0 as control ep */
+ if (readl(&dr->endptsetupstat) & EP_SETUP_STATUS_EP0)
+ tripwire_handler(dr, 0);
+
+ /* completion of dtd */
+ if (readl(&dr->endptcomplete))
+ dtd_complete_irq(dr);
+ }
+
+ if (state == state_complete)
+ return 0;
+ else
+ return -EAGAIN;
+}
+
+int imx_barebox_load_usb(void __iomem *dr, void *dest)
+{
+ int ret;
+
+ image = dest;
+
+ while (1) {
+ ret = usb_irq(dr);
+ if (!ret)
+ break;
+ }
+
+ return 0;
+}
+
+int imx_barebox_start_usb(void __iomem *dr, void *dest)
+{
+ void __noreturn (*bb)(void);
+ int ret;
+
+ ret = imx_barebox_load_usb(dr, dest);
+ if (ret)
+ return ret;
+
+ printf("Downloading complete, start barebox\n");
+ bb = dest;
+ bb();
+}
+
+int imx8mm_barebox_load_usb(void *dest)
+{
+ return imx_barebox_load_usb(IOMEM(MX8MM_USB1_BASE_ADDR), dest);
+}
+
+int imx8mm_barebox_start_usb(void *dest)
+{
+ return imx_barebox_start_usb(IOMEM(MX8MM_USB1_BASE_ADDR), dest);
+}
diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
index b401351796..b983f714c5 100644
--- a/include/soc/fsl/fsl_udc.h
+++ b/include/soc/fsl/fsl_udc.h
@@ -374,4 +374,10 @@ struct ep_td_struct {
/* Controller dma boundary */
#define UDC_DMA_BOUNDARY 0x1000
+int imx_barebox_load_usb(void __iomem *dr, void *dest);
+int imx_barebox_start_usb(void __iomem *dr, void *dest);
+
+int imx8mm_barebox_load_usb(void *dest);
+int imx8mm_barebox_start_usb(void *dest);
+
#endif /* __FSL_UDC_H */
--
2.25.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2020-02-17 12:46 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-17 12:45 [PATCH 00/42] Add i.MX8M support Sascha Hauer
2020-02-17 12:45 ` [PATCH 01/42] ARM: i.MX8: Move iomux header to make space for i.MX8MM Sascha Hauer
2020-02-17 12:45 ` [PATCH 02/42] ARM: i.MX8M: Add base addresses common to i.MX8M Sascha Hauer
2020-02-17 12:45 ` [PATCH 03/42] ARM: i.MX8M: add and use imx8mq_setup_pad() Sascha Hauer
2020-02-17 12:45 ` [PATCH 04/42] ARM: i.MX: Drop iomux argument from mx7_setup_pad() Sascha Hauer
2020-02-17 12:45 ` [PATCH 05/42] ARM: i.MX8M: Add iomux header for i.MX8MM Sascha Hauer
2020-02-17 12:45 ` [PATCH 06/42] ARM: i.MX8M: Add imx8mm-regs.h Sascha Hauer
2020-02-17 12:45 ` [PATCH 07/42] ARM: i.MX8M: Add ARCH_IMX8M symbol Sascha Hauer
2020-02-17 12:45 ` [PATCH 08/42] ARM: i.MX: esdctl: rename functions to imx8m_* Sascha Hauer
2020-02-17 12:45 ` [PATCH 09/42] ARM: i.MX8M: Use imx8mq.c for other i.MX8M as well Sascha Hauer
2020-02-17 12:45 ` [PATCH 10/42] ARM: i.MX8M: rename imx8_* bootsource functions to imx8mq_* Sascha Hauer
2020-02-17 12:45 ` [PATCH 11/42] ARM: i.MX8M: Detect serial downloader mode correctly Sascha Hauer
2020-02-17 12:45 ` [PATCH 12/42] HAB: i.MX8M: rename imx8_* functions to imx8m_* Sascha Hauer
2020-02-17 12:45 ` [PATCH 13/42] ARM: i.MX8M: rename i.MX8M specific function Sascha Hauer
2020-02-17 12:45 ` [PATCH 14/42] ARM: i.MX8M: rename functions to be i.MX8M specific Sascha Hauer
2020-02-17 12:45 ` [PATCH 15/42] mci: imx-esdhc-pbl: Add instance 2 for i.MX8MM Sascha Hauer
2020-02-17 12:45 ` [PATCH 16/42] USB: gadget: fsl_udc: move register definitions to header file Sascha Hauer
2020-02-17 12:45 ` Sascha Hauer [this message]
2020-02-17 12:45 ` [PATCH 18/42] usb: gadget: fsl_udc: Fix warnings on 64bit compilation Sascha Hauer
2020-02-17 12:46 ` [PATCH 19/42] usb: imx: Add i.MX8mm support Sascha Hauer
2020-02-17 12:46 ` [PATCH 20/42] serial: imx: Add imx8mm compatible Sascha Hauer
2020-02-17 12:46 ` [PATCH 21/42] mci: imx-esdhc: Add i.MX8mm support Sascha Hauer
2020-02-17 12:46 ` [PATCH 22/42] I2C: i.MX: Add early i2c support for i.MX8M Sascha Hauer
2020-02-17 12:46 ` [PATCH 23/42] clk: imx: Add pll14xx support Sascha Hauer
2020-02-17 12:46 ` [PATCH 24/42] clk: imx: Add imx8m_clk_composite_critical Sascha Hauer
2020-02-17 12:46 ` [PATCH 25/42] clk: imx: Add imx8mm clk driver Sascha Hauer
2020-02-17 12:46 ` [PATCH 26/42] ARM: i.MX: Add SoC namespace to imx7/8m CCM defines Sascha Hauer
2020-02-17 12:46 ` [PATCH 27/42] Add some CCM defines for i.MX8M Sascha Hauer
2020-02-17 12:46 ` [PATCH 28/42] ARM: i.MX8M: rename imx8-ccm-regs.h to imx8m-ccm-regs.h Sascha Hauer
2020-02-17 12:46 ` [PATCH 29/42] ARM: i.MX8M: Add some lowlevel clock functions Sascha Hauer
2020-02-17 12:46 ` [PATCH 30/42] ARM: i.MX7: Add and use function for early UART clock setup Sascha Hauer
2020-02-17 12:46 ` [PATCH 31/42] ARM: i.MX8M: " Sascha Hauer
2020-02-17 12:46 ` [PATCH 32/42] iomux: Add i.MX8MM support Sascha Hauer
2020-02-17 12:46 ` [PATCH 33/42] mfd: Add Rohm bd71837 header file Sascha Hauer
2020-02-17 12:46 ` [PATCH 34/42] scripts: imx-usb-loader: Add 2nd stage loading support Sascha Hauer
2020-02-17 12:46 ` [PATCH 35/42] scripts: imx-usb-loader: Add i.MX8MM support Sascha Hauer
2020-02-17 12:46 ` [PATCH 36/42] ARM: i.MX8MQ boards: Add missing includes Sascha Hauer
2020-02-17 12:46 ` [PATCH 37/42] ARM: i.MX8M: Add DDR controller support Sascha Hauer
2020-02-17 12:46 ` [PATCH 38/42] ARM: i.MX8M: Add TF-A loading support for i.MX8MM Sascha Hauer
2020-02-17 12:46 ` [PATCH 39/42] ARM: i.MX8M: Add i.MX8MM support Sascha Hauer
2020-02-17 12:46 ` [PATCH 40/42] scripts: imx-image: " Sascha Hauer
2020-02-17 12:46 ` [PATCH 41/42] ARM: i.MX: Add i.MX8MM EVK board support Sascha Hauer
2020-02-17 12:46 ` [PATCH 42/42] ARM: i.MX: update imx_v8_defconfig for i.MX8MM Sascha Hauer
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=20200217124623.14520-18-s.hauer@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox