From 995d19ebfd2bac540b4e6968c767d32f5c0e7183 Mon Sep 17 00:00:00 2001 From: Sebastian Holzapfel Date: Mon, 19 Feb 2018 11:23:27 +1100 Subject: [PATCH] efm32hg: usb: add usb support --- include/libopencm3/efm32/hg/memorymap.h | 2 + include/libopencm3/efm32/hg/usb.h | 61 ++++++++++++ include/libopencm3/efm32/usb.h | 2 + include/libopencm3/usb/usbd.h | 1 + lib/efm32/hg/Makefile | 2 + lib/usb/usb_efm32hg.c | 126 ++++++++++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 include/libopencm3/efm32/hg/usb.h create mode 100644 lib/usb/usb_efm32hg.c diff --git a/include/libopencm3/efm32/hg/memorymap.h b/include/libopencm3/efm32/hg/memorymap.h index 615d92ac..25898720 100644 --- a/include/libopencm3/efm32/hg/memorymap.h +++ b/include/libopencm3/efm32/hg/memorymap.h @@ -96,4 +96,6 @@ #define ACMP0_BASE (PERIPH_BASE + 0x01000) #define VCMP_BASE (PERIPH_BASE + 0x00000) +#define USB_OTG_FS_BASE (USB_BASE + 0x3C000) + #endif diff --git a/include/libopencm3/efm32/hg/usb.h b/include/libopencm3/efm32/hg/usb.h new file mode 100644 index 00000000..f4096c27 --- /dev/null +++ b/include/libopencm3/efm32/hg/usb.h @@ -0,0 +1,61 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2015 Kuldeep Singh Dhaka + * Copyright (C) 2018 Seb Holzapfel + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef LIBOPENCM3_EFM32_USB_H +#define LIBOPENCM3_EFM32_USB_H + +#include +#include + +#define USB_CTRL MMIO32(USB_BASE + 0x000) +#define USB_STATUS MMIO32(USB_BASE + 0x004) +#define USB_IF MMIO32(USB_BASE + 0x008) +#define USB_IFS MMIO32(USB_BASE + 0x00C) +#define USB_IFC MMIO32(USB_BASE + 0x010) +#define USB_IEN MMIO32(USB_BASE + 0x014) +#define USB_ROUTE MMIO32(USB_BASE + 0x018) + +/* USB_CTRL */ +/* Bits 31:26 - Reserved */ +#define USB_CTRL_BIASPROGEM23_MASK (0x3 << 24) +/* Bits 23:22 - Reserved */ +#define USB_CTRL_BIASPROGEM01_MASK (0x3 << 20) +/* Bits 19:18 - Reserved */ +#define USB_CTRL_VREGOSEN (1 << 17) +#define USB_CTRL_VREGDIS (1 << 16) +/* Bits 15:10 - Reserved */ +#define USB_CTRL_LEMIDLEEN (1 << 9) +/* Bit 8 - Reserved */ +#define USB_CTRL_LEMPHYCTRL (1 << 7) +/* Bit 6 - Reserved */ +#define USB_CTRL_LEMOSCCTRL_MASK (0x3 << 4) +#define USB_CTRL_LEMOSCCTRL_NONE (0x0 << 4) +#define USB_CTRL_LEMOSCCTRL_GATE (0x1 << 4) +/* Bits 3:2 - Reserved */ +#define USB_CTRL_DMPUAP (1 << 1) +/* Bit 0 - Reserved */ + +/* USB_ROUTE */ +/* Bits 31:3 - Reserved */ +#define USB_ROUTE_DMPUPEN (1 << 2) +/* Bit 1 - Reserved */ +#define USB_ROUTE_PHYPEN (1 << 0) + +#endif diff --git a/include/libopencm3/efm32/usb.h b/include/libopencm3/efm32/usb.h index ce72c237..ac7d48e1 100644 --- a/include/libopencm3/efm32/usb.h +++ b/include/libopencm3/efm32/usb.h @@ -19,6 +19,8 @@ #if defined(EFM32LG) # include +#elif defined(EFM32HG) +# include #else # error "efm32 family not defined." #endif diff --git a/include/libopencm3/usb/usbd.h b/include/libopencm3/usb/usbd.h index c1b5d40a..39244088 100644 --- a/include/libopencm3/usb/usbd.h +++ b/include/libopencm3/usb/usbd.h @@ -59,6 +59,7 @@ extern const usbd_driver st_usbfs_v2_usb_driver; #define otgfs_usb_driver stm32f107_usb_driver #define otghs_usb_driver stm32f207_usb_driver extern const usbd_driver efm32lg_usb_driver; +extern const usbd_driver efm32hg_usb_driver; /* */ /** diff --git a/lib/efm32/hg/Makefile b/lib/efm32/hg/Makefile index 634895e1..8628a1a5 100644 --- a/lib/efm32/hg/Makefile +++ b/lib/efm32/hg/Makefile @@ -41,6 +41,8 @@ TGT_CFLAGS += $(STANDARD_FLAGS) ARFLAGS = rcs OBJS = cmu.o gpio_common_hglg.o timer_common_hglg.o +OBJS += usb.o usb_control.o usb_standard.o usb_msc.o \ + usb_dwc_common.o usb_efm32hg.o VPATH += ../../usb:../:../../cm3:../common diff --git a/lib/usb/usb_efm32hg.c b/lib/usb/usb_efm32hg.c new file mode 100644 index 00000000..96f22c1e --- /dev/null +++ b/lib/usb/usb_efm32hg.c @@ -0,0 +1,126 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2011 Gareth McMullin + * Copyright (C) 2018 Seb Holzapfel + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include "usb_private.h" +#include "usb_dwc_common.h" + +/* Receive FIFO size in 32-bit words. */ +#define RX_FIFO_SIZE 256 + +/* FIXME: EFM32HG has 6 bidirectional endpoints. + * problem is "uint32_t doeptsiz[4];" in usb_private.h */ + +#define ENDPOINT_COUNT 4 + +static struct _usbd_device _usbd_dev; + +/** Initialize the USB device controller hardware of the EFM32HG. */ +static usbd_device *efm32hg_usbd_init(void) +{ + /* Enable peripheral clocks required for USB */ + cmu_periph_clock_enable(CMU_USB); + cmu_periph_clock_enable(CMU_USBC); + cmu_periph_clock_enable(CMU_LE); + + /* Select LFRCO as LFCCLK clock */ + CMU_LFCLKSEL = CMU_LFCLKSEL_LFC_LFRCO; + + /* Enable the USBLE peripheral clock (sits on LFCCLK) */ + cmu_periph_clock_enable(CMU_USBLE); + + /* Calibrate USB based on communications */ + CMU_USHFRCOCONF = CMU_USHFRCOCONF_BAND_48MHZ; + + /* Enable USHFRCO Clock Recovery mode. */ + CMU_USBCRCTRL |= CMU_USBCRCTRL_EN; + + /* Select USHFRCO as clock source for USB */ + cmu_osc_on(USHFRCO); + cmu_wait_for_osc_ready(USHFRCO); + + /* Set up the USB clock source */ + cmu_set_usbclk_source(USHFRCO); + cmu_wait_for_usbclk_selected(USHFRCO); + + /* Turn off all Low Energy Mode (LEM) features. */ + USB_CTRL = 0; + + /* Initialize USB core */ + USB_ROUTE = USB_ROUTE_PHYPEN; /* Enable PHY pins. */ + + /* Wait for AHB idle. */ + while (!(OTG_FS_GRSTCTL & OTG_GRSTCTL_AHBIDL)); + /* Do core soft reset. */ + OTG_FS_GRSTCTL |= OTG_GRSTCTL_CSRST; + while (OTG_FS_GRSTCTL & OTG_GRSTCTL_CSRST); + + /* Explicitly enable DP pullup (not all cores do this by default) */ + OTG_FS_DCTL &= ~OTG_DCTL_SDIS; + + /* Force peripheral only mode. */ + OTG_FS_GUSBCFG |= OTG_GUSBCFG_FDMOD | OTG_GUSBCFG_TRDT_MASK; + + OTG_FS_GINTSTS = OTG_GINTSTS_MMIS; + + /* Full speed device. */ + OTG_FS_DCFG |= OTG_DCFG_DSPD; + + /* Restart the PHY clock. */ + OTG_FS_PCGCCTL = 0; + + OTG_FS_GRXFSIZ = efm32hg_usb_driver.rx_fifo_size; + _usbd_dev.fifo_mem_top = efm32hg_usb_driver.rx_fifo_size; + + /* Unmask interrupts for TX and RX. */ + OTG_FS_GAHBCFG |= OTG_GAHBCFG_GINT; + OTG_FS_GINTMSK = OTG_GINTMSK_ENUMDNEM | + OTG_GINTMSK_RXFLVLM | + OTG_GINTMSK_IEPINT | + OTG_GINTMSK_USBSUSPM | + OTG_GINTMSK_WUIM; + OTG_FS_DAINTMSK = 0xF; + OTG_FS_DIEPMSK = OTG_DIEPMSK_XFRCM; + + return &_usbd_dev; +} + +const struct _usbd_driver efm32hg_usb_driver = { + .init = efm32hg_usbd_init, + .set_address = dwc_set_address, + .ep_setup = dwc_ep_setup, + .ep_reset = dwc_endpoints_reset, + .ep_stall_set = dwc_ep_stall_set, + .ep_stall_get = dwc_ep_stall_get, + .ep_nak_set = dwc_ep_nak_set, + .ep_write_packet = dwc_ep_write_packet, + .ep_read_packet = dwc_ep_read_packet, + .poll = dwc_poll, + .disconnect = dwc_disconnect, + .base_address = USB_OTG_FS_BASE, + .set_address_before_status = 1, + .rx_fifo_size = RX_FIFO_SIZE, +};