Skip to content

Commit 5465f98

Browse files
committed
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
1 parent 29296ae commit 5465f98

File tree

4 files changed

+114
-2
lines changed

4 files changed

+114
-2
lines changed

src/Makefile.am

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
AM_CFLAGS = -std=c99 -pedantic -W -Wall -Wextra -Wno-unused-parameter -Wshadow
22

33
sbin_PROGRAMS = bootcount
4-
bootcount_SOURCES = bootcount.c am33xx.c stm32mp1.c i2c_eeprom.c memory.c \
5-
dt.c imx8m.c imx93.c
4+
bootcount_SOURCES = bootcount.c dt.c memory.c \
5+
am33xx.c am62x.c \
6+
stm32mp1.c \
7+
i2c_eeprom.c\
8+
imx8m.c imx93.c
69

src/am62x.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* Access and reset u-boot's "bootcount" counter for the TI AM625 and AM62A SoCs
3+
* which is stored in the RTC_SCRATCH2_REG.
4+
*
5+
* see:
6+
* - AM625 TRM: https://www.ti.com/lit/pdf/spruiv7
7+
* Section 12.7.3.3.4 Scratch Registers
8+
* Section 14.8.7.3.12.1 RTC_RTC_SCRATCH0_N Register
9+
*
10+
* - AM62ax TRM: https://www.ti.com/lit/pdf/spruj16
11+
* Section 12.8.3.3.4 Scratch Registers
12+
* Section 14.9.7.3.12.1 RTC_RTC_SCRATCH0_N Register
13+
*/
14+
15+
#include <stdlib.h>
16+
#include <stdint.h>
17+
#include <stdio.h>
18+
#include <string.h>
19+
20+
#include "./constants.h"
21+
#include "./memory.h"
22+
#include "./dt.h"
23+
#include "./am62x.h"
24+
25+
// spruiv7.pdf Section 14.8.7.3.12 RTC_RTC_RTC_SCRATCH0_N Register
26+
// spruj16.pdf Section 14.9.7.3.12 RTC_RTC_RTC_SCRATCH0_N Register
27+
#define AM62_RTCSS 0x2B1F0000ul
28+
#define AM62_REG_SIZE 4ul // registers are 4 bytes/ 32bit
29+
// Offset = 30h + (j * 4h); where j = 0h to 7h:
30+
#define AM62_SCRATCH2_REG_OFFSET (0x30ul + 2*AM62_REG_SIZE)
31+
32+
// spruiv7.pdf Section 14.8.7.3.19 RTC_RTC_RTC_KICK0 Registers
33+
// spruj16.pdf Section 14.9.7.3.19 RTC_RTC_RTC_KICK0 Registers
34+
#define AM62_KICK0R_REG_OFFSET 0x70ul
35+
#define AM62_KICK1R_REG_OFFSET 0x74ul
36+
#define AM62_KICK0_MAGIC 0x83e70b13ul
37+
#define AM62_KICK1_MAGIC 0x95a4f1e0ul
38+
39+
#define AM62_MEM_OFFSET (AM62_RTCSS + AM62_SCRATCH2_REG_OFFSET)
40+
// We need to map the RTCSS block from SCRATCH2 up to the end of KICK1R:
41+
#define AM62_MEM_LEN (AM62_KICK1R_REG_OFFSET + AM62_REG_SIZE - AM62_SCRATCH2_REG_OFFSET)
42+
43+
bool is_am62() {
44+
return is_compatible_soc("ti,am625") || is_compatible_soc("ti,am62a7");
45+
}
46+
47+
int am62_read_bootcount(uint16_t* val) {
48+
49+
uint32_t *scratch2_addr = memory_open(AM62_MEM_OFFSET, AM62_MEM_LEN);
50+
if ( scratch2_addr == (void *)E_DEVICE ) {
51+
return E_DEVICE;
52+
}
53+
54+
uint32_t scratch2_val = memory_read(scratch2_addr);
55+
// low two bytes are the value, high two bytes are magic
56+
if ((scratch2_val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) {
57+
return E_BADMAGIC;
58+
}
59+
60+
*val = (uint16_t)(scratch2_val & 0x0000ffff);
61+
return 0;
62+
}
63+
64+
65+
int am62_write_bootcount(uint16_t val) {
66+
// NOTE: These must be volatile.
67+
// See https://github.com/brgl/busybox/blob/master/miscutils/devmem.c
68+
volatile uint32_t *scratch2_addr =
69+
(volatile uint32_t *)memory_open(AM62_MEM_OFFSET, AM62_MEM_LEN);
70+
if ( scratch2_addr == (void *)E_DEVICE ) {
71+
return E_DEVICE;
72+
}
73+
74+
volatile uint32_t *kick0r = scratch2_addr + (AM62_KICK0R_REG_OFFSET - AM62_SCRATCH2_REG_OFFSET) / 4;
75+
volatile uint32_t *kick1r = kick0r + 1; // (AM62_KICK1R_REG_OFFSET - AM62_SCRATCH2_REG_OFFSET) / 4;
76+
77+
// Disable write protection, then write to SCRATCH2
78+
*kick0r = AM62_KICK0_MAGIC;
79+
*kick1r = AM62_KICK1_MAGIC;
80+
uint32_t scratch2_val = (BOOTCOUNT_MAGIC & 0xffff0000) | (val & 0xffff);
81+
memory_write(scratch2_addr, scratch2_val);
82+
83+
// re-lock the write protection register
84+
*kick1r = 0;
85+
86+
// read back to verify:
87+
uint16_t read_val = 0;
88+
am62_read_bootcount(&read_val);
89+
if ( read_val != val ) {
90+
return E_WRITE_FAILED;
91+
}
92+
93+
return 0;
94+
}

src/am62x.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# pragma once
2+
3+
#include <stdbool.h>
4+
5+
#define AM62_PLAT_NAME "TI AM62x"
6+
7+
bool is_am62();
8+
int am62_read_bootcount(uint16_t* val);
9+
int am62_write_bootcount(uint16_t val);

src/bootcount.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "constants.h"
3131
#include "dt.h"
3232
#include "am33xx.h"
33+
#include "am62x.h"
3334
#include "imx8m.h"
3435
#include "imx93.h"
3536
#include "stm32mp1.h"
@@ -50,6 +51,11 @@ static const struct platform platforms[] = {
5051
.read_bootcount = am33_read_bootcount,
5152
.write_bootcount = am33_write_bootcount
5253
},
54+
{.name = AM62_PLAT_NAME,
55+
.detect = is_am62,
56+
.read_bootcount = am62_read_bootcount,
57+
.write_bootcount = am62_write_bootcount
58+
},
5359
{.name = IMX8M_PLAT_NAME,
5460
.detect = is_imx8m,
5561
.read_bootcount = imx8m_read_bootcount,

0 commit comments

Comments
 (0)