diff --git a/src/machine/machine_rp2040.go b/src/machine/machine_rp2040.go index fcff58bc..ca4ea7f2 100644 --- a/src/machine/machine_rp2040.go +++ b/src/machine/machine_rp2040.go @@ -4,6 +4,7 @@ package machine import ( "device/rp" + "unsafe" ) const deviceName = rp.Device @@ -96,3 +97,20 @@ func CurrentCore() int { // NumCores returns number of cores available on the device. func NumCores() int { return 2 } + +// ChipVersion returns the version of the chip. 1 is returned for B0 and B1 +// chip. +func ChipVersion() uint8 { + const ( + SYSINFO_BASE = 0x40000000 + SYSINFO_CHIP_ID_OFFSET = 0x00000000 + SYSINFO_CHIP_ID_REVISION_BITS = 0xf0000000 + SYSINFO_CHIP_ID_REVISION_LSB = 28 + ) + + // First register of sysinfo is chip id + chipID := *(*uint32)(unsafe.Pointer(uintptr(SYSINFO_BASE + SYSINFO_CHIP_ID_OFFSET))) + // Version 1 == B0/B1 + version := (chipID & SYSINFO_CHIP_ID_REVISION_BITS) >> SYSINFO_CHIP_ID_REVISION_LSB + return uint8(version) +} diff --git a/src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go b/src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go index dd7e0c42..6412ada0 100644 --- a/src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go +++ b/src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go @@ -10,8 +10,19 @@ import ( // 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() + // Actually check for B0/B1 h/w + if ChipVersion() == 1 { + // After coming out of reset, the hardware expects 800us of LS_J (linestate J) time + // before it will move to the connected state. However on a hub that broadcasts packets + // for other devices this isn't the case. The plan here is to wait for the end of the bus + // reset, force an LS_J for 1ms and then switch control back to the USB phy. Unfortunately + // this requires us to use GPIO15 as there is no other way to force the input path. + // We only need to force DP as DM can be left at zero. It will be gated off by GPIO + // logic if it isn't func selected. + + // 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() {