mirror of
https://github.com/sakumisu/CherryUSB.git
synced 2025-05-09 00:21:44 +08:00
144 lines
4.5 KiB
C
144 lines
4.5 KiB
C
/*
|
|
* Copyright (c) 2024, sakumisu
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include "bflb_core.h"
|
|
#include "usbh_core.h"
|
|
#include "hardware/usb_v2_reg.h"
|
|
|
|
#ifndef CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
|
#error "usb host must enable CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE"
|
|
#endif
|
|
|
|
#define BLFB_USB_BASE ((uint32_t)0x20072000)
|
|
#define BFLB_PDS_BASE ((uint32_t)0x2000e000)
|
|
|
|
#define PDS_USB_CTL_OFFSET (0x500) /* usb_ctl */
|
|
#define PDS_USB_PHY_CTRL_OFFSET (0x504) /* usb_phy_ctrl */
|
|
|
|
/* 0x500 : usb_ctl */
|
|
#define PDS_REG_USB_SW_RST_N (1 << 0U)
|
|
#define PDS_REG_USB_EXT_SUSP_N (1 << 1U)
|
|
#define PDS_REG_USB_WAKEUP (1 << 2U)
|
|
#define PDS_REG_USB_L1_WAKEUP (1 << 3U)
|
|
#define PDS_REG_USB_DRVBUS_POL (1 << 4U)
|
|
#define PDS_REG_USB_IDDIG (1 << 5U)
|
|
|
|
/* 0x504 : usb_phy_ctrl */
|
|
#define PDS_REG_USB_PHY_PONRST (1 << 0U)
|
|
#define PDS_REG_USB_PHY_OSCOUTEN (1 << 1U)
|
|
#define PDS_REG_USB_PHY_XTLSEL_SHIFT (2U)
|
|
#define PDS_REG_USB_PHY_XTLSEL_MASK (0x3 << PDS_REG_USB_PHY_XTLSEL_SHIFT)
|
|
#define PDS_REG_USB_PHY_OUTCLKSEL (1 << 4U)
|
|
#define PDS_REG_USB_PHY_PLLALIV (1 << 5U)
|
|
#define PDS_REG_PU_USB20_PSW (1 << 6U)
|
|
|
|
#define USB_SOF_TIMER_MASK_AFTER_RESET_HS (0x44C)
|
|
#define USB_SOF_TIMER_MASK_AFTER_RESET_FS (0x2710)
|
|
|
|
extern void USBH_IRQHandler(uint8_t busid);
|
|
|
|
void USBH_IRQ(int irq, void *arg) {
|
|
USBH_IRQHandler(0);
|
|
}
|
|
|
|
static void bflb_usb_phy_init(void)
|
|
{
|
|
uint32_t regval;
|
|
|
|
/* USB_PHY_CTRL[3:2] reg_usb_phy_xtlsel=0 */
|
|
/* 2000e504 = 0x40; #100; USB_PHY_CTRL[6] reg_pu_usb20_psw=1 (VCC33A) */
|
|
/* 2000e504 = 0x41; #500; USB_PHY_CTRL[0] reg_usb_phy_ponrst=1 */
|
|
/* 2000e500 = 0x20; #100; USB_CTL[0] reg_usb_sw_rst_n=0 */
|
|
/* 2000e500 = 0x22; #500; USB_CTL[1] reg_usb_ext_susp_n=1 */
|
|
/* 2000e500 = 0x23; #100; USB_CTL[0] reg_usb_sw_rst_n=1 */
|
|
/* #1.2ms; wait UCLK */
|
|
/* wait(soc616_b0.usb_uclk); */
|
|
|
|
regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
|
|
regval &= ~PDS_REG_USB_PHY_XTLSEL_MASK;
|
|
putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
|
|
|
|
regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
|
|
regval |= PDS_REG_PU_USB20_PSW;
|
|
putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
|
|
|
|
regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
|
|
regval |= PDS_REG_USB_PHY_PONRST;
|
|
putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
|
|
|
|
/* greater than 5T */
|
|
bflb_mtimer_delay_us(1);
|
|
|
|
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
regval &= ~PDS_REG_USB_SW_RST_N;
|
|
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
|
|
/* greater than 5T */
|
|
bflb_mtimer_delay_us(1);
|
|
|
|
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
regval |= PDS_REG_USB_EXT_SUSP_N;
|
|
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
|
|
/* wait UCLK 1.2ms */
|
|
bflb_mtimer_delay_ms(3);
|
|
|
|
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
regval |= PDS_REG_USB_SW_RST_N;
|
|
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
|
|
bflb_mtimer_delay_ms(2);
|
|
}
|
|
|
|
void usb_hc_low_level_init(struct usbh_bus *bus)
|
|
{
|
|
uint32_t regval;
|
|
|
|
bflb_usb_phy_init();
|
|
|
|
bflb_irq_attach(37, USBH_IRQ, NULL);
|
|
bflb_irq_enable(37);
|
|
|
|
/* enable device-A for host */
|
|
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
regval &= ~PDS_REG_USB_IDDIG;
|
|
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
|
|
|
|
regval = getreg32(BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
|
|
regval |= USB_A_BUS_DROP_HOV;
|
|
regval &= ~USB_A_BUS_REQ_HOV;
|
|
putreg32(regval, BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
|
|
|
|
bflb_mtimer_delay_ms(10);
|
|
|
|
/* enable vbus and bus control */
|
|
regval = getreg32(BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
|
|
regval &= ~USB_A_BUS_DROP_HOV;
|
|
regval |= USB_A_BUS_REQ_HOV;
|
|
putreg32(regval, BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
|
|
|
|
regval = getreg32(BLFB_USB_BASE + USB_GLB_INT_OFFSET);
|
|
regval |= USB_MDEV_INT;
|
|
regval |= USB_MOTG_INT;
|
|
regval &= ~USB_MHC_INT;
|
|
putreg32(regval, BLFB_USB_BASE + USB_GLB_INT_OFFSET);
|
|
}
|
|
|
|
uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
|
|
{
|
|
uint8_t speed = 3;
|
|
|
|
speed = (getreg32(BLFB_USB_BASE + USB_OTG_CSR_OFFSET) & USB_SPD_TYP_HOV_POV_MASK) >> USB_SPD_TYP_HOV_POV_SHIFT;
|
|
|
|
if (speed == 0) {
|
|
return USB_SPEED_FULL;
|
|
} else if (speed == 1) {
|
|
return USB_SPEED_LOW;
|
|
} else if (speed == 2) {
|
|
return USB_SPEED_HIGH;
|
|
}
|
|
return USB_SPEED_HIGH;
|
|
}
|