Skip to content

Commit

Permalink
USB: Add support for external ULPI PHYs
Browse files Browse the repository at this point in the history
  • Loading branch information
mattico committed Feb 12, 2021
1 parent 5471426 commit 22ad278
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ paste = "1.0.1"
bare-metal = "1.0.0"
sdio-host = { version = "0.4", optional = true }
stm32-fmc = { version = "0.2", optional = true }
synopsys-usb-otg = { version = "^0.2.2", features = ["cortex-m"], optional = true }
synopsys-usb-otg = { version = "^0.2.4", features = ["cortex-m"], optional = true }

[dependencies.smoltcp]
version = "0.7.0"
Expand Down
112 changes: 106 additions & 6 deletions src/usb_hs.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
//! USB OTG peripherals
//!
//! Requires the `usb_hs` feature.
//!
//! Note that only full-speed mode is supported,
//! external high-speed PHY is not supported.

use crate::rcc;
use crate::stm32;

use crate::gpio::{
gpioa::{PA11, PA12},
gpioa::{PA11, PA12, PA3, PA5},
gpiob::{PB0, PB1, PB10, PB11, PB12, PB13, PB5},
gpioc::PC0,
gpioc::{PC2, PC3},
gpioh::PH4,
gpioi::PI11,
Alternate, AF10,
};
#[cfg(not(feature = "rm0455"))]
Expand All @@ -21,7 +23,7 @@ use crate::gpio::{
use crate::time::Hertz;

pub use synopsys_usb_otg::UsbBus;
use synopsys_usb_otg::UsbPeripheral;
use synopsys_usb_otg::{PhyType, UsbPeripheral};

#[cfg(not(feature = "rm0455"))]
pub struct USB1 {
Expand All @@ -33,6 +35,7 @@ pub struct USB1 {
pub prec: rcc::rec::Usb1Otg,
pub hclk: Hertz,
}

#[cfg(not(feature = "rm0455"))]
pub struct USB2 {
pub usb_global: stm32::OTG2_HS_GLOBAL,
Expand Down Expand Up @@ -64,7 +67,6 @@ macro_rules! usb_peripheral {

const HIGH_SPEED: bool = true;
const FIFO_DEPTH_WORDS: usize = 1024;

const ENDPOINT_COUNT: usize = 9;

fn enable() {
Expand Down Expand Up @@ -106,3 +108,101 @@ usb_peripheral! {
}
#[cfg(not(feature = "rm0455"))]
pub type Usb2BusType = UsbBus<USB2>;

#[cfg(not(feature = "rm0455"))]
pub struct USB1_ULPI {
pub usb_global: stm32::OTG1_HS_GLOBAL,
pub usb_device: stm32::OTG1_HS_DEVICE,
pub usb_pwrclk: stm32::OTG1_HS_PWRCLK,
pub prec: rcc::rec::Usb1Otg,
pub hclk: Hertz,
pub ulpi_clk: PA5<Alternate<AF10>>,
pub ulpi_dir: Usb1UlpiDirPin,
pub ulpi_nxt: Usb1UlpiNxtPin,
pub ulpi_stp: PC0<Alternate<AF10>>,
pub ulpi_d0: PA3<Alternate<AF10>>,
pub ulpi_d1: PB0<Alternate<AF10>>,
pub ulpi_d2: PB1<Alternate<AF10>>,
pub ulpi_d3: PB10<Alternate<AF10>>,
pub ulpi_d4: PB11<Alternate<AF10>>,
pub ulpi_d5: PB12<Alternate<AF10>>,
pub ulpi_d6: PB13<Alternate<AF10>>,
pub ulpi_d7: PB5<Alternate<AF10>>,
}

#[cfg(not(feature = "rm0455"))]
pub enum Usb1UlpiDirPin {
PC2(PC2<Alternate<AF10>>),
PI11(PI11<Alternate<AF10>>),
}

#[cfg(not(feature = "rm0455"))]
impl From<PI11<Alternate<AF10>>> for Usb1UlpiDirPin {
fn from(v: PI11<Alternate<AF10>>) -> Self {
Usb1UlpiDirPin::PI11(v)
}
}

#[cfg(not(feature = "rm0455"))]
impl From<PC2<Alternate<AF10>>> for Usb1UlpiDirPin {
fn from(v: PC2<Alternate<AF10>>) -> Self {
Usb1UlpiDirPin::PC2(v)
}
}

#[cfg(not(feature = "rm0455"))]
pub enum Usb1UlpiNxtPin {
PC3(PC3<Alternate<AF10>>),
PH4(PH4<Alternate<AF10>>),
}

#[cfg(not(feature = "rm0455"))]
impl From<PH4<Alternate<AF10>>> for Usb1UlpiNxtPin {
fn from(v: PH4<Alternate<AF10>>) -> Self {
Usb1UlpiNxtPin::PH4(v)
}
}

#[cfg(not(feature = "rm0455"))]
impl From<PC3<Alternate<AF10>>> for Usb1UlpiNxtPin {
fn from(v: PC3<Alternate<AF10>>) -> Self {
Usb1UlpiNxtPin::PC3(v)
}
}

#[cfg(not(feature = "rm0455"))]
unsafe impl Sync for USB1_ULPI {}

#[cfg(not(feature = "rm0455"))]
unsafe impl UsbPeripheral for USB1_ULPI {
const REGISTERS: *const () = stm32::OTG1_HS_GLOBAL::ptr() as *const ();

const HIGH_SPEED: bool = true;
const FIFO_DEPTH_WORDS: usize = 1024;
const ENDPOINT_COUNT: usize = 9;

fn enable() {
let rcc = unsafe { &*stm32::RCC::ptr() };

cortex_m::interrupt::free(|_| {
// Enable USB peripheral
rcc.ahb1enr.modify(|_, w| w.usb1otgen().enabled());

// Enable ULPI Clock
rcc.ahb1enr.modify(|_, w| w.usb1ulpien().enabled());

// Reset USB peripheral
rcc.ahb1rstr.modify(|_, w| w.usb1otgrst().set_bit());
rcc.ahb1rstr.modify(|_, w| w.usb1otgrst().clear_bit());
});
}

fn ahb_frequency_hz(&self) -> u32 {
self.hclk.0
}

fn phy_type(&self) -> PhyType {
PhyType::ExternalHighSpeed
}
}
pub type Usb1UlpiBusType = UsbBus<USB1_ULPI>;

0 comments on commit 22ad278

Please sign in to comment.