rp2040: fix usb device enumeration (RP2040-E5)
Этот коммит содержится в:
родитель
8d4d3c6201
коммит
762a6f1256
2 изменённых файлов: 102 добавлений и 0 удалений
|
@ -130,6 +130,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
|
||||||
rp.USBCTRL_REGS.ADDR_ENDP.Set(0)
|
rp.USBCTRL_REGS.ADDR_ENDP.Set(0)
|
||||||
|
|
||||||
initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)
|
initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)
|
||||||
|
fixRP2040UsbDeviceEnumeration()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
101
src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go
Обычный файл
101
src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go
Обычный файл
|
@ -0,0 +1,101 @@
|
||||||
|
//go:build rp2040
|
||||||
|
// +build rp2040
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/rp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c
|
||||||
|
func fixRP2040UsbDeviceEnumeration() {
|
||||||
|
|
||||||
|
// Wait SE0 phase will call force ls_j phase which will call finish phase
|
||||||
|
hw_enumeration_fix_wait_se0()
|
||||||
|
}
|
||||||
|
|
||||||
|
func hw_enumeration_fix_wait_se0() {
|
||||||
|
// Wait for SE0 to end (i.e. the host to stop resetting). This reset can last quite long.
|
||||||
|
// 10-15ms so we are going to set a timer callback.
|
||||||
|
|
||||||
|
// if timer pool disabled, or no timer available, have to busy wait.
|
||||||
|
hw_enumeration_fix_busy_wait_se0()
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
LS_SE0 = 0b00
|
||||||
|
LS_J = 0b01
|
||||||
|
LS_K = 0b10
|
||||||
|
LS_SE1 = 0b11
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dp = 15
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
gpioCtrlPrev uint32
|
||||||
|
padCtrlPrev uint32
|
||||||
|
)
|
||||||
|
|
||||||
|
func hw_enumeration_fix_busy_wait_se0() {
|
||||||
|
for ((rp.USBCTRL_REGS.SIE_STATUS.Get() & rp.USBCTRL_REGS_SIE_STATUS_LINE_STATE_Msk) >> rp.USBCTRL_REGS_SIE_STATUS_LINE_STATE_Pos) == LS_SE0 {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now force LS_J (next stage of fix)
|
||||||
|
hw_enumeration_fix_force_ls_j()
|
||||||
|
}
|
||||||
|
|
||||||
|
func hw_enumeration_fix_force_ls_j() {
|
||||||
|
// DM must be 0 for this to work. This is true if it is selected
|
||||||
|
// to any other function. fn 8 on this pin is only for debug so shouldn't
|
||||||
|
// be selected
|
||||||
|
|
||||||
|
// Before changing any pin state, take a copy of the current gpio control register
|
||||||
|
gpioCtrlPrev = ioBank0.io[dp].ctrl.Get()
|
||||||
|
// Also take a copy of the pads register
|
||||||
|
padCtrlPrev = padsBank0.io[dp].Get()
|
||||||
|
|
||||||
|
// Enable bus keep and force pin to tristate, so USB DP muxing doesn't affect
|
||||||
|
// pin state
|
||||||
|
padsBank0.io[dp].SetBits(rp.PADS_BANK0_GPIO0_PUE | rp.PADS_BANK0_GPIO0_PDE)
|
||||||
|
ioBank0.io[dp].ctrl.ReplaceBits(rp.IO_BANK0_GPIO0_CTRL_OEOVER_DISABLE, rp.IO_BANK0_GPIO0_CTRL_OEOVER_Msk>>rp.IO_BANK0_GPIO0_CTRL_OEOVER_Pos, rp.IO_BANK0_GPIO0_CTRL_OEOVER_Pos)
|
||||||
|
|
||||||
|
// Select function 8 (USB debug muxing) without disturbing other controls
|
||||||
|
ioBank0.io[dp].ctrl.ReplaceBits(8, rp.IO_BANK0_GPIO0_CTRL_FUNCSEL_Msk>>rp.IO_BANK0_GPIO0_CTRL_FUNCSEL_Pos, rp.IO_BANK0_GPIO0_CTRL_FUNCSEL_Pos)
|
||||||
|
|
||||||
|
// J state is a differential 1 for a full speed device so
|
||||||
|
// DP = 1 and DM = 0. Don't actually need to set DM low as it
|
||||||
|
// is already gated assuming it isn't funcseld.
|
||||||
|
ioBank0.io[dp].ctrl.ReplaceBits(rp.IO_BANK0_GPIO1_CTRL_INOVER_HIGH, rp.IO_BANK0_GPIO1_CTRL_INOVER_Msk>>rp.IO_BANK0_GPIO1_CTRL_INOVER_Pos, rp.IO_BANK0_GPIO1_CTRL_INOVER_Pos)
|
||||||
|
|
||||||
|
// Force PHY pull up to stay before switching away from the phy
|
||||||
|
rp.USBCTRL_REGS.USBPHY_DIRECT.SetBits(rp.USBCTRL_REGS_USBPHY_DIRECT_DP_PULLUP_EN)
|
||||||
|
rp.USBCTRL_REGS.USBPHY_DIRECT_OVERRIDE.SetBits(rp.USBCTRL_REGS_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN)
|
||||||
|
|
||||||
|
// Switch to GPIO phy with LS_J forced
|
||||||
|
rp.USBCTRL_REGS.USB_MUXING.Set(rp.USBCTRL_REGS_USB_MUXING_TO_DIGITAL_PAD | rp.USBCTRL_REGS_USB_MUXING_SOFTCON)
|
||||||
|
|
||||||
|
// LS_J is now forced but while loop here just to check
|
||||||
|
|
||||||
|
// if timer pool disabled, or no timer available, have to busy wait.
|
||||||
|
hw_enumeration_fix_finish()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func hw_enumeration_fix_finish() {
|
||||||
|
// Should think we are connected now
|
||||||
|
for (rp.USBCTRL_REGS.SIE_STATUS.Get() & rp.USBCTRL_REGS_SIE_STATUS_CONNECTED) != rp.USBCTRL_REGS_SIE_STATUS_CONNECTED {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch back to USB phy
|
||||||
|
rp.USBCTRL_REGS.USB_MUXING.Set(rp.USBCTRL_REGS_USB_MUXING_TO_PHY | rp.USBCTRL_REGS_USB_MUXING_SOFTCON)
|
||||||
|
|
||||||
|
// Get rid of DP pullup override
|
||||||
|
rp.USBCTRL_REGS.USBPHY_DIRECT_OVERRIDE.ClearBits(rp.USBCTRL_REGS_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN)
|
||||||
|
|
||||||
|
// Finally, restore the gpio ctrl value back to GPIO15
|
||||||
|
ioBank0.io[dp].ctrl.Set(gpioCtrlPrev)
|
||||||
|
// Restore the pad ctrl value
|
||||||
|
padsBank0.io[dp].Set(padCtrlPrev)
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче