diff --git a/firmware/zedboard-bsp/src/ddrc_config_autogen.rs b/firmware/zedboard-bsp/src/ddrc_config_autogen.rs index 33d6be2..1b75132 100644 --- a/firmware/zedboard-bsp/src/ddrc_config_autogen.rs +++ b/firmware/zedboard-bsp/src/ddrc_config_autogen.rs @@ -1,4 +1,4 @@ -#![doc = r"This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/tools/zynq7000-ps7init-extract) program."] +#![doc = r"This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/host/zynq7000-ps7init-extract) program."] #![doc = r""] #![doc = r"This configuration file contains static DDR configuration parameters extracted from the"] #![doc = r"AMD ps7init.tcl file. It was generated for the MT41K128M16JT-125 DDR chip."] @@ -34,7 +34,7 @@ pub const DDRC_CONFIG_ZEDBOARD: DdrcConfigSet = DdrcConfigSet { ctrl_reg5: regs::CtrlReg5::new_with_raw_value(0x00466111), ctrl_reg6: regs::CtrlReg6::new_with_raw_value(0x00032222), che_t_zq: regs::CheTZq::new_with_raw_value(0x10200802), - che_t_zq_short_interval_reg: regs::CheTZqShortInterval::new_with_raw_value(0x10200802), + che_t_zq_short_interval_reg: regs::CheTZqShortInterval::new_with_raw_value(0x0690cb73), deep_powerdown: regs::DeepPowerdown::new_with_raw_value(0x000001fe), reg_2c: regs::Reg2c::new_with_raw_value(0x1cffffff), reg_2d: regs::Reg2d::new_with_raw_value(0x00000200), diff --git a/firmware/zedboard-bsp/src/ddriob_config_autogen.rs b/firmware/zedboard-bsp/src/ddriob_config_autogen.rs index b92112e..decaba0 100644 --- a/firmware/zedboard-bsp/src/ddriob_config_autogen.rs +++ b/firmware/zedboard-bsp/src/ddriob_config_autogen.rs @@ -1,10 +1,11 @@ -#![doc = r"This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/tools/zynq7000-ps7init-extract) program."] +#![doc = r"This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/host/zynq7000-ps7init-extract) program."] #![doc = r""] #![doc = r"This configuration file contains static DDRIOB configuration parameters extracted from the"] #![doc = r"AMD ps7init.tcl file. It was generated for the MT41K128M16JT-125 DDR chip."] use zynq7000::ddrc::regs; use zynq7000_hal::ddr::DdriobConfigSet; pub const DDRIOB_CONFIG_SET_ZEDBOARD: DdriobConfigSet = DdriobConfigSet { + ddr_control: zynq7000::slcr::ddriob::DdrControl::new_with_raw_value(0x00000260), addr0: regs::DdriobConfig::new_with_raw_value(0x00000600), addr1: regs::DdriobConfig::new_with_raw_value(0x00000600), data0: regs::DdriobConfig::new_with_raw_value(0x00000672), diff --git a/firmware/zedboard-fsbl/src/main.rs b/firmware/zedboard-fsbl/src/main.rs index 5661e52..2cfbb5d 100644 --- a/firmware/zedboard-fsbl/src/main.rs +++ b/firmware/zedboard-fsbl/src/main.rs @@ -85,6 +85,10 @@ fn main() -> ! { zynq7000_hal::clocks::CpuClockRatio::SixToTwoToOne, u6::new(2), ); + // This is done by the AMD FSBL. + zynq7000_hal::Slcr::with(|val| { + val.gpiob().modify_ctrl(|val| val.with_vref_en(true)); + }); } // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. @@ -113,7 +117,6 @@ fn main() -> ! { false, ) }; - //log::info!("clocks: {:?}", clocks); // Set up the global interrupt controller. let mut gic = gic::GicConfigurator::new_with_init(periphs.gicc, periphs.gicd); @@ -187,6 +190,7 @@ fn main() -> ! { spansion_qspi.into_linear_addressed(qspi_spansion::QSPI_DEV_COMBINATION_REV_F.into()); qspi_boot(spansion_lqspi, priv_tim); } + loop { aarch32_cpu::asm::nop(); } @@ -324,6 +328,8 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode, _priv_tim: priv_tim::Cpu } } + // The PL is in reset state after power-up. This method needs to be called in the first-stage + // bootloader to put it out of reset. zynq7000_hal::pl::deassert_reset(); match opt_jump_addr { @@ -361,7 +367,7 @@ fn interrupt_handler() { gic::Interrupt::Invalid(_) => (), gic::Interrupt::Spurious => { log::warn!("spurious interrupt"); - }, + } } gic_helper.end_of_interrupt(irq_info); } diff --git a/firmware/zynq7000-hal/CHANGELOG.md b/firmware/zynq7000-hal/CHANGELOG.md index 6856b46..e982da6 100644 --- a/firmware/zynq7000-hal/CHANGELOG.md +++ b/firmware/zynq7000-hal/CHANGELOG.md @@ -8,15 +8,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] +## Fixed + +- Bugfix for DDR initialization: `calibrate_iob_impedance_for_ddr3` and `calibrate_iob_impedance` + now expect a `zynq7000::slcr::ddriob::DdrControl` input argument. This register write was + missing +- Several bugfixes and improvements for GIC module. Some of the registers previously were + completely overwritten instead of only modifying their own bit portions. Also allow targeting + interrupts without clearing other CPU target. + ## Changed - `devcfg` moved to `pl` module - Added division by zero check in gtc frequency_to_ticks to avoid runtime panic - Increased UART type safety by providing dedicated MIO constructors for UART 0 and UART 1 respectively. -- Several bugfixes and improvements for GIC module. Some of the registers previously were - completely overwritten instead of only modifying their own bit portions. Also allow targeting - interrupts without clearing other CPU target. ## Added diff --git a/firmware/zynq7000-hal/src/ddr/ll.rs b/firmware/zynq7000-hal/src/ddr/ll.rs index 81bac6d..1d784ab 100644 --- a/firmware/zynq7000-hal/src/ddr/ll.rs +++ b/firmware/zynq7000-hal/src/ddr/ll.rs @@ -86,9 +86,14 @@ pub unsafe fn configure_dci(ddr_clk: &DdrClocks) { /// /// This function writes to the DDR IOB related registers. It should only be called once during /// DDR initialization. -pub unsafe fn calibrate_iob_impedance_for_ddr3(dci_clk_cfg: DciClkConfig, poll_for_done: bool) { +pub unsafe fn calibrate_iob_impedance_for_ddr3( + ddr_control: zynq7000::slcr::ddriob::DdrControl, + dci_clk_cfg: DciClkConfig, + poll_for_done: bool, +) { unsafe { calibrate_iob_impedance( + ddr_control, dci_clk_cfg, u3::new(0), u2::new(0), @@ -115,6 +120,7 @@ pub unsafe fn calibrate_iob_impedance_for_ddr3(dci_clk_cfg: DciClkConfig, poll_f /// This function writes to the DDR IOB related registers. It should only be called once during /// DDR initialization. pub unsafe fn calibrate_iob_impedance( + ddr_control: zynq7000::slcr::ddriob::DdrControl, dci_clk_cfg: DciClkConfig, pref_opt2: u3, pref_opt1: u2, @@ -134,19 +140,11 @@ pub unsafe fn calibrate_iob_impedance( .build(), ); let mut ddriob = slcr.ddriob(); - ddriob.modify_dci_ctrl(|mut val| { - val.set_reset(true); - val - }); - ddriob.modify_dci_ctrl(|mut val| { - val.set_reset(false); - val - }); - ddriob.modify_dci_ctrl(|mut val| { - val.set_reset(true); - val - }); - ddriob.modify_dci_ctrl(|mut val| { + ddriob.write_ddr_control(ddr_control); + ddriob.modify_dci_control(|val| val.with_reset(true)); + ddriob.modify_dci_control(|val| val.with_reset(false)); + ddriob.modify_dci_control(|val| val.with_reset(true)); + ddriob.modify_dci_control(|mut val| { val.set_pref_opt2(pref_opt2); val.set_pref_opt1(pref_opt1); val.set_nref_opt4(nref_opt4); @@ -154,11 +152,11 @@ pub unsafe fn calibrate_iob_impedance( val.set_nref_opt1(nref_opt1); val }); - ddriob.modify_dci_ctrl(|mut val| { + ddriob.modify_dci_control(|mut val| { val.set_update_control(false); val }); - ddriob.modify_dci_ctrl(|mut val| { + ddriob.modify_dci_control(|mut val| { val.set_enable(true); val }); @@ -170,6 +168,7 @@ pub unsafe fn calibrate_iob_impedance( /// Static configuration for DDR IOBs. pub struct DdriobConfigSet { + pub ddr_control: zynq7000::slcr::ddriob::DdrControl, pub addr0: DdriobConfig, pub addr1: DdriobConfig, pub data0: DdriobConfig, diff --git a/firmware/zynq7000-hal/src/ddr/mod.rs b/firmware/zynq7000-hal/src/ddr/mod.rs index 00c15fa..ca56d03 100644 --- a/firmware/zynq7000-hal/src/ddr/mod.rs +++ b/firmware/zynq7000-hal/src/ddr/mod.rs @@ -76,7 +76,7 @@ pub fn configure_ddr_for_ddr3( ll::configure_iob(ddriob_cfg); // Do not wait for completion, it takes a bit of time. We can set all the DDR config registers // before polling for completion. - ll::calibrate_iob_impedance_for_ddr3(dci_clk_cfg, false); + ll::calibrate_iob_impedance_for_ddr3(ddriob_cfg.ddr_control, dci_clk_cfg, false); } ll::configure_ddr_config(&mut ddrc_regs, ddr_cfg); // Safety: This is only called once during DDR initialization, and we only modify DDR related diff --git a/firmware/zynq7000-hal/src/lib.rs b/firmware/zynq7000-hal/src/lib.rs index 9376049..b808732 100644 --- a/firmware/zynq7000-hal/src/lib.rs +++ b/firmware/zynq7000-hal/src/lib.rs @@ -18,7 +18,7 @@ #[cfg(feature = "alloc")] extern crate alloc; -use slcr::Slcr; +pub use slcr::Slcr; use zynq7000::{ SpiClockPhase, SpiClockPolarity, slcr::{BootModeRegister, BootPllConfig, LevelShifterRegister}, diff --git a/firmware/zynq7000-hal/src/qspi/mod.rs b/firmware/zynq7000-hal/src/qspi/mod.rs index 5fe239f..4e2b7d8 100644 --- a/firmware/zynq7000-hal/src/qspi/mod.rs +++ b/firmware/zynq7000-hal/src/qspi/mod.rs @@ -417,7 +417,7 @@ impl Qspi { .with_disable_hstl_rcvr(false) .with_pullup(true) .with_io_type(voltage) - .with_speed(Speed::SlowCmosEdge) + .with_speed(Speed::FastCmosEdge) .with_l3_sel(QSPI_MUX_CONFIG.l3_sel()) .with_l2_sel(QSPI_MUX_CONFIG.l2_sel()) .with_l1_sel(QSPI_MUX_CONFIG.l1_sel()) @@ -429,7 +429,7 @@ impl Qspi { .with_disable_hstl_rcvr(false) .with_pullup(false) .with_io_type(voltage) - .with_speed(Speed::SlowCmosEdge) + .with_speed(Speed::FastCmosEdge) .with_l3_sel(QSPI_MUX_CONFIG.l3_sel()) .with_l2_sel(QSPI_MUX_CONFIG.l2_sel()) .with_l1_sel(QSPI_MUX_CONFIG.l1_sel()) @@ -471,7 +471,7 @@ impl Qspi { .with_disable_hstl_rcvr(false) .with_pullup(false) .with_io_type(voltage) - .with_speed(Speed::SlowCmosEdge) + .with_speed(Speed::FastCmosEdge) .with_l3_sel(QSPI_MUX_CONFIG.l3_sel()) .with_l2_sel(QSPI_MUX_CONFIG.l2_sel()) .with_l1_sel(QSPI_MUX_CONFIG.l1_sel()) diff --git a/firmware/zynq7000/src/slcr/ddriob.rs b/firmware/zynq7000/src/slcr/ddriob.rs index d657d4e..4c6160b 100644 --- a/firmware/zynq7000/src/slcr/ddriob.rs +++ b/firmware/zynq7000/src/slcr/ddriob.rs @@ -118,8 +118,8 @@ pub struct DdrIobRegisters { ddriob_drive_slew_data: u32, ddriob_drive_slew_diff: u32, ddriob_drive_slew_clock: u32, - ddr_ctrl: DdrControl, - dci_ctrl: DciControl, + ddr_control: DdrControl, + dci_control: DciControl, dci_status: DciStatus, } diff --git a/host/zynq7000-ps7init-extract/src/main.rs b/host/zynq7000-ps7init-extract/src/main.rs index db195c2..cb8ec0c 100644 --- a/host/zynq7000-ps7init-extract/src/main.rs +++ b/host/zynq7000-ps7init-extract/src/main.rs @@ -4,7 +4,7 @@ use clap::Parser as _; use simple_logger::SimpleLogger; const DDRC_ADDR_RANGE: RangeInclusive = 0xf800_6000..=0xf800_62b4; -const DDRIOB_ADDR_RANGE: RangeInclusive = 0xf800_0b40..=0xf800_0b68; +const DDRIOB_ADDR_RANGE: RangeInclusive = 0xf800_0b40..=0xf800_0b6C; const DDRC_FILE_NAME: &str = "ddrc_config_autogen.rs"; const DDRIOB_FILE_NAME: &str = "ddriob_config_autogen.rs"; @@ -198,7 +198,7 @@ fn generate_ddrc_config( let lpddr_ctrl_3 = reg_to_values.val_as_token("LPDDR CTRL 3", 0xF800_62B4); let generated = quote::quote! { - //!This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/tools/zynq7000-ps7init-extract) program. + //!This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/host/zynq7000-ps7init-extract) program. //! //!This configuration file contains static DDR configuration parameters extracted from the //!AMD ps7init.tcl file @@ -310,6 +310,7 @@ fn generate_ddriob_config( file_name: &str, ) -> std::io::Result<()> { // Format as hex strings + let ddr_control = reg_to_values.val_as_token("DDRIOB DDR Control", 0xF800_0B6C); let addr0 = reg_to_values.val_as_token("DDRIOB Addr 0", 0xF800_0B40); let addr1 = reg_to_values.val_as_token("DDRIOB Addr 1", 0xF800_0B44); let data0 = reg_to_values.val_as_token("DDRIOB Data 0", 0xF800_0B48); @@ -318,7 +319,7 @@ fn generate_ddriob_config( let diff1 = reg_to_values.val_as_token("DDRIOB Diff 1", 0xF800_0B54); let clock = reg_to_values.val_as_token("DDRIOB Clock", 0xF800_0B58); let generated = quote::quote! { - //!This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/tools/zynq7000-ps7init-extract) program. + //!This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/host/zynq7000-ps7init-extract) program. //! //!This configuration file contains static DDRIOB configuration parameters extracted from the //!AMD ps7init.tcl file @@ -326,6 +327,7 @@ fn generate_ddriob_config( use zynq7000_hal::ddr::DdriobConfigSet; pub const DDRIOB_CONFIG_SET_ZEDBOARD: DdriobConfigSet = DdriobConfigSet { + ddr_control: zynq7000::slcr::ddriob::DdrControl::new_with_raw_value(#ddr_control), addr0: regs::DdriobConfig::new_with_raw_value(#addr0), addr1: regs::DdriobConfig::new_with_raw_value(#addr1), data0: regs::DdriobConfig::new_with_raw_value(#data0), diff --git a/scripts/ps7_init.tcl b/scripts/ps7_init.tcl index ee6fb61..1520ce6 100644 --- a/scripts/ps7_init.tcl +++ b/scripts/ps7_init.tcl @@ -84,26 +84,26 @@ proc ps7_ddr_init_data_3_0 {} { mask_write 0XF800611C 0x7FFFFFCF 0x40000001 mask_write 0XF8006120 0x7FFFFFCF 0x40000001 mask_write 0XF8006124 0x7FFFFFCF 0x40000001 - mask_write 0XF800612C 0x000FFFFF 0x00024000 - mask_write 0XF8006130 0x000FFFFF 0x00022C00 - mask_write 0XF8006134 0x000FFFFF 0x00023000 - mask_write 0XF8006138 0x000FFFFF 0x00024C00 + mask_write 0XF800612C 0x000FFFFF 0x00033C03 + mask_write 0XF8006130 0x000FFFFF 0x00034003 + mask_write 0XF8006134 0x000FFFFF 0x0002F400 + mask_write 0XF8006138 0x000FFFFF 0x00030400 mask_write 0XF8006140 0x000FFFFF 0x00000035 mask_write 0XF8006144 0x000FFFFF 0x00000035 mask_write 0XF8006148 0x000FFFFF 0x00000035 mask_write 0XF800614C 0x000FFFFF 0x00000035 - mask_write 0XF8006154 0x000FFFFF 0x00000077 - mask_write 0XF8006158 0x000FFFFF 0x0000007C - mask_write 0XF800615C 0x000FFFFF 0x0000007C - mask_write 0XF8006160 0x000FFFFF 0x00000075 - mask_write 0XF8006168 0x001FFFFF 0x000000E5 - mask_write 0XF800616C 0x001FFFFF 0x000000E0 - mask_write 0XF8006170 0x001FFFFF 0x000000E1 - mask_write 0XF8006174 0x001FFFFF 0x000000E8 - mask_write 0XF800617C 0x000FFFFF 0x000000B7 - mask_write 0XF8006180 0x000FFFFF 0x000000BC - mask_write 0XF8006184 0x000FFFFF 0x000000BC - mask_write 0XF8006188 0x000FFFFF 0x000000B5 + mask_write 0XF8006154 0x000FFFFF 0x00000083 + mask_write 0XF8006158 0x000FFFFF 0x00000083 + mask_write 0XF800615C 0x000FFFFF 0x0000007F + mask_write 0XF8006160 0x000FFFFF 0x00000078 + mask_write 0XF8006168 0x001FFFFF 0x00000124 + mask_write 0XF800616C 0x001FFFFF 0x00000125 + mask_write 0XF8006170 0x001FFFFF 0x00000112 + mask_write 0XF8006174 0x001FFFFF 0x00000116 + mask_write 0XF800617C 0x000FFFFF 0x000000C3 + mask_write 0XF8006180 0x000FFFFF 0x000000C3 + mask_write 0XF8006184 0x000FFFFF 0x000000BF + mask_write 0XF8006188 0x000FFFFF 0x000000B8 mask_write 0XF8006190 0x6FFFFEFE 0x00040080 mask_write 0XF8006194 0x000FFFFF 0x0001FC82 mask_write 0XF8006204 0xFFFFFFFF 0x00000000 @@ -320,26 +320,26 @@ proc ps7_ddr_init_data_2_0 {} { mask_write 0XF800611C 0x7FFFFFFF 0x40000001 mask_write 0XF8006120 0x7FFFFFFF 0x40000001 mask_write 0XF8006124 0x7FFFFFFF 0x40000001 - mask_write 0XF800612C 0x000FFFFF 0x00024000 - mask_write 0XF8006130 0x000FFFFF 0x00022C00 - mask_write 0XF8006134 0x000FFFFF 0x00023000 - mask_write 0XF8006138 0x000FFFFF 0x00024C00 + mask_write 0XF800612C 0x000FFFFF 0x00033C03 + mask_write 0XF8006130 0x000FFFFF 0x00034003 + mask_write 0XF8006134 0x000FFFFF 0x0002F400 + mask_write 0XF8006138 0x000FFFFF 0x00030400 mask_write 0XF8006140 0x000FFFFF 0x00000035 mask_write 0XF8006144 0x000FFFFF 0x00000035 mask_write 0XF8006148 0x000FFFFF 0x00000035 mask_write 0XF800614C 0x000FFFFF 0x00000035 - mask_write 0XF8006154 0x000FFFFF 0x00000077 - mask_write 0XF8006158 0x000FFFFF 0x0000007C - mask_write 0XF800615C 0x000FFFFF 0x0000007C - mask_write 0XF8006160 0x000FFFFF 0x00000075 - mask_write 0XF8006168 0x001FFFFF 0x000000E5 - mask_write 0XF800616C 0x001FFFFF 0x000000E0 - mask_write 0XF8006170 0x001FFFFF 0x000000E1 - mask_write 0XF8006174 0x001FFFFF 0x000000E8 - mask_write 0XF800617C 0x000FFFFF 0x000000B7 - mask_write 0XF8006180 0x000FFFFF 0x000000BC - mask_write 0XF8006184 0x000FFFFF 0x000000BC - mask_write 0XF8006188 0x000FFFFF 0x000000B5 + mask_write 0XF8006154 0x000FFFFF 0x00000083 + mask_write 0XF8006158 0x000FFFFF 0x00000083 + mask_write 0XF800615C 0x000FFFFF 0x0000007F + mask_write 0XF8006160 0x000FFFFF 0x00000078 + mask_write 0XF8006168 0x001FFFFF 0x00000124 + mask_write 0XF800616C 0x001FFFFF 0x00000125 + mask_write 0XF8006170 0x001FFFFF 0x00000112 + mask_write 0XF8006174 0x001FFFFF 0x00000116 + mask_write 0XF800617C 0x000FFFFF 0x000000C3 + mask_write 0XF8006180 0x000FFFFF 0x000000C3 + mask_write 0XF8006184 0x000FFFFF 0x000000BF + mask_write 0XF8006188 0x000FFFFF 0x000000B8 mask_write 0XF8006190 0xFFFFFFFF 0x10040080 mask_write 0XF8006194 0x000FFFFF 0x0001FC82 mask_write 0XF8006204 0xFFFFFFFF 0x00000000 @@ -554,26 +554,26 @@ proc ps7_ddr_init_data_1_0 {} { mask_write 0XF800611C 0x7FFFFFFF 0x40000001 mask_write 0XF8006120 0x7FFFFFFF 0x40000001 mask_write 0XF8006124 0x7FFFFFFF 0x40000001 - mask_write 0XF800612C 0x000FFFFF 0x00024000 - mask_write 0XF8006130 0x000FFFFF 0x00022C00 - mask_write 0XF8006134 0x000FFFFF 0x00023000 - mask_write 0XF8006138 0x000FFFFF 0x00024C00 + mask_write 0XF800612C 0x000FFFFF 0x00033C03 + mask_write 0XF8006130 0x000FFFFF 0x00034003 + mask_write 0XF8006134 0x000FFFFF 0x0002F400 + mask_write 0XF8006138 0x000FFFFF 0x00030400 mask_write 0XF8006140 0x000FFFFF 0x00000035 mask_write 0XF8006144 0x000FFFFF 0x00000035 mask_write 0XF8006148 0x000FFFFF 0x00000035 mask_write 0XF800614C 0x000FFFFF 0x00000035 - mask_write 0XF8006154 0x000FFFFF 0x00000077 - mask_write 0XF8006158 0x000FFFFF 0x0000007C - mask_write 0XF800615C 0x000FFFFF 0x0000007C - mask_write 0XF8006160 0x000FFFFF 0x00000075 - mask_write 0XF8006168 0x001FFFFF 0x000000E5 - mask_write 0XF800616C 0x001FFFFF 0x000000E0 - mask_write 0XF8006170 0x001FFFFF 0x000000E1 - mask_write 0XF8006174 0x001FFFFF 0x000000E8 - mask_write 0XF800617C 0x000FFFFF 0x000000B7 - mask_write 0XF8006180 0x000FFFFF 0x000000BC - mask_write 0XF8006184 0x000FFFFF 0x000000BC - mask_write 0XF8006188 0x000FFFFF 0x000000B5 + mask_write 0XF8006154 0x000FFFFF 0x00000083 + mask_write 0XF8006158 0x000FFFFF 0x00000083 + mask_write 0XF800615C 0x000FFFFF 0x0000007F + mask_write 0XF8006160 0x000FFFFF 0x00000078 + mask_write 0XF8006168 0x001FFFFF 0x00000124 + mask_write 0XF800616C 0x001FFFFF 0x00000125 + mask_write 0XF8006170 0x001FFFFF 0x00000112 + mask_write 0XF8006174 0x001FFFFF 0x00000116 + mask_write 0XF800617C 0x000FFFFF 0x000000C3 + mask_write 0XF8006180 0x000FFFFF 0x000000C3 + mask_write 0XF8006184 0x000FFFFF 0x000000BF + mask_write 0XF8006188 0x000FFFFF 0x000000B8 mask_write 0XF8006190 0xFFFFFFFF 0x10040080 mask_write 0XF8006194 0x000FFFFF 0x0001FC82 mask_write 0XF8006204 0xFFFFFFFF 0x00000000