From 993913cb4657463be994730df2960fa3de20b59b Mon Sep 17 00:00:00 2001 From: Thom Nichols <95562+thom-nic@users.noreply.github.com> Date: Wed, 29 Jan 2025 09:04:17 -0500 Subject: [PATCH] Add support for TI AM625 and AM62A arm64 SoCs - TI AM625: https://www.ti.com/lit/pdf/spruiv7 - TI AM62a: https://www.ti.com/lit/pdf/spruj16 - fixes #12 --- src/Makefile.am | 7 ++-- src/am62x.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ src/am62x.h | 9 +++++ src/bootcount.c | 6 ++++ 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/am62x.c create mode 100644 src/am62x.h diff --git a/src/Makefile.am b/src/Makefile.am index 17c212b..07d9721 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,9 @@ AM_CFLAGS = -std=c99 -pedantic -W -Wall -Wextra -Wno-unused-parameter -Wshadow sbin_PROGRAMS = bootcount -bootcount_SOURCES = bootcount.c am33xx.c stm32mp1.c i2c_eeprom.c memory.c \ - dt.c imx8m.c imx93.c +bootcount_SOURCES = bootcount.c dt.c memory.c \ + am33xx.c am62x.c \ + stm32mp1.c \ + i2c_eeprom.c\ + imx8m.c imx93.c diff --git a/src/am62x.c b/src/am62x.c new file mode 100644 index 0000000..7ba7041 --- /dev/null +++ b/src/am62x.c @@ -0,0 +1,94 @@ +/** + * Access and reset u-boot's "bootcount" counter for the TI AM625 and AM62A SoCs + * which is stored in the RTC_SCRATCH2_REG. + * + * see: + * - AM625 TRM: https://www.ti.com/lit/pdf/spruiv7 + * Section 12.7.3.3.4 Scratch Registers + * Section 14.8.7.3.12.1 RTC_RTC_SCRATCH0_N Register + * + * - AM62ax TRM: https://www.ti.com/lit/pdf/spruj16 + * Section 12.8.3.3.4 Scratch Registers + * Section 14.9.7.3.12.1 RTC_RTC_SCRATCH0_N Register + */ + +#include +#include +#include +#include + +#include "./constants.h" +#include "./memory.h" +#include "./dt.h" +#include "./am62x.h" + +// spruiv7.pdf Section 14.8.7.3.12 RTC_RTC_RTC_SCRATCH0_N Register +// spruj16.pdf Section 14.9.7.3.12 RTC_RTC_RTC_SCRATCH0_N Register +#define AM62_RTCSS 0x2B1F0000ul +#define AM62_SCRATCH2_REG_OFFSET (0x30ul * 2) +#define AM62_REG_SIZE 4ul // registers are 4 bytes/ 32bit + +// spruiv7.pdf Section 14.8.7.3.19 RTC_RTC_RTC_KICK0 Registers +// spruj16.pdf Section 14.9.7.3.19 RTC_RTC_RTC_KICK0 Registers +#define AM62_KICK0R_REG_OFFSET 0x70ul +#define AM62_KICK1R_REG_OFFSET 0x74ul +#define AM62_KICK0_MAGIC 0x83e70b13ul +#define AM62_KICK1_MAGIC 0x95a4f1e0ul + +#define AM62_MEM_OFFSET (AM62_RTCSS + AM62_SCRATCH2_REG_OFFSET) +// We need to map the RTCSS block from SCRATCH2 up to the end of KICK1R: +#define AM62_MEM_LEN (AM62_KICK1R_REG_OFFSET + AM62_REG_SIZE - AM62_SCRATCH2_REG_OFFSET) + +bool is_am62() { + return is_compatible_soc("ti,am625") || is_compatible_soc("ti,am62a7"); +} + +int am62_read_bootcount(uint16_t* val) { + + uint32_t *scratch2_addr = memory_open(AM62_MEM_OFFSET, AM62_MEM_LEN); + if ( scratch2_addr == (void *)E_DEVICE ) { + return E_DEVICE; + } + + uint32_t scratch2_val = memory_read(scratch2_addr); + // low two bytes are the value, high two bytes are magic + if ((scratch2_val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) { + return E_BADMAGIC; + } + + *val = (uint16_t)(scratch2_val & 0x0000ffff); + return 0; +} + + +int am62_write_bootcount(uint16_t val) { + // NOTE: These must be volatile. + // See https://github.com/brgl/busybox/blob/master/miscutils/devmem.c + volatile uint32_t *scratch2_addr = + (volatile uint32_t *)memory_open(AM62_MEM_OFFSET, AM62_MEM_LEN); + if ( scratch2_addr == (void *)E_DEVICE ) { + return E_DEVICE; + } + + volatile uint32_t *kick0r = scratch2_addr + (AM62_KICK0R_REG_OFFSET - AM62_SCRATCH2_REG_OFFSET) / 4; + volatile uint32_t *kick1r = kick0r + 1; // (AM62_KICK1R_REG_OFFSET - AM62_SCRATCH2_REG_OFFSET) / 4; + + // Disable write protection, then write to SCRATCH2 + *kick0r = AM62_KICK0_MAGIC; + *kick1r = AM62_KICK1_MAGIC; + uint32_t scratch2_val = (BOOTCOUNT_MAGIC & 0xffff0000) | (val & 0xffff); + memory_write(scratch2_addr, scratch2_val); + + // re-lock the write protection register + *kick1r = 0; + + // read back to verify: + uint16_t read_val = 0; + am33_read_bootcount(&read_val); + if ( read_val != val ) { + return E_WRITE_FAILED; + } + + + return 0; +} diff --git a/src/am62x.h b/src/am62x.h new file mode 100644 index 0000000..bf0b445 --- /dev/null +++ b/src/am62x.h @@ -0,0 +1,9 @@ +# pragma once + +#include + +#define AM62_PLAT_NAME "TI AM62x" + +bool is_am62(); +int am62_read_bootcount(uint16_t* val); +int am62_write_bootcount(uint16_t val); diff --git a/src/bootcount.c b/src/bootcount.c index 7023fe0..14bf43e 100644 --- a/src/bootcount.c +++ b/src/bootcount.c @@ -30,6 +30,7 @@ #include "constants.h" #include "dt.h" #include "am33xx.h" +#include "am62x.h" #include "imx8m.h" #include "imx93.h" #include "stm32mp1.h" @@ -50,6 +51,11 @@ static const struct platform platforms[] = { .read_bootcount = am33_read_bootcount, .write_bootcount = am33_write_bootcount }, + {.name = AM62_PLAT_NAME, + .detect = is_am62, + .read_bootcount = am62_read_bootcount, + .write_bootcount = am62_write_bootcount + }, {.name = IMX8M_PLAT_NAME, .detect = is_imx8m, .read_bootcount = imx8m_read_bootcount,