* Create the `esp32c6-hal` package * Teach `esp-hal-common` about the ESP32-C6 * Get a number of peripheral drivers building for the ESP32-C6 bckup initial clocks_ii * Create the `esp32c6-hal` package C6: update * Simplify and fix the linker script update * C6: add I2S * Create the `esp32c6-hal` package * Teach `esp-hal-common` about the ESP32-C6 * Get a number of peripheral drivers building for the ESP32-C6 bckup initial clocks_ii * Create the `esp32c6-hal` package * C6: update * Simplify and fix the linker script * update * C6: add I2S * update * C6 Interrupts * C6: Update build.rs, linker scripts and initial examples * C6: RMT * Fix interrupt handling * Fix `ClockControl::configure` * C6: revert to I2S0 instead of just I2S * C6: rebase and update * RTC not buildable * Implement RWDT and SWD disable * C6: working LEDC * C6: working RMT * C6: add aes * C6: add mcpwm * C6: add rtc_cntln - not finished * C6: update and formatting * C6: add pcnt * C6: add examples and format * Remove inline assembly, fix interrupts and linker scripts * Remove unused features, update cargo config for atomic emu, misc cleanup * Get ADC building and example "working" (as much as it ever does) * Remove a bunch of unused constants which were copied from ESP-IDF * The `mcpwm` example now works correctly * Get `TWAI` peripheral driver building for C6 * Clean up the `rtc_cntl` module and get all the other HALs building again * Add the C6 to our CI workflow * Fix various things that have been missed when rebasing Still missing a few examples (`clock_monitor`, `embassy_spi`, `ram`) * C6: Small updates in wdt (#1) * C6: Update WDT * C6: Update examples with WDT update * Update `esp-println` dependency to fix build errors * Fix formatting issues causing pre-commit hook to fail * Get some more examples working * Working `ram` example * Sync with changes in `main` after rebasing * Working `embassy_spi` example * Use a git dependency for the PAC until we publish a release * Fix I2S for ESP32-C6 * Fix esp32c6 direct boot (#4) * Add direct boot support for C6 * Fix direct boot for c6 - Actually copy into rtc ram - remove dummy section that is no longer needed (was just a waste of flash space) - Move RTC stuff before the no load sections * Update RWDT and refactor RTC (#3) * C6: Update RWDT and add example, refactor RTC and add not-really-good example * Update based on review comments, resolve bunch of warnings and run cargo fmt * Update C6 esp-pacs rev commit * Fix clocks_ll/esp32c6.rs * Fix riscv interrupts * Remove clock_monitor example for now * RAM example works in direct-boot mode * Add a TODO for &mut TIMG0 and cargo fmt * Fix linker script after a bad rebase * Update CI and Cargo.toml embassy required features * use riscv32imac-unknown-none-elf target for C6 in CI * change default target to riscv32imac-unknown-none-elf * add riscv32imac-unknown-none-elf target to MSRV job * another cleanup --------- Co-authored-by: bjoernQ <bjoern.quentin@mobile-j.de> Co-authored-by: Jesse Braham <jesse@beta7.io> * Make required changes to include new `RADIO` peripheral * Use published versions of PAC and `esp-println` * Use the correct target extensions (`imac`) * Fix the super watchdog timer, plus a few more examples * Fix UART clock configuration * Make sure to sync UART registers when configuring AT cmd detection * Disable APM in direct-boot mode * Address a number of review comments * Fix `SPI` clocks and `rtc_watchdog` example (#6) * fix SPI clocks * run cargo fmt * Add comment about used default clk src * Fix rtc_watchdog example in BL mode * run cargo fmt * Update rtc_watchdog example that it works in DB mode * README and example fixes/cleanup * Add I2C peripheral enable and reset * Fix `ApbSarAdc` configuration in `system.rs` --------- Co-authored-by: bjoernQ <bjoern.quentin@mobile-j.de> Co-authored-by: Juraj Sadel <juraj.sadel@espressif.com> Co-authored-by: Juraj Sadel <jurajsadel@gmail.com> Co-authored-by: Scott Mabin <scott@mabez.dev>
370 lines
12 KiB
Rust
370 lines
12 KiB
Rust
use crate::clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock};
|
|
|
|
extern "C" {
|
|
fn ets_update_cpu_frequency(ticks_per_us: u32);
|
|
}
|
|
|
|
const I2C_BBPLL: u8 = 0x66;
|
|
const I2C_BBPLL_HOSTID: u8 = 0;
|
|
|
|
const I2C_BBPLL_OC_REF_DIV: u8 = 2;
|
|
const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
|
|
|
|
const I2C_BBPLL_OC_DIV_7_0: u8 = 3;
|
|
|
|
const I2C_BBPLL_OC_DR1: u8 = 5;
|
|
const I2C_BBPLL_OC_DR1_MSB: u8 = 2;
|
|
const I2C_BBPLL_OC_DR1_LSB: u8 = 0;
|
|
|
|
const I2C_BBPLL_OC_DR3: u8 = 5;
|
|
const I2C_BBPLL_OC_DR3_MSB: u8 = 6;
|
|
const I2C_BBPLL_OC_DR3_LSB: u8 = 4;
|
|
|
|
const I2C_BBPLL_OC_DCUR: u8 = 6;
|
|
|
|
const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
|
|
|
|
const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
|
|
|
|
const I2C_BBPLL_OC_VCO_DBIAS: u8 = 9;
|
|
const I2C_BBPLL_OC_VCO_DBIAS_MSB: u8 = 1;
|
|
const I2C_BBPLL_OC_VCO_DBIAS_LSB: u8 = 0;
|
|
|
|
// Analog function control register
|
|
const I2C_MST_ANA_CONF0_REG: u32 = 0x600AF818;
|
|
const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2;
|
|
const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 3;
|
|
const I2C_MST_BBPLL_CAL_DONE: u32 = 1 << 24;
|
|
|
|
const MODEM_LPCON_CLK_CONF_FORCE_ON_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x1c;
|
|
const MODEM_LPCON_CLK_I2C_MST_FO: u32 = 1 << 2;
|
|
const MODEM_LPCON_I2C_MST_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x10;
|
|
const MODEM_LPCON_CLK_I2C_MST_SEL_160M: u32 = 1 << 0;
|
|
|
|
pub(crate) fn esp32c6_rtc_bbpll_configure(_xtal_freq: XtalClock, _pll_freq: PllClock) {
|
|
unsafe {
|
|
// enable i2c mst clk by force on temporarily
|
|
(MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).write_volatile(
|
|
(MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).read_volatile()
|
|
| MODEM_LPCON_CLK_I2C_MST_FO,
|
|
);
|
|
(MODEM_LPCON_I2C_MST_CLK_CONF_REG as *mut u32).write_volatile(
|
|
(MODEM_LPCON_I2C_MST_CLK_CONF_REG as *mut u32).read_volatile()
|
|
| MODEM_LPCON_CLK_I2C_MST_SEL_160M,
|
|
);
|
|
|
|
let i2c_mst_ana_conf0_reg_ptr = I2C_MST_ANA_CONF0_REG as *mut u32;
|
|
// BBPLL CALIBRATION START
|
|
i2c_mst_ana_conf0_reg_ptr.write_volatile(
|
|
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_HIGH,
|
|
);
|
|
i2c_mst_ana_conf0_reg_ptr.write_volatile(
|
|
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_LOW,
|
|
);
|
|
|
|
let div_ref = 0u32;
|
|
let div7_0 = 8u32;
|
|
let dr1 = 0u32;
|
|
let dr3 = 0u32;
|
|
let dchgp = 5u32;
|
|
let dcur = 3u32;
|
|
let dbias = 2u32;
|
|
|
|
let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref;
|
|
let i2c_bbpll_div_7_0 = div7_0;
|
|
let i2c_bbpll_dcur =
|
|
(1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
|
|
|
|
regi2c_write(
|
|
I2C_BBPLL,
|
|
I2C_BBPLL_HOSTID,
|
|
I2C_BBPLL_OC_REF_DIV,
|
|
i2c_bbpll_lref as u8,
|
|
);
|
|
regi2c_write(
|
|
I2C_BBPLL,
|
|
I2C_BBPLL_HOSTID,
|
|
I2C_BBPLL_OC_DIV_7_0,
|
|
i2c_bbpll_div_7_0 as u8,
|
|
);
|
|
regi2c_write_mask(
|
|
I2C_BBPLL,
|
|
I2C_BBPLL_HOSTID,
|
|
I2C_BBPLL_OC_DR1,
|
|
I2C_BBPLL_OC_DR1_MSB,
|
|
I2C_BBPLL_OC_DR1_LSB,
|
|
dr1 as u8,
|
|
);
|
|
regi2c_write_mask(
|
|
I2C_BBPLL,
|
|
I2C_BBPLL_HOSTID,
|
|
I2C_BBPLL_OC_DR3,
|
|
I2C_BBPLL_OC_DR3_MSB,
|
|
I2C_BBPLL_OC_DR3_LSB,
|
|
dr3 as u8,
|
|
);
|
|
regi2c_write(
|
|
I2C_BBPLL,
|
|
I2C_BBPLL_HOSTID,
|
|
I2C_BBPLL_OC_DCUR,
|
|
i2c_bbpll_dcur as u8,
|
|
);
|
|
regi2c_write_mask(
|
|
I2C_BBPLL,
|
|
I2C_BBPLL_HOSTID,
|
|
I2C_BBPLL_OC_VCO_DBIAS,
|
|
I2C_BBPLL_OC_VCO_DBIAS_MSB,
|
|
I2C_BBPLL_OC_VCO_DBIAS_LSB,
|
|
dbias as u8,
|
|
);
|
|
|
|
// WAIT CALIBRATION DONE
|
|
while (i2c_mst_ana_conf0_reg_ptr.read_volatile() & I2C_MST_BBPLL_CAL_DONE) == 0 {}
|
|
|
|
// BBPLL CALIBRATION STOP
|
|
i2c_mst_ana_conf0_reg_ptr.write_volatile(
|
|
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_HIGH,
|
|
);
|
|
i2c_mst_ana_conf0_reg_ptr.write_volatile(
|
|
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_LOW,
|
|
);
|
|
}
|
|
}
|
|
|
|
pub(crate) fn esp32c6_rtc_bbpll_enable() {
|
|
let pmu = unsafe { &*crate::peripherals::PMU::PTR };
|
|
|
|
pmu.imm_hp_ck_power.modify(|_, w| {
|
|
w.tie_high_xpd_bb_i2c()
|
|
.set_bit()
|
|
.tie_high_xpd_bbpll()
|
|
.set_bit()
|
|
.tie_high_xpd_bbpll_i2c()
|
|
.set_bit()
|
|
});
|
|
|
|
pmu.imm_hp_ck_power
|
|
.modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
|
|
}
|
|
|
|
pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) {
|
|
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
|
|
unsafe {
|
|
ets_update_cpu_frequency(freq.mhz());
|
|
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
|
|
// first.
|
|
pcr.apb_freq_conf
|
|
.modify(|_, w| w.apb_div_num().bits(0).apb_div_num().bits(_div - 1));
|
|
|
|
// Switch clock source
|
|
pcr.sysclk_conf.modify(|_, w| w.soc_clk_sel().bits(0));
|
|
}
|
|
}
|
|
|
|
pub(crate) fn esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
|
|
// On ESP32C6, MSPI source clock's default HS divider leads to 120MHz, which is
|
|
// unusable before calibration Therefore, before switching SOC_ROOT_CLK to
|
|
// HS, we need to set MSPI source clock HS divider to make it run at
|
|
// 80MHz after the switch. PLL = 480MHz, so divider is 6.
|
|
clk_ll_mspi_fast_set_hs_divider(6);
|
|
|
|
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
|
|
unsafe {
|
|
pcr.cpu_freq_conf.modify(|_, w| {
|
|
w.cpu_hs_div_num()
|
|
.bits(((480 / cpu_clock_speed.mhz() / 3) - 1) as u8)
|
|
.cpu_hs_120m_force()
|
|
.clear_bit()
|
|
});
|
|
|
|
pcr.cpu_freq_conf
|
|
.modify(|_, w| w.cpu_hs_120m_force().clear_bit());
|
|
|
|
pcr.sysclk_conf.modify(|_, w| {
|
|
w.soc_clk_sel().bits(1) // PLL = 1
|
|
});
|
|
ets_update_cpu_frequency(cpu_clock_speed.mhz());
|
|
}
|
|
}
|
|
|
|
pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) {
|
|
let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() };
|
|
let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
|
|
| (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
|
|
|
|
lp_aon
|
|
.store5
|
|
.modify(|_, w| unsafe { w.lp_aon_store5().bits(value) });
|
|
}
|
|
|
|
fn clk_ll_mspi_fast_set_hs_divider(divider: u32) {
|
|
// SOC_ROOT_CLK ------> MSPI_FAST_CLK
|
|
// HS divider option: 4, 5, 6 (PCR_MSPI_FAST_HS_DIV_NUM=3, 4, 5)
|
|
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
|
|
|
|
unsafe {
|
|
match divider {
|
|
4 => pcr
|
|
.mspi_clk_conf
|
|
.modify(|_, w| w.mspi_fast_hs_div_num().bits(3)),
|
|
5 => pcr
|
|
.mspi_clk_conf
|
|
.modify(|_, w| w.mspi_fast_hs_div_num().bits(4)),
|
|
6 => pcr
|
|
.mspi_clk_conf
|
|
.modify(|_, w| w.mspi_fast_hs_div_num().bits(5)),
|
|
_ => panic!("Unsupported HS MSPI_FAST divider"),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn reg_set_bit(reg: u32, bit: u32) {
|
|
unsafe {
|
|
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | bit);
|
|
}
|
|
}
|
|
|
|
fn reg_clr_bit(reg: u32, bit: u32) {
|
|
unsafe {
|
|
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !bit);
|
|
}
|
|
}
|
|
|
|
fn reg_write(reg: u32, v: u32) {
|
|
unsafe {
|
|
(reg as *mut u32).write_volatile(v);
|
|
}
|
|
}
|
|
|
|
fn reg_get_bit(reg: u32, b: u32) -> u32 {
|
|
unsafe { (reg as *mut u32).read_volatile() & b }
|
|
}
|
|
|
|
fn reg_get_field(reg: u32, s: u32, v: u32) -> u32 {
|
|
unsafe { ((reg as *mut u32).read_volatile() >> s) & v }
|
|
}
|
|
|
|
const DR_REG_MODEM_LPCON_BASE: u32 = 0x600AF000;
|
|
const MODEM_LPCON_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x18;
|
|
const MODEM_LPCON_CLK_I2C_MST_EN: u32 = 1 << 2;
|
|
const DR_REG_LP_I2C_ANA_MST_BASE: u32 = 0x600B2400;
|
|
const LP_I2C_ANA_MST_DATE_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x3fc;
|
|
const LP_I2C_ANA_MST_I2C_MAT_CLK_EN: u32 = 1 << 28;
|
|
const REGI2C_BIAS: u8 = 0x6a;
|
|
const REGI2C_DIG_REG: u8 = 0x6d;
|
|
const REGI2C_ULP_CAL: u8 = 0x61;
|
|
const REGI2C_SAR_I2C: u8 = 0x69;
|
|
|
|
const LP_I2C_ANA_MST_DEVICE_EN_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x14;
|
|
const REGI2C_BBPLL_DEVICE_EN: u32 = 1 << 5;
|
|
const REGI2C_BIAS_DEVICE_EN: u32 = 1 << 4;
|
|
const REGI2C_DIG_REG_DEVICE_EN: u32 = 1 << 8;
|
|
const REGI2C_ULP_CAL_DEVICE_EN: u32 = 1 << 6;
|
|
const REGI2C_SAR_I2C_DEVICE_EN: u32 = 1 << 7;
|
|
|
|
const REGI2C_RTC_SLAVE_ID_V: u8 = 0xFF;
|
|
const REGI2C_RTC_SLAVE_ID_S: u8 = 0;
|
|
const REGI2C_RTC_ADDR_V: u8 = 0xFF;
|
|
const REGI2C_RTC_ADDR_S: u8 = 8;
|
|
const REGI2C_RTC_WR_CNTL_V: u8 = 0x1;
|
|
const REGI2C_RTC_WR_CNTL_S: u8 = 24;
|
|
const REGI2C_RTC_DATA_V: u8 = 0xFF;
|
|
const REGI2C_RTC_DATA_S: u8 = 16;
|
|
|
|
const LP_I2C_ANA_MST_I2C0_CTRL_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x0;
|
|
const LP_I2C_ANA_MST_I2C0_BUSY: u32 = 1 << 25;
|
|
|
|
const LP_I2C_ANA_MST_I2C0_DATA_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x8;
|
|
const LP_I2C_ANA_MST_I2C0_RDATA_V: u32 = 0x000000FF;
|
|
const LP_I2C_ANA_MST_I2C0_RDATA_S: u32 = 0;
|
|
|
|
const REGI2C_BBPLL: u8 = 0x66;
|
|
|
|
fn regi2c_enable_block(block: u8) {
|
|
reg_set_bit(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
|
|
reg_set_bit(LP_I2C_ANA_MST_DATE_REG, LP_I2C_ANA_MST_I2C_MAT_CLK_EN);
|
|
|
|
// Before config I2C register, enable corresponding slave.
|
|
match block {
|
|
REGI2C_BBPLL => {
|
|
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BBPLL_DEVICE_EN);
|
|
}
|
|
REGI2C_BIAS => {
|
|
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BIAS_DEVICE_EN);
|
|
}
|
|
REGI2C_DIG_REG => {
|
|
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_DIG_REG_DEVICE_EN);
|
|
}
|
|
REGI2C_ULP_CAL => {
|
|
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_ULP_CAL_DEVICE_EN);
|
|
}
|
|
REGI2C_SAR_I2C => {
|
|
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_SAR_I2C_DEVICE_EN);
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
|
|
fn regi2c_disable_block(block: u8) {
|
|
match block {
|
|
REGI2C_BBPLL => {
|
|
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BBPLL_DEVICE_EN);
|
|
}
|
|
REGI2C_BIAS => {
|
|
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BIAS_DEVICE_EN);
|
|
}
|
|
REGI2C_DIG_REG => {
|
|
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_DIG_REG_DEVICE_EN);
|
|
}
|
|
REGI2C_ULP_CAL => {
|
|
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_ULP_CAL_DEVICE_EN);
|
|
}
|
|
REGI2C_SAR_I2C => {
|
|
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_SAR_I2C_DEVICE_EN);
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn regi2c_write(block: u8, _host_id: u8, reg_add: u8, data: u8) {
|
|
regi2c_enable_block(block);
|
|
|
|
let temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32)
|
|
| ((reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32)
|
|
| ((0x1 & REGI2C_RTC_WR_CNTL_V as u32) << REGI2C_RTC_WR_CNTL_S as u32) // 0: READ I2C register; 1: Write I2C register;
|
|
| (((data as u32) & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S as u32);
|
|
reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp);
|
|
while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {}
|
|
|
|
regi2c_disable_block(block);
|
|
}
|
|
|
|
pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
|
|
assert!(msb - lsb < 8);
|
|
regi2c_enable_block(block);
|
|
|
|
// Read the i2c bus register
|
|
let mut temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32)
|
|
<< REGI2C_RTC_SLAVE_ID_S as u32)
|
|
| (reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32;
|
|
reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp);
|
|
while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {}
|
|
temp = reg_get_field(
|
|
LP_I2C_ANA_MST_I2C0_DATA_REG,
|
|
LP_I2C_ANA_MST_I2C0_RDATA_S,
|
|
LP_I2C_ANA_MST_I2C0_RDATA_V,
|
|
);
|
|
// Write the i2c bus register
|
|
temp &= (!(0xFFFFFFFF << lsb)) | (0xFFFFFFFF << (msb + 1));
|
|
temp =
|
|
((data as u32 & (!(0xFFFFFFFF << (msb as u32 - lsb as u32 + 1)))) << (lsb as u32)) | temp;
|
|
temp = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32)
|
|
| ((reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32)
|
|
| ((0x1 & REGI2C_RTC_WR_CNTL_V as u32) << REGI2C_RTC_WR_CNTL_S as u32)
|
|
| ((temp & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S as u32);
|
|
reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp);
|
|
while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {}
|
|
|
|
regi2c_disable_block(block);
|
|
}
|