[otp_ctrl] Update hjson file according to newest spec
This updates the hjson file according to the newest OTP controller
specification. The markdown documentation will follow in a subsequent
commit.
Note that there are still several TODOs in this file that will have to
be addressed during implementation and top-level integration.
Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/otp_ctrl/data/otp_ctrl.hjson b/hw/ip/otp_ctrl/data/otp_ctrl.hjson
index 16fcf23..e2ad5a6 100644
--- a/hw/ip/otp_ctrl/data/otp_ctrl.hjson
+++ b/hw/ip/otp_ctrl/data/otp_ctrl.hjson
@@ -5,28 +5,25 @@
clock_primary: "clk_i",
bus_device: "tlul",
bus_host: "none",
- estimated_gates: "32kGE" // Excluding OTP macro
///////////////////////////
// Interrupts and Alerts //
///////////////////////////
interrupt_list: [
- { name: "otp_access_done",
- desc: "A direct access command has completed."
+ { name: "otp_operation_done",
+ desc: "A direct access command or digest calculation operation has completed."
}
- { name: "otp_ctrl_err",
- desc: "An error has occurred during an access. Check the ERR_CODE register to get more information."
+ { name: "otp_error",
+ desc: "An error has occurred in the OTP controller. Check the ERR_CODE register to get more information."
}
],
alert_list: [
- // fast integrity check of buffered OTP partitions.
- { name: "otp_reg_parity_mismatch",
- desc: "This alert triggers if hardware detects a parity bit error in the buffered partitions.",
+ { name: "otp_integrity_mismatch",
+ desc: "This alert triggers if hardware detects a parity bit or digest error in the buffered partitions.",
}
- // background check digest mismatch
- { name: "otp_reg_digest_mismatch",
+ { name: "otp_consistency_mismatch",
desc: "This alert triggers if the digest over the buffered registers does not match with the digest stored in OTP.",
}
],
@@ -35,41 +32,40 @@
// Parameters //
////////////////
param_list: [
- { name: "NumLcPartitionWords",
- desc: "Number of 32bit words in the life cycle partition",
+ { name: "OtpByteAddressWidth",
+ desc: "Width of the OTP Byte address.",
type: "int",
- default: "4", // 4 x 32bit = 128bit
+ default: "11",
local: "true"
},
- { name: "NumSecretPartitionWords",
- desc: "Number of 32bit words in the secret partition",
+ { name: "NumCreatorSwCfgPartitionWords",
+ desc: "Number of 32bit words in the software config partitions.",
type: "int",
- default: "32", // 32 x 32bit = 1024bit
+ default: "192",
+ local: "true"
+ },
+ { name: "NumOwnerSwCfgPartitionWords",
+ desc: "Number of 32bit words in the software config partitions.",
+ type: "int",
+ default: "192",
local: "true"
},
{ name: "NumHwCfgWords",
- desc: "Number of 32bit words in the hardware config partition",
+ desc: "Number of 32bit words in the hardware config partition.",
type: "int",
- default: "8", // 8 x 32bit = 256bit
+ default: "16",
local: "true"
},
- // TODO: this will change once we add more switches to this partition.
- { name: "NumHwCfgReservedRegs",
- desc: "Number of unallocated 32bit OTP words in the hardware partition",
+ { name: "NumLcPartitionWords",
+ desc: "Number of 32bit words in the life cycle partition.",
type: "int",
- default: "6", // 6 x 32bit = 192bit
+ default: "56",
local: "true"
},
- { name: "NumSwCfgPartitionWords",
- desc: "Number of 32bit words in the software config partition",
+ { name: "NumSecretPartitionWords",
+ desc: "Number of 32bit words in the secret partition.",
type: "int",
- default: "212", // 212 x 32bit = 256bit
- local: "true"
- },
- { name: "NumSwCfgWindowWords",
- desc: "Number of 32bit words in the software config partition window",
- type: "int",
- default: "256", // 212 x 32bit = 6784bit, but window is 256 large for alignment reasons
+ default: "56",
local: "true"
},
{ name: "NumDebugWindowWords",
@@ -83,17 +79,25 @@
/////////////////////////////
// Intermodule Connections //
/////////////////////////////
+ // TODO: these need to be refined during implementation and integration
inter_signal_list: [
+ // CSRNG interface
+ { struct: "otp_csrng"
+ type: "req_rsp"
+ name: "otp_csrng"
+ act: "req"
+ package: "otp_ctrl_pkg"
+ }
// Power manager init command
- { struct: "pwr_otp_init"
+ { struct: "pwr_otp"
type: "req_rsp"
name: "pwr_otp_init"
act: "rsp"
- package: "otp_ctrl_pkg"
+ package: "pwrmgr_pkg"
}
// Status output to power manager
{ struct: "otp_pwr_state"
- type: "uni" // no `_req/rsp`
+ type: "uni"
name: "otp_pwr_state"
act: "req"
package: "otp_ctrl_pkg"
@@ -107,38 +111,59 @@
}
// Broadcast to LC
{ struct: "otp_lc_data"
- type: "uni" // no `_req/rsp`
+ type: "uni"
name: "otp_lc_data"
act: "req"
package: "otp_ctrl_pkg"
}
// Broadcast from LC
- { struct: "lc_tx_t"
- type: "uni" // no `_req/rsp`
+ { struct: "lc_tx"
+ type: "uni"
name: "lc_provision_en"
act: "rcv"
- package: "otp_ctrl_pkg" // TODO: move to LC package
+ package: "lifecycle_pkg" // TODO: move to LC package?
}
- { struct: "lc_tx_t"
- type: "uni" // no `_req/rsp`
+ { struct: "lc_tx"
+ type: "uni"
name: "lc_test_en"
act: "rcv"
- package: "otp_ctrl_pkg" // TODO: move to LC package
+ package: "lifecycle_pkg" // TODO: move to LC package?
}
- //Broadcast to Key Manager
+ // Broadcast to Key Manager
{ struct: "keymgr_key"
- type: "uni" // no `_req/rsp`
+ type: "uni"
name: "otp_keymgr_key"
act: "req"
- package: "otp_ctrl_pkg" // TODO: move this to keymgr package
+ package: "otp_ctrl_pkg" // TODO: move this to keymgr package?
}
- //Broadcast to Flash Controller
+ // Broadcast to Flash Controller
{ struct: "flash_key"
- type: "uni" // no `_req/rsp`
+ type: "uni"
name: "otp_flash_key"
act: "req"
package: "otp_ctrl_pkg"
}
+ // Key request from Main RAM Scrambler
+ { struct: "ram_main_key"
+ type: "req_rsp"
+ name: "otp_ram_main_key"
+ act: "rsp"
+ package: "otp_ctrl_pkg"
+ }
+ // Key request from Retention RAM Scrambler
+ { struct: "ram_ret_aon_key"
+ type: "req_rsp"
+ name: "otp_ram_ret_aon_key"
+ act: "rsp"
+ package: "otp_ctrl_pkg"
+ }
+ // Key request from OTBN RAM Scrambler
+ { struct: "otbn_ram_key"
+ type: "req_rsp"
+ name: "otp_otbn_ram_key"
+ act: "rsp"
+ package: "otp_ctrl_pkg"
+ }
] // inter_signal_list
regwidth: "32",
@@ -147,35 +172,122 @@
////////////////////////
// Ctrl / Status CSRs //
////////////////////////
+ // TODO: this may have to be refined during implementation.
{ name: "STATUS",
desc: "OTP status register.",
swaccess: "ro",
hwaccess: "hwo",
fields: [
- { bits: "31:0",
- name: "err_code",
- desc: '''This register holds information on the OTP controller status.
- TODO: make this an enum {INIT, READY, ERROR, LOCKED, WRITE_PENDING, READ_PENDING}
- '''
+ { bits: "2:0"
+ enum: [
+ { value: "0",
+ name: "IDLE",
+ desc: '''
+ OTP is in IDLE state and ready to accept commands.
+ '''
+ },
+ { value: "1",
+ name: "INIT",
+ desc: '''
+ OTP is initializing.
+ '''
+ },
+ { value: "2",
+ name: "ERROR",
+ desc: '''
+ An error condition has occurred.
+ Please check the ERR_CODE register for specifics.
+ '''
+ },
+ { value: "3",
+ name: "READ_PENDING",
+ desc: '''
+ A read operation is pending.
+ '''
+ },
+ { value: "4",
+ name: "WRITE_PENDING",
+ desc: '''
+ A write operation is pending.
+ '''
+ },
+ ]
}
]
}
+ // TODO: need to define error codes for errors during background operations (or add alerts for them)
{ name: "ERR_CODE",
- desc: "OTP Ctrl Error Code",
+ desc: '''This register holds information on error conditions and should be
+ checked when !!STATUS indicates that an error has occurred, or when
+ an !!INTR_STATE.otp_error has been triggered.
+ '''
swaccess: "ro",
hwaccess: "hwo",
fields: [
- { bits: "31:0",
- name: "err_code",
- desc: '''This register holds information on the error that occurred.
- To be checked after an error interrupt occurred.
- TODO: add reference to error type here.
- '''
+ {
+ bits: "2:0"
+ enum: [
+ { value: "0",
+ name: "NONE",
+ desc: '''
+ No error condition has occurred.
+ '''
+ },
+ { value: "1",
+ name: "MISSING_INIT",
+ desc: '''
+ Read or write operation attempted before initialization.
+ The OTP controller automatically recovers from this error when initializing.
+ '''
+ },
+ { value: "2",
+ name: "INVALID_CMD",
+ desc: '''
+ Invalid command has been written to !!DIRECT_ACCESS_CMD.
+ The OTP controller automatically recovers from this error when issuing a new command.
+ '''
+ },
+ { value: "3",
+ name: "READ_CORR",
+ desc: '''
+ A correctable error has occured during a read operation.
+ The OTP controller automatically recovers from this error when issuing a new command.
+ '''
+ },
+ { value: "4",
+ name: "READ_UNCORR",
+ desc: '''
+ An uncorrectable error has occurred during a read operation.
+ The OTP controller automatically recovers from this error when issuing a new command.
+ '''
+ },
+ { value: "5",
+ name: "READ_ERR",
+ desc: '''
+ An error has occurred during a read operation.
+ The OTP controller may not be able to automatically recover from this error and has to be reset.
+ '''
+ },
+ { value: "6",
+ name: "WRITE_ERR",
+ desc: '''
+ An error has occurred during a programming operation.
+ The OTP controller may not be able to automatically recover from this error and has to be reset.
+ '''
+ },
+ { value: "7",
+ name: "ESCALATED",
+ desc: '''
+ OTP has been rendered unusable due to an escalation.
+ This is a terminal state.
+ '''
+ },
+ ]
}
]
}
{ name: "DIRECT_ACCESS_CMD",
- desc: "OTP array command for direct access.",
+ desc: "Command register for direct accesses.",
swaccess: "r0w1c",
hwaccess: "hro",
hwext: "true",
@@ -183,216 +295,248 @@
fields: [
{ bits: "0",
name: "read",
- desc: "Initiates a readout sequence that reads the location specified by !!DIRECT_ACCESS_ADDRESS and !!DIRECT_ACCESS_SIZE. The command places the read data in !!DIRECT_ACCESS_RDATA."
+ desc: '''
+ Initiates a readout sequence that reads the location specified
+ by !!DIRECT_ACCESS_ADDRESS. The command places the data read into
+ !!DIRECT_ACCESS_RDATA_0 and !!DIRECT_ACCESS_RDATA_1 (for 64bit partitions).
+ '''
}
{ bits: "1",
name: "write",
- desc: "Initiates a programming sequence that writes the !!DIRECT_ACCESS_WDATA to the location specified by !!DIRECT_ACCESS_ADDRESS and !!DIRECT_ACCESS_SIZE."
+ desc: '''
+ Initiates a programming sequence that writes the data in !!DIRECT_ACCESS_WDATA_0
+ and !!DIRECT_ACCESS_WDATA_1 (for 64bit partitions) to the location specified by
+ !!DIRECT_ACCESS_ADDRESS.
+ '''
}
]
}
{ name: "DIRECT_ACCESS_ADDRESS",
- desc: "OTP array address for direct access.",
+ desc: "Address register for direct accesses.",
swaccess: "rw",
hwaccess: "hro",
fields: [
- { bits: "9:0",
- desc: '''This is the address for the OTP word to be read or written through
- the direct access interface. Note that the address is 32bit aligned internally,
- hence bit 1:0 are ignored.'''
+ { bits: "OtpByteAddressWidth-1:0",
+ desc: '''
+ This is the address for the OTP word to be read or written through
+ the direct access interface. Note that the address is aligned to the access size
+ internally, hence bits 1:0 are ignored for 32bit accesses, and bits 2:0 are ignored
+ for 64bit accesses.
+ '''
}
]
}
- { name: "DIRECT_ACCESS_SIZE",
- desc: "OTP array acces size for direct access.",
- swaccess: "rw",
- hwaccess: "hro",
- fields: [
- { bits: "1:0",
- desc: '''This is the access size for for the OTP word to be read or written through
- the direct access interface. Note that the address is always aligned to the
- access size internally. 0 = 1 Byte, 1 = 2 Bytes, 2 = 4 Bytes, 3 = 8 Bytes.'''
- }
- ]
- }
- { multireg: { name: "DIRECT_ACCESS_WDATA",
- desc: '''Write data for direct access. Note that only 1s are effectively programmed into the array. 0s do not have any effect.
+ { multireg: {
+ name: "DIRECT_ACCESS_WDATA",
+ desc: '''Write data for direct accesses.
+ Hardware automatically determines the access granule (32bit or 64bit) based on which
+ partition is being written to.
''',
- count: "2", // 2 x 32bit = 64bit
- swaccess: "rw",
- hwaccess: "hro",
- hwqe: "true",
- cname: "WORD",
- fields: [
- { bits: "31:0"
- }
- ]
- }
+ count: "2", // 2 x 32bit = 64bit
+ swaccess: "rw",
+ hwaccess: "hro",
+ hwqe: "true",
+ cname: "WORD",
+ fields: [
+ { bits: "31:0"
+ }
+ ]
+ }
},
- { multireg: { name: "DIRECT_ACCESS_RDATA",
- desc: '''Read data for direct access.
+ { multireg: {
+ name: "DIRECT_ACCESS_RDATA",
+ desc: '''Read data for direct accesses.
+ Hardware automatically determines the access granule (32bit or 64bit) based on which
+ partition is read from.
''',
- count: "2", // 2 x 32bit = 64bit
- swaccess: "ro",
- hwaccess: "hwo",
- cname: "WORD",
- fields: [
- { bits: "31:0"
- desc: ""
- }
- ]
- }
+ count: "2", // 2 x 32bit = 64bit
+ swaccess: "ro",
+ hwaccess: "hwo",
+ cname: "WORD",
+ fields: [
+ { bits: "31:0"
+ }
+ ]
+ }
+ },
+ { name: "CHECK_PERIOD_REGEN",
+ desc: '''
+ Register write enable for !!INTEGRITY_CHECK_PERIOD_MSB and !!CONSISTENCY_CHECK_PERIOD_MSB.
+ ''',
+ swaccess: "rw1c",
+ hwaccess: "hro",
+ fields: [
+ { bits: "0",
+ desc: '''
+ When true, !!INTEGRITY_CHECK_PERIOD_MSB and !!CONSISTENCY_CHECK_PERIOD_MSB registers cannot be written anymore.
+ '''
+ resval: 1,
+ },
+ ]
+ },
+ { name: "INTEGRITY_CHECK_PERIOD_MSB",
+ desc: '''
+ This value specifies the maximum period that can be generated pseudo-randomly.
+ Only applies to the HW_CFG and SECRET partitions if they are locked.
+ '''
+ swaccess: "rw",
+ hwaccess: "hro",
+ regwen: "CHECK_PERIOD_REGEN",
+ fields: [
+ { bits: "5:0",
+ desc: '''
+ The pseudo-random period is generated using a 40bit LFSR internally, and this value defines
+ the bit mask to be applied to the LFSR output in order to limit its range. A value of N will generate
+ an internal mask of 2^N-1. So for N=16 this would allow the maximum pseudo-random period to be 0xFFFF cycles.
+ The default value has been set to 27, which corresponds to a maximum period of a bit more than 1.3s at 100MHz.
+ '''
+ resval: "27"
+ }
+ ]
+ }
+ { name: "CONSISTENCY_CHECK_PERIOD_MSB",
+ desc: '''
+ This value specifies the maximum period that can be generated pseudo-randomly.
+ This applies to the LIFE_CYCLE partition and the HW_CFG and SECRET partitions (but only if they are locked).
+ '''
+ swaccess: "rw",
+ hwaccess: "hro",
+ regwen: "CHECK_PERIOD_REGEN",
+ fields: [
+ { bits: "5:0",
+ desc: '''
+ The pseudo-random period is generated using a 40bit LFSR internally, and this value defines
+ the bit mask to be applied to the LFSR output in order to limit its range. A value of N will generate
+ an internal mask of 2^N-1. So for N=16 this would allow the maximum pseudo-random period to be 0xFFFF cycles.
+ The default value has been set to 30, which corresponds to a maximum period of a bit more than 10s at 100MHz.
+ '''
+ resval: "30"
+ }
+ ]
+ }
+
+ ////////////////////////////////////
+ // Dynamic Locks of SW Parititons //
+ ////////////////////////////////////
+ { name: "CREATOR_SW_CFG_READ_LOCK",
+ desc: '''
+ Runtime read lock for the creator software partition.
+ ''',
+ swaccess: "rw1c",
+ hwaccess: "hro",
+ fields: [
+ { bits: "0",
+ desc: '''
+ When true, read access to the !!CREATOR_SW_CFG partition is locked.
+ '''
+ resval: 1,
+ },
+ ]
+ },
+ { name: "OWNER_SW_CFG_READ_LOCK",
+ desc: '''
+ Runtime read lock for the owner software partition.
+ ''',
+ swaccess: "rw1c",
+ hwaccess: "hro",
+ fields: [
+ { bits: "0",
+ desc: '''
+ When true, read access to the !!OWNER_SW_CFG partition is locked.
+ '''
+ resval: 1,
+ },
+ ]
},
///////////////////////
// Integrity Digests //
///////////////////////
- { skipto: "0x050" }
-
- { name: "SECRET_INTEGRITY_DIGEST_CALC",
- desc: "Compute and program digest for secret partition.",
+ { name: "HW_CFG_DIGEST_CALC",
+ desc: "Compute and program digest for the HW_CFG partition.",
swaccess: "r0w1c",
hwaccess: "hro",
fields: [
{ bits: "0",
- desc: '''Writing 1 to this register computes the partition digest and burns it into OTP.
- Note: this effectively locks write and read access to this partition after power cycling the device.
- '''
+ desc: '''
+ Writing 1 to this register computes the partition digest and burns it into OTP.
+ After a reset, write access to the HW_CFG partition is locked, and the digest
+ becomes visible in !!HW_CFG_DIGEST.
+ '''
}
]
}
-
- { name: "HW_CFG_INTEGRITY_DIGEST_CALC",
- desc: "Compute and program digest for the hardware config partition.",
+ { name: "SECRET_DIGEST_CALC",
+ desc: "Compute and program digest for the secret partition.",
swaccess: "r0w1c",
hwaccess: "hro",
fields: [
{ bits: "0",
- desc: '''Writing 1 to this register computes the partition digest and burns it into OTP.
- Note that this effectively locks write access to this partition after power cycling the device.
- '''
+ desc: '''
+ Writing 1 to this register computes the partition digest and burns it into OTP.
+ After a reset, write and read access to the SECRET partition is locked, and the digest
+ becomes visible in !!SECRET_DIGEST.
+ '''
}
]
}
-
- { name: "SW_CFG_INTEGRITY_DIGEST_CALC",
- desc: "Compute and program digest for the software config partition.",
- swaccess: "r0w1c",
- hwaccess: "hro",
- fields: [
- { bits: "0",
- desc: '''Writing 1 to this register computes the partition digest and burns it into OTP.
- Note that effectively locks write access to this partition after power cycling the device.
- '''
- }
- ]
- }
-
- { name: "SECRET_INTEGRITY_DIGEST",
- desc: "Integrity digest for the secret config partition",
+ { name: "CREATOR_SW_CFG_DIGEST",
+ desc: "Integrity digest for the creator software config partition.",
swaccess: "ro",
hwaccess: "hwo",
hwext: "true",
fields: [
{ bits: "31:0",
- desc: '''The integrity digest is 0 by default. Once the partition has been locked,
- this digest is set to a nonzero value.'''
+ desc: '''
+ The integrity digest is 0 by default. Software must write this
+ digest value via the direct access interface in order to lock the partition.
+ After a reset, write access to the !!CREATOR_SW_CFG partition is locked and
+ the digest becomes visible in this CSR.
+ '''
}
]
}
- { name: "HW_CFG_INTEGRITY_DIGEST",
+ { name: "OWNER_SW_CFG_DIGEST",
+ desc: "Integrity digest for the owner software config partition.",
+ swaccess: "ro",
+ hwaccess: "hwo",
+ hwext: "true",
+ fields: [
+ { bits: "31:0",
+ desc: '''
+ The integrity digest is 0 by default. Software must write this
+ digest value via the direct access interface in order to lock the partition.
+ After a reset, write access to the !!OWNER_SW_CFG partition is locked and
+ the digest becomes visible in this CSR.
+ '''
+ }
+ ]
+ }
+ { name: "HW_CFG_DIGEST",
desc: "Hardware config partition integrity digest.",
swaccess: "ro",
hwaccess: "hwo",
hwext: "true",
fields: [
{ bits: "31:0",
- desc: '''The integrity digest is 0 by default. Once the partition has been locked,
- this digest is set to a nonzero value.'''
+ desc: '''
+ The integrity digest is 0 by default. Once the HW_CFG partition has been locked by
+ writing to !!HW_CFG_DIGEST_CALC, the digest becomes visible in this CSR after a reset.
+ '''
}
]
}
- { name: "SW_CFG_INTEGRITY_DIGEST",
- desc: "Integrity digest for the software config partition",
+ { name: "SECRET_DIGEST",
+ desc: "Integrity digest for the secret config partition.",
swaccess: "ro",
hwaccess: "hwo",
hwext: "true",
fields: [
{ bits: "31:0",
- desc: '''The integrity digest is 0 by default. Once the partition has been locked,
- this digest is set to a nonzero value.'''
- }
- ]
- }
-
- //////////////////////////
- // Life Cycle Partition //
- //////////////////////////
- { skipto: "0x100" }
-
- { multireg: { name: "LC_STATE",
- desc: '''Life cycle state.
- ''',
- count: "6", // 6 x8bit = 48bit
- swaccess: "ro",
- hwaccess: "hwo",
- cname: "BYTE",
- fields: [
- { bits: "7:0"
- desc: "TODO: explain state encoding"
- }
- ]
- }
- },
- { name: "ID_STATE",
- desc: "ID state of the device.",
- swaccess: "ro",
- hwaccess: "hwo",
- fields: [
- { bits: "7:0",
- desc: '''The ID state is BLANK when set to 0x00, and CREATOR_PERSONALIZED if set to 0x6D.
- Note that this affects certain secrets stored in FLASH and OTP. For instance, the
- !!CREATOR_ROOT_KEY_SHARE0 stored in OTP is readable and writable by software if BLANK, and
- all hardware outputs to the LC controller and the key manager will be tied to 0 in this state.
- If ID state is CREATOR_PERSONALIZED the !!CREATOR_ROOT_KEY_SHARE0 is not accessible by software anymore,
- and all hardware outputs to the LC controller and key manager will be driven.
- '''
- }
- ]
- }
- // TODO: update XXX related bits
- { name: "TEST_XXX_CNT",
- desc: "Counters related to the test and XXX states."
- swaccess: "ro",
- hwaccess: "hwo",
- fields: [
- { bits: "7:0",
- name: "TEST_STATE_CNT"
- desc: "TODO: add description of this counter"
- }
- { bits: "15:8",
- name: "TEST_UNLOCK_CNT"
- desc: "Number of times test unlock has been attempted."
- }
- { bits: "23:16",
- name: "TEST_EXIT_CNT"
- desc: "Number of times test exit has been attempted."
- }
- { bits: "31:24",
- name: "XXX_UNLOCK_CNT"
- desc: "Number of times XXX unlock has been attempted."
- }
- ]
- }
- { name: "TRANSITION_CNT",
- desc: "Counter for total amount of state transition attempts.",
- swaccess: "ro",
- hwaccess: "hwo",
- fields: [
- { bits: "15:0",
- desc: '''This counter will be incremented upon each state transition attempt,
- or when the transition command coming from the life cycle controller is invalid.
- '''
+ desc: '''
+ The integrity digest is 0 by default. Once the SECRET partition has been locked by
+ writing to !!SECRET_DIGEST_CALC, the digest becomes visible in this CSR after a reset.
+ '''
}
]
}
@@ -400,75 +544,182 @@
///////////////////////////////
// Hardware Config Partition //
///////////////////////////////
- { skipto: "0x200" }
+ { skipto: "0x100" }
- // TODO: update XXX related bits
- { name: "HW_CFG_LOCK",
- desc: "Hardware config lock values.",
+ { name: "TEST_TOKENS_LOCK",
+ desc: '''
+ TEST token lock value. When set to nonzero, the life cycle tokens TEST_UNLOCK_TOKEN
+ and TEST_EXIT_TOKEN are no longer accessible to software.
+ '''
swaccess: "ro",
hwaccess: "hwo",
hwext: "true",
fields: [
- { bits: "2:0",
- name: "TEST_TOKENS_LOCK",
- desc: '''TEST token lock value. When set to nonzero, the life cycle
- TEST_*_TOKENS are no longer accessible to software.
- '''
- }
- {
- bits: "7:3",
- name: "XXX_TOKEN_LOCK",
- desc: '''XXX token lock value. When set to nonzero, the life cycle
- XXX_*_TOKENS are no longer accessible to software.
- '''
+ { bits: "31:0"
}
]
}
- // TODO: update this field once known
- { multireg: { name: "HW_CFG",
- desc: '''Unallocated OTP bits.
+ { name: "RMA_TOKEN_LOCK",
+ desc: '''
+ RMA token lock value. When set to nonzero, the life cycle
+ RMA_TOKEN is no longer accessible to software.
+ '''
+ swaccess: "ro",
+ hwaccess: "hwo",
+ hwext: "true",
+ fields: [
+ { bits: "31:0",
+ }
+ ]
+ }
+ { name: "FLASH_KEYS_LOCK",
+ desc: '''
+ FLASH key lock value. When set to nonzero, the
+ FLASH_ADDR_KEY and FLASH_DATA_KEY are no longer accessible to software.
+ '''
+ swaccess: "ro",
+ hwaccess: "hwo",
+ hwext: "true",
+ fields: [
+ { bits: "31:0",
+ }
+ ]
+ }
+ { name: "SRAM_KEY_LOCK",
+ desc: '''
+ SRAM key lock value. When set to nonzero, the
+ SRAM_KEY_LOCK is no longer accessible to software.
+ '''
+ swaccess: "ro",
+ hwaccess: "hwo",
+ hwext: "true",
+ fields: [
+ { bits: "31:0",
+ }
+ ]
+ }
+ { name: "CREATOR_KEY_LOCK",
+ desc: '''
+ CREATOR key lock value. When set to nonzero, the
+ CREATOR_ROOT_KEY_SHARE0 and CREATOR_ROOT_KEY_SHARE1 are no longer accessible to software.
+ '''
+ swaccess: "ro",
+ hwaccess: "hwo",
+ hwext: "true",
+ fields: [
+ { bits: "31:0",
+ }
+ ]
+ }
+ // TODO: there is likely more collateral that needs to be stored in the HW_CFG partition.
+ // add them as they become apparent.
+
+ //////////////////////////
+ // Life Cycle Partition //
+ //////////////////////////
+ { skipto: "0x200" }
+
+ { multireg: {
+ name: "LC_STATE",
+ desc: '''
+ Life cycle state, comprised of 9 Byte groups.
+ TODO: add link to LC controller spec.
''',
- count: "NumHwCfgReservedRegs", // 7 x32bit = 192bit
- swaccess: "ro",
- hwaccess: "hwo",
- cname: "WORD",
- fields: [
- { bits: "31:0"
- }
- ]
- }
+ count: "9",
+ swaccess: "ro",
+ hwaccess: "hwo",
+ cname: "BYTE",
+ fields: [
+ { bits: "7:0"
+ enum: [
+ { value: "0",
+ name: "BLANK",
+ desc: '''
+ 0x00
+ '''
+ },
+ { value: "106",
+ name: "ONE",
+ desc: '''
+ 0x6A
+ '''
+ },
+ { value: "149",
+ name: "TWO",
+ desc: '''
+ 0x95
+ '''
+ },
+ { value: "255",
+ name: "FULL",
+ desc: '''
+ 0xFF
+ '''
+ },
+ ]
+ }
+ ]
+ }
},
+ { name: "TRANSITION_CNT",
+ desc: "Counter for total amount of state transition attempts.",
+ swaccess: "ro",
+ hwaccess: "hwo",
+ fields: [
+ { bits: "31:0",
+ desc: '''
+ This counter will be incremented upon each state transition attempt,
+ or when the transition command coming from the life cycle controller is invalid.
+ '''
+ }
+ ]
+ }
///////////////////////////////
// Software Config Partition //
///////////////////////////////
-
- // TODO: split SW partition into creator and owner partitions
{ skipto: "0x300" }
{ window: {
- name: "SW_CFG"
- items: "NumSwCfgWindowWords" // 212 x 32bit = 6784bit, but window is 256 large for alignment reasons
+ name: "CREATOR_SW_CFG"
+ items: "NumCreatorSwCfgPartitionWords"
swaccess: "ro",
- desc: '''Any read to this window directly maps to the corresponding offset in the software
- config partition, and triggers an OTP readout of the bytes requested. Note that the transaction
- will block until OTP readout has completed.
- '''
+ desc: '''
+ Any read to this window directly maps to the corresponding offset in the creator software
+ config partition, and triggers an OTP readout of the Bytes requested. Note that the transaction
+ will block until OTP readout has completed.
+ '''
+ }
+ }
+
+ { skipto: "0x600" }
+
+ { window: {
+ name: "OWNER_SW_CFG"
+ items: "NumOwnerSwCfgPartitionWords"
+ swaccess: "ro",
+ desc: '''
+ Any read to this window directly maps to the corresponding offset in the owner software
+ config partition, and triggers an OTP readout of the Bytes requested. Note that the transaction
+ will block until OTP readout has completed.
+ '''
}
}
//////////////////////
// Test Access Port //
//////////////////////
- { skipto: "0x800" }
+ { skipto: "0xA00" }
+ // TODO: may have to update description, once it is known how RAW unlock is handled.
{ window: {
name: "TEST_ACCESS"
items: "NumDebugWindowWords"
swaccess: "rw",
- desc: '''This directly maps to the OTP macro address map. Note that this is only
- accessible during the test life cycle state of the OpenTitan device.
- '''
+ desc: '''
+ This maps to the register file of the proprietary OTP macro. Note that this is only
+ accessible during the TEST life cycle state.
+ '''
}
}
],