Compare commits

...

2 Commits

Author SHA1 Message Date
alnyan aba41cb5b2 WIP2 2025-09-29 14:01:54 +03:00
alnyan 475bf90eb9 WIP 2025-09-29 13:18:26 +03:00
9 changed files with 639 additions and 0 deletions
Generated
+20
View File
@@ -2872,6 +2872,25 @@ dependencies = [
"yggdrasil-abi",
]
[[package]]
name = "ygg_driver_usb_dwc2"
version = "0.1.0"
dependencies = [
"async-trait",
"atomic_enum",
"bytemuck",
"device-api",
"device-tree",
"futures-util",
"libk",
"libk-mm",
"libk-util",
"log",
"tock-registers",
"ygg_driver_usb",
"yggdrasil-abi",
]
[[package]]
name = "ygg_driver_usb_xhci"
version = "0.1.0"
@@ -3029,6 +3048,7 @@ dependencies = [
"ygg_driver_nvme",
"ygg_driver_pci",
"ygg_driver_usb",
"ygg_driver_usb_dwc2",
"ygg_driver_usb_xhci",
"ygg_driver_virtio_blk",
"ygg_driver_virtio_gpu",
+1
View File
@@ -58,6 +58,7 @@ device-tree.workspace = true
kernel-arch-aarch64.workspace = true
ygg_driver_bsp_arm.path = "driver/bsp/arm"
ygg_driver_bsp_bcm283x.path = "driver/bsp/bcm283x"
ygg_driver_usb_dwc2.path = "driver/usb/dwc2"
[target.'cfg(target_arch = "riscv64")'.dependencies]
device-tree.workspace = true
+21
View File
@@ -0,0 +1,21 @@
[package]
name = "ygg_driver_usb_dwc2"
version = "0.1.0"
edition = "2024"
[dependencies]
yggdrasil-abi = { path = "../../../../lib/abi" }
device-api = { path = "../../../lib/device-api", features = ["derive"] }
ygg_driver_usb = { path = "../../bus/usb" }
device-tree = { path = "../../../lib/device-tree" }
libk-util = { path = "../../../libk/libk-util" }
libk-mm = { path = "../../../libk/libk-mm" }
libk = { path = "../../../libk" }
async-trait.workspace = true
log.workspace = true
atomic_enum.workspace = true
tock-registers.workspace = true
bytemuck.workspace = true
futures-util.workspace = true
+222
View File
@@ -0,0 +1,222 @@
#![no_std]
use core::{
sync::atomic::{AtomicBool, AtomicU32},
time::Duration,
};
use alloc::sync::Arc;
use device_api::{
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqVector},
};
use futures_util::task::AtomicWaker;
use libk::{error::Error, task::runtime};
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
use libk_util::{event::BitmapEvent, sync::IrqSafeSpinlock};
use tock_registers::{
interfaces::{ReadWriteable, Readable, Writeable},
LocalRegisterCopy,
};
use yggdrasil_abi::bitflags;
use crate::{
regs::{PortSpeed, Regs},
vendor::Dwc2Impl,
};
extern crate alloc;
mod regs;
mod vendor;
pub struct Dwc2<H: Dwc2Impl> {
imp: H,
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
name: Arc<str>,
channel_bitmask: AtomicU32,
port_event_mask: BitmapEvent<AtomicWaker>,
}
impl<H: Dwc2Impl + 'static> Dwc2<H> {
pub unsafe fn new<N: Into<Arc<str>>>(
imp: H,
base: PhysicalAddress,
name: N,
) -> Result<Self, Error> {
let name = name.into();
let regs = IrqSafeSpinlock::new(unsafe { DeviceMemoryIo::map(base, Default::default()) }?);
Ok(Self {
imp,
regs,
name,
channel_bitmask: AtomicU32::new(0),
port_event_mask: BitmapEvent::new(AtomicWaker::new()),
})
}
fn signal_events(&self, channels: u16, ports: u32) {
self.port_event_mask
.signal(((channels as u64) << 32) | (ports as u64));
}
async fn setup_port(self: Arc<Self>, speed: PortSpeed) -> Result<(), Error> {
log::info!("{}: setup port", self.name);
todo!()
}
async fn wait_for_port_event(&self) -> LocalRegisterCopy<u32, regs::HPRT::Register> {
LocalRegisterCopy::new(self.port_event_mask.wait_mask(0x2A).await as u32)
}
async fn wait_for_channel_events(&self) -> u16 {
(self.port_event_mask.wait_mask(0xFFFF00000000).await >> 32) as u16
}
async fn wait_for_device(&self) -> PortSpeed {
let hprt = self.regs.lock().HPRT.extract();
// If already connected, begin init, if not, wait for connect change
if !hprt.matches_all(regs::HPRT::PCSTS::SET) {
loop {
let event = self.wait_for_port_event().await;
if event.matches_all(regs::HPRT::PCDET::SET) {
log::info!("{}: port connection detected", self.name);
break;
} else {
log::warn!("{}: unhandled port event {:#x}", self.name, event.get());
}
}
}
log::info!("{}: port connected", self.name);
// Reset the port
{
let regs = self.regs.lock();
regs.HPRT.modify(regs::HPRT::PRST::SET);
}
runtime::sleep(Duration::from_millis(10)).await;
// Clear the reset
{
let regs = self.regs.lock();
regs.HPRT.modify(regs::HPRT::PRST::CLEAR);
}
// Wait for port enable status
loop {
let event = self.wait_for_port_event().await;
if event.matches_all(regs::HPRT::PENA::SET) {
log::info!("{}: port enabled", self.name);
break;
}
if event.matches_all(regs::HPRT::PCSTS::CLEAR) {
todo!("Handle port disconnect");
}
}
let regs = self.regs.lock();
match regs.HPRT.read_as_enum(regs::HPRT::PSPD) {
Some(regs::HPRT::PSPD::Value::LowSpeed) => PortSpeed::LowSpeed,
Some(regs::HPRT::PSPD::Value::FullSpeed) => PortSpeed::FullSpeed,
Some(regs::HPRT::PSPD::Value::HighSpeed) => PortSpeed::HighSpeed,
_ => todo!(),
}
}
async fn softirq(self: Arc<Self>) -> Result<(), Error> {
loop {
// 4-9
let speed = self.wait_for_device().await;
// 10. HFIR setup for PHY clk TODO
// 11. Configure FSLPCS based on step 9 TODO
// 12. GRXFSIZ to configure Rx FIFO size
// 13. HNPTXFSIZ to configure non-periodic Tx FIFO
// 14. HPTXFSIZ to configure periodic Tx FIFO
if let Err(error) = self.clone().setup_port(speed).await {
log::error!("{}: port error {:?}", self.name, error);
}
}
}
async fn setup(self: Arc<Self>) -> Result<(), Error> {
log::info!("{}: init", self.name);
let regs = self.regs.lock();
regs.soft_reset(Duration::from_secs(1)).await?;
// Common setup
regs.GAHBCFG
.write(regs::GAHBCFG::GINTMSK::SET + regs::GAHBCFG::DMAEN::SET);
// GUSBCTL
// TODO HNP/SRP capability?
// TODO OTG_FS/OTG_HS timeout calibration
// TODO USB turnaround time
regs.GINTMSK.write(
regs::GINTMSK::OTGINT::SET
+ regs::GINTMSK::MMISM::SET
+ regs::GINTMSK::USBRST::SET
+ regs::GINTMSK::ENUMDNEM::SET
+ regs::GINTMSK::OEPINT::SET
+ regs::GINTMSK::IEPINT::SET
// + regs::GINTMSK::PRTIM::SET
+ regs::GINTMSK::DISCINT::SET,
);
let mode = if regs.GINTSTS.matches_all(regs::GINTSTS::CMOD::Host) {
"host"
} else {
log::warn!("TODO: device mode setup");
"device"
};
log::info!("{}: operating in {} mode", self.name, mode);
// Host mode setup
// 1. Enable HPRTINT
regs.GINTMSK.modify(regs::GINTMSK::PRTIM::SET);
// 2. Setup FS host
regs.HCFG
.write(regs::HCFG::FSLSS::CLEAR + regs::HCFG::FSLSPCS.val(1));
// 3. Drive Vbus on the USB
regs.HPRT.modify(regs::HPRT::PPWR::SET);
// 4. Wait for PCDET interrupt on HPRT0
runtime::spawn(self.clone().softirq())?;
Ok(())
}
}
impl<H: Dwc2Impl + 'static> Device for Dwc2<H> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
unsafe { self.imp.initialize_host_early(self.clone()) }?;
runtime::spawn(self.clone().setup())?;
Ok(())
}
fn display_name(&self) -> &str {
&self.name
}
}
impl<H: Dwc2Impl + 'static> InterruptHandler for Dwc2<H> {
fn handle_irq(self: Arc<Self>, vector: IrqVector) -> bool {
let regs = self.regs.lock();
let gintsts = regs.take_interrupt();
let hprt = if gintsts.matches_all(regs::GINTSTS::HPRTINT::SET) {
regs.take_port_status().get()
} else {
0
};
if hprt != 0 {
self.signal_events(0, hprt);
}
true
}
}
+292
View File
@@ -0,0 +1,292 @@
use core::time::Duration;
use libk::{error::Error, task::runtime, time};
use tock_registers::{
interfaces::{ReadWriteable, Readable, Writeable},
register_bitfields, register_structs,
registers::ReadWrite,
LocalRegisterCopy,
};
register_bitfields! {
u32,
pub GAHBCFG [
PTXFELVL OFFSET(8) NUMBITS(1) [],
TXFELVL OFFSET(7) NUMBITS(1) [],
DMAEN OFFSET(5) NUMBITS(1) [],
HBSTLEN OFFSET(1) NUMBITS(4) [],
GINTMSK OFFSET(0) NUMBITS(1) [],
],
pub GUSBCFG [
FDMOD OFFSET(30) NUMBITS(1) [],
FHMOD OFFSET(29) NUMBITS(1) [],
ULPIIPD OFFSET(25) NUMBITS(1) [],
PTCI OFFSET(24) NUMBITS(1) [],
PCCI OFFSET(23) NUMBITS(1) [],
TSDPS OFFSET(22) NUMBITS(1) [],
ULPIEVBUSI OFFSET(21) NUMBITS(1) [],
ULPIEVBUSD OFFSET(20) NUMBITS(1) [],
ULPICSM OFFSET(19) NUMBITS(1) [],
ULPIAR OFFSET(18) NUMBITS(1) [],
ULPIFSLS OFFSET(17) NUMBITS(1) [],
PHYLPC OFFSET(15) NUMBITS(1) [],
TRDT OFFSET(10) NUMBITS(4) [],
HNPCAP OFFSET(9) NUMBITS(1) [],
SRPCAP OFFSET(8) NUMBITS(1) [],
PHYSEL OFFSET(6) NUMBITS(1) [],
TOCAL OFFSET(0) NUMBITS(3) [],
],
pub GRSTCTL [
AHBIDL OFFSET(31) NUMBITS(1) [],
DMAREQ OFFSET(30) NUMBITS(1) [],
TXFNUM OFFSET(6) NUMBITS(5) [],
TXFFLSH OFFSET(5) NUMBITS(1) [],
RXFFLSH OFFSET(4) NUMBITS(1) [],
FCRST OFFSET(2) NUMBITS(1) [],
PSRST OFFSET(1) NUMBITS(1) [],
CSRST OFFSET(0) NUMBITS(1) [],
],
pub GINTSTS [
WKUPINT OFFSET(31) NUMBITS(1) [],
SRQINT OFFSET(30) NUMBITS(1) [],
DISCINT OFFSET(29) NUMBITS(1) [],
CIDSCHG OFFSET(28) NUMBITS(1) [],
LPMINT OFFSET(27) NUMBITS(1) [],
PTXFE OFFSET(26) NUMBITS(1) [],
HCINT OFFSET(25) NUMBITS(1) [],
HPRTINT OFFSET(24) NUMBITS(1) [],
RSTDET OFFSET(23) NUMBITS(1) [],
DATAFSUSP OFFSET(22) NUMBITS(1) [],
IPXFR OFFSET(21) NUMBITS(1) [],
IISOIXFR OFFSET(20) NUMBITS(1) [],
OEPINT OFFSET(19) NUMBITS(1) [],
IEPINT OFFSET(18) NUMBITS(1) [],
EOPF OFFSET(15) NUMBITS(1) [],
ISOODRP OFFSET(14) NUMBITS(1) [],
ENUMDNE OFFSET(13) NUMBITS(1) [],
USBRST OFFSET(12) NUMBITS(1) [],
USBSUSP OFFSET(11) NUMBITS(1) [],
ESUSP OFFSET(10) NUMBITS(1) [],
GONAKEFF OFFSET(7) NUMBITS(1) [],
GINAKEFF OFFSET(6) NUMBITS(1) [],
NPTXFE OFFSET(5) NUMBITS(1) [],
RXFLVL OFFSET(4) NUMBITS(1) [],
SOF OFFSET(3) NUMBITS(1) [],
OTGINT OFFSET(2) NUMBITS(1) [],
MMIS OFFSET(1) NUMBITS(1) [],
CMOD OFFSET(0) NUMBITS(1) [
Device = 0,
Host = 1
],
],
pub GINTMSK [
WUIM OFFSET(31) NUMBITS(1) [],
SRQIM OFFSET(30) NUMBITS(1) [],
DISCINT OFFSET(29) NUMBITS(1) [],
CIDSCHGM OFFSET(28) NUMBITS(1) [],
LPMINTM OFFSET(27) NUMBITS(1) [],
PTXFEM OFFSET(26) NUMBITS(1) [],
HCIM OFFSET(25) NUMBITS(1) [],
PRTIM OFFSET(24) NUMBITS(1) [],
RSTDETM OFFSET(23) NUMBITS(1) [],
FSUSPM OFFSET(22) NUMBITS(1) [],
IPXFRM OFFSET(21) NUMBITS(1) [],
IISOIXFRM OFFSET(20) NUMBITS(1) [],
OEPINT OFFSET(19) NUMBITS(1) [],
IEPINT OFFSET(18) NUMBITS(1) [],
EOPFM OFFSET(15) NUMBITS(1) [],
ISOODRPM OFFSET(14) NUMBITS(1) [],
ENUMDNEM OFFSET(13) NUMBITS(1) [],
USBRST OFFSET(12) NUMBITS(1) [],
USBSUSPM OFFSET(11) NUMBITS(1) [],
ESUSPM OFFSET(10) NUMBITS(1) [],
GONAKEFFM OFFSET(7) NUMBITS(1) [],
GINAKEFFM OFFSET(6) NUMBITS(1) [],
NPTXFEM OFFSET(5) NUMBITS(1) [],
RXFLVLM OFFSET(4) NUMBITS(1) [],
SOFM OFFSET(3) NUMBITS(1) [],
OTGINT OFFSET(2) NUMBITS(1) [],
MMISM OFFSET(1) NUMBITS(1) [],
],
pub HCFG [
FSLSS OFFSET(2) NUMBITS(1) [],
FSLSPCS OFFSET(0) NUMBITS(2) [],
],
pub HPRT [
PSPD OFFSET(17) NUMBITS(2) [
HighSpeed = 0,
FullSpeed = 1,
LowSpeed = 2,
],
PTCTL OFFSET(13) NUMBITS(4) [],
PPWR OFFSET(12) NUMBITS(1) [],
PLSTS OFFSET(10) NUMBITS(2) [],
PRST OFFSET(8) NUMBITS(1) [],
PSUSP OFFSET(7) NUMBITS(1) [],
PRES OFFSET(6) NUMBITS(1) [],
POCCHNG OFFSET(5) NUMBITS(1) [],
POCA OFFSET(4) NUMBITS(1) [],
PENCHNG OFFSET(3) NUMBITS(1) [],
PENA OFFSET(2) NUMBITS(1) [],
PCDET OFFSET(1) NUMBITS(1) [],
PCSTS OFFSET(0) NUMBITS(1) [],
],
pub HCCHARx [
CHENA OFFSET(31) NUMBITS(1) [],
CHDIS OFFSET(30) NUMBITS(1) [],
ODDFRM OFFSET(29) NUMBITS(1) [],
DAD OFFSET(22) NUMBITS(7) [],
MCNT OFFSET(20) NUMBITS(2) [],
EPTYP OFFSET(18) NUMBITS(2) [
Control = 0,
Isochronous = 1,
Bulk = 2,
Interrupt = 3
],
LSDEV OFFSET(17) NUMBITS(1) [],
EPDIR OFFSET(15) NUMBITS(1) [
Out = 0,
In = 1
],
EPNUM OFFSET(11) NUMBITS(4) [],
MPSIZ OFFSET(0) NUMBITS(11) [],
],
pub HCSPLTx [
SPLITEN OFFSET(31) NUMBITS(1) [],
COMPLSPLT OFFSET(16) NUMBITS(1) [],
XACTPOS OFFSET(14) NUMBITS(2) [
Mid = 0,
End = 1,
Begin = 2,
All = 3,
],
HUBADDR OFFSET(7) NUMBITS(7) [],
PRTADDR OFFSET(0) NUMBITS(7) [],
],
pub HCINTx [
DTERR OFFSET(10) NUMBITS(1) [],
FRMOR OFFSET(9) NUMBITS(1) [],
BBERR OFFSET(8) NUMBITS(1) [],
TXERR OFFSET(7) NUMBITS(1) [],
NYET OFFSET(6) NUMBITS(1) [],
ACK OFFSET(5) NUMBITS(1) [],
NAK OFFSET(4) NUMBITS(1) [],
STALL OFFSET(3) NUMBITS(1) [],
AHBERR OFFSET(2) NUMBITS(1) [],
CHH OFFSET(1) NUMBITS(1) [],
XFRC OFFSET(0) NUMBITS(1) [],
],
pub HCTSIZx [
DPID OFFSET(29) NUMBITS(2) [
DATA0 = 0,
DATA2 = 1,
DATA1 = 2,
SETUP = 3
],
PKTCNT OFFSET(19) NUMBITS(10) [],
XFRSIZ OFFSET(0) NUMBITS(19) []
],
}
register_structs! {
#[allow(non_snake_case)]
pub HostChannelRegs {
(0x00 => pub HCCHARx: ReadWrite<u32, HCCHARx::Register>),
(0x04 => pub HCSPLTx: ReadWrite<u32, HCSPLTx::Register>),
(0x08 => pub HCINTx: ReadWrite<u32, HCINTx::Register>),
(0x0C => pub HCINTMSKx: ReadWrite<u32, HCINTx::Register>),
(0x10 => pub HCTSIZx: ReadWrite<u32, HCTSIZx::Register>),
(0x14 => pub HCDMAx: ReadWrite<u32>),
(0x18 => _0),
(0x20 => @END),
}
}
register_structs! {
#[allow(non_snake_case)]
pub Regs {
(0x000 => pub GOTGCTL: ReadWrite<u32>),
(0x004 => pub GOTGINT: ReadWrite<u32>),
(0x008 => pub GAHBCFG: ReadWrite<u32, GAHBCFG::Register>),
(0x00C => pub GUSBCFG: ReadWrite<u32, GUSBCFG::Register>),
(0x010 => pub GRSTCTL: ReadWrite<u32, GRSTCTL::Register>),
(0x014 => pub GINTSTS: ReadWrite<u32, GINTSTS::Register>),
(0x018 => pub GINTMSK: ReadWrite<u32, GINTMSK::Register>),
(0x01C => pub GRXSTSR: ReadWrite<u32>),
(0x020 => pub GRXSTSP: ReadWrite<u32>),
(0x024 => pub GRXFSIZ: ReadWrite<u32>),
(0x028 => pub HNPTXFSIZ: ReadWrite<u32>),
(0x02C => pub HNPTXSTS: ReadWrite<u32>),
(0x030 => _0),
(0x038 => pub GCCFG: ReadWrite<u32>),
(0x03C => pub CID: ReadWrite<u32>),
(0x040 => _1),
(0x054 => pub GLPMCFG: ReadWrite<u32>),
(0x058 => _2),
(0x100 => pub HPTXFSIZ: ReadWrite<u32>),
(0x104 => pub DIEPTXF_N: [ReadWrite<u32>; 8]),
(0x124 => _3),
(0x400 => pub HCFG: ReadWrite<u32, HCFG::Register>),
(0x404 => pub HFIR: ReadWrite<u32>),
(0x408 => pub HFNUM: ReadWrite<u32>),
(0x40C => _4),
(0x410 => pub HPTXSTS: ReadWrite<u32>),
(0x414 => pub HAINT: ReadWrite<u32>),
(0x418 => pub HAINTMSK: ReadWrite<u32>),
(0x41C => _5),
(0x440 => pub HPRT: ReadWrite<u32, HPRT::Register>),
(0x444 => _6),
(0x500 => pub CHANNELx: [HostChannelRegs; 16]),
(0x700 => _7),
(0x800 => _8),
(0xF00 => @END),
}
}
unsafe impl Send for Regs {}
unsafe impl Sync for Regs {}
pub enum PortSpeed {
LowSpeed,
FullSpeed,
HighSpeed,
}
impl Regs {
pub async fn soft_reset(&self, timeout: Duration) -> Result<(), Error> {
self.GRSTCTL.modify(GRSTCTL::CSRST::SET);
let deadline = time::monotonic_time() + timeout;
let mut timeout = true;
while time::monotonic_time() < deadline {
if self.GRSTCTL.matches_all(GRSTCTL::CSRST::CLEAR) {
timeout = false;
break;
}
runtime::sleep(Duration::from_millis(20)).await;
}
if timeout {
return Err(Error::TimedOut);
}
// The spec wants the OS to wait for at least 3 PHY clocks
runtime::sleep(Duration::from_millis(100)).await;
assert!(self.GRSTCTL.matches_all(GRSTCTL::AHBIDL::SET));
Ok(())
}
pub fn take_interrupt(&self) -> LocalRegisterCopy<u32, GINTSTS::Register> {
let intsts = self.GINTSTS.extract();
self.GINTSTS.set(intsts.get());
intsts
}
pub fn take_port_status(&self) -> LocalRegisterCopy<u32, HPRT::Register> {
let hprt = self.HPRT.extract();
self.HPRT.set(hprt.get());
hprt
}
}
+65
View File
@@ -0,0 +1,65 @@
use alloc::sync::Arc;
use device_api::{clock::ClockHandle, device::Device, interrupt::IrqHandle};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
use libk::error::Error;
use libk_mm::device::DeviceMemoryIo;
use crate::{regs::Regs, Dwc2};
pub trait Dwc2Impl: Send + Sync + Sized {
unsafe fn initialize_host_early(&self, dwc2: Arc<Dwc2<Self>>) -> Result<(), Error>;
async unsafe fn initialize_host(
&self,
dwc2: Arc<Dwc2<Self>>,
regs: &DeviceMemoryIo<'_, Regs>,
) -> Result<(), Error>;
}
pub struct Bcm2835Usb {
clk_otg: ClockHandle,
irq: IrqHandle,
}
impl Dwc2Impl for Bcm2835Usb {
unsafe fn initialize_host_early(&self, dwc2: Arc<Dwc2<Self>>) -> Result<(), Error> {
// TODO PHY setup
self.irq.register(dwc2)?;
self.irq.enable()?;
self.clk_otg.enable()?;
Ok(())
}
async unsafe fn initialize_host(
&self,
dwc2: Arc<Dwc2<Self>>,
regs: &DeviceMemoryIo<'_, Regs>,
) -> Result<(), Error> {
todo!()
}
}
device_tree_driver! {
compatible: ["brcm,bcm2835-usb"],
driver: {
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
let base = node.map_base(context, 0).unwrap();
let clk_otg = node.named_clock("otg").unwrap();
let irq = node.interrupt(0).unwrap();
let name = node.name()?;
node.dump();
let imp = Bcm2835Usb {
clk_otg,
irq
};
let dwc2 = unsafe { Dwc2::new(imp, base, name) }
.inspect_err(|e| log::error!("{name}: setup error {e:?}"))
.ok()?;
Some(Arc::new(dwc2))
}
}
}
+15
View File
@@ -204,6 +204,21 @@ impl<N: EventNotify> BitmapEvent<N> {
self.notify.notify_all();
}
pub async fn wait_mask(&self, mask: u64) -> u64 {
let not_mask = !mask;
poll_fn(|cx| {
let state = self.value.fetch_and(not_mask, Ordering::AcqRel);
if state & mask != 0 {
self.notify.unsubscribe(cx.waker());
Poll::Ready(state)
} else {
self.notify.subscribe(cx.waker());
Poll::Pending
}
})
.await
}
pub async fn wait(&self) -> u64 {
poll_fn(|cx| {
let state = self.value.swap(0, Ordering::AcqRel);
+2
View File
@@ -87,6 +87,8 @@ pub fn kinit() -> Result<(), Error> {
random::init();
loop {}
let root = setup_root().inspect_err(|error| {
log::error!("Cannot setup root filesystem: {error:?}");
})?;
+1
View File
@@ -77,6 +77,7 @@ cfg_if::cfg_if! {
} else if #[cfg(target_arch = "aarch64")] {
extern crate ygg_driver_bsp_arm;
extern crate ygg_driver_bsp_bcm283x;
extern crate ygg_driver_usb_dwc2;
} else if #[cfg(target_arch = "riscv64")] {
extern crate ygg_driver_bsp_riscv;
extern crate ygg_driver_bsp_jh7110;