127 lines
2.8 KiB
Rust
127 lines
2.8 KiB
Rust
// Oscillator
|
|
use devices::DeviceImpl;
|
|
use slog::Logger;
|
|
|
|
const OSC_CTRL: u32 = 0;
|
|
const OSC_STATUS: u32 = 1;
|
|
const OSC_XOSCCTRL: u32 = 2;
|
|
const OSC_XOSCFAIL: u32 = 3;
|
|
/*
|
|
const OSC_RC32KCAL: u32 = 4;
|
|
const OSC_PLLCTRL: u32 = 5;
|
|
const OSC_DFLLCTRL: u32 = 6;
|
|
*/
|
|
|
|
/*
|
|
enum PllSrc {
|
|
RC2M,
|
|
RC32M,
|
|
XOSC,
|
|
}
|
|
*/
|
|
|
|
pub struct Oscillator {
|
|
log: Logger,
|
|
reg_values: [u8; 7],
|
|
|
|
// Real attributes:
|
|
ctrl: u8,
|
|
status: u8,
|
|
xoscctrl: u8,
|
|
/*
|
|
xoscfail: u8,
|
|
rs32kcal: u8,
|
|
pllsrc: PllSrc,
|
|
pllfac: u8,
|
|
dfllctrl: u8,
|
|
*/
|
|
}
|
|
|
|
impl Oscillator {
|
|
pub fn new(log: Logger) -> Self {
|
|
Self {
|
|
log,
|
|
reg_values: [0u8; 7],
|
|
|
|
ctrl: 0,
|
|
status: 0,
|
|
xoscctrl: 0,
|
|
/*
|
|
xoscfail: 0,
|
|
rs32kcal: 0,
|
|
pllsrc: PllSrc::RC2M,
|
|
pllfac: 0,
|
|
dfllctrl: 0,
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DeviceImpl for Oscillator {
|
|
fn read(&mut self, addr: u32) -> u8 {
|
|
match addr {
|
|
OSC_CTRL => {
|
|
// PLL and clock ready.
|
|
return self.ctrl | 0x30;
|
|
}
|
|
OSC_STATUS => {
|
|
return self.status | 0x30;
|
|
}
|
|
_ => {}
|
|
}
|
|
self.reg_values[addr as usize]
|
|
}
|
|
|
|
fn write(&mut self, addr: u32, value: u8) {
|
|
match addr {
|
|
OSC_CTRL => {
|
|
info!(self.log, "OSC_CTRL <= {:02X}", value);
|
|
self.ctrl = value & 0x1F;
|
|
self.status = value & 0x1F;
|
|
}
|
|
OSC_XOSCCTRL => {
|
|
self.xoscctrl = value & 0xEF;
|
|
}
|
|
OSC_XOSCFAIL => {}
|
|
|
|
_ => {}
|
|
}
|
|
self.reg_values[addr as usize] = value;
|
|
}
|
|
|
|
/*
|
|
} else if(addr == 0x03) { // XOSCFAIL
|
|
XOSCFAIL vreg;
|
|
vreg.data = v & 0x03;
|
|
// XOSCFDEN
|
|
if(!xoscfail_.xoscfden && vreg.xoscfden) {
|
|
if(device_->ccpState() & Device::CCP_IOREG) {
|
|
xoscfail_.xoscfden = 1;
|
|
} else {
|
|
LOGF(ERROR, "cannot set XOSCFAIL.XOSCFDEN: protected by CCP");
|
|
}
|
|
} else if(xoscfail_.xoscfden && !vreg.xoscfden) {
|
|
LOGF(ERROR, "XOSCFAIL.XOSCFDEN cannot be cleared");
|
|
}
|
|
// XOSCFDIF
|
|
if(vreg.xoscfdif) {
|
|
xoscfail_.xoscfdif = 0;
|
|
}
|
|
} else if(addr == 0x04) { // RC32KCAL
|
|
rc32kcal_ = v;
|
|
} else if(addr == 0x05) { // PLLCTRL
|
|
if((v >> 6) == 1) {
|
|
LOGF(ERROR, "invalid PLLSRC value");
|
|
} else {
|
|
pllsrc_ = static_cast<PLLSRC>(v >> 6);
|
|
}
|
|
pllfac_ = v & 0x1F;
|
|
} else if(addr == 0x06) { // DFLLCTRL
|
|
//TODO no check nor handling is made here
|
|
dfllctrl_.data = v & 0x03;
|
|
} else {
|
|
LOGF(ERROR, "I/O write %s + 0x%02X: not writable") % name() % addr;
|
|
}
|
|
*/
|
|
}
|