Skip to content

Commit

Permalink
fel: sid: unify SID functions into fel_read_sid()
Browse files Browse the repository at this point in the history
At the moment we have two functions reading the SID eFuses:
fel_get_sid_root_key() to read the "root key" (the first 128 bits), and
fel_get_sid() to read an arbitrary range. The latter does not use the
MMIO register workaround on affected SoCs, while the former only reads
that specific range of bits.

Unify the two functions into one that combines the advantanges of both:
we can read any range of eFuses, and it uses the MMIO register access
method, if needed. Switch the users to use the new function.

Signed-off-by: Andre Przywara <osp@andrep.de>
  • Loading branch information
apritzel committed Mar 5, 2023
1 parent c1f947e commit 4a0c8c7
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 40 deletions.
4 changes: 2 additions & 2 deletions fel.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ void aw_fel_print_sid(feldev_handle *dev, bool force_workaround)
pr_info("SID key (e-fuses) at 0x%08X\n",
soc_info->sid_base + soc_info->sid_offset);
}
fel_get_sid_root_key(dev, key, force_workaround);
fel_read_sid(dev, key, 0, sizeof(key), force_workaround);

/* output SID in "xxxxxxxx:xxxxxxxx:xxxxxxxx:xxxxxxxx" format */
for (unsigned i = 0; i <= 3; i++)
Expand All @@ -454,7 +454,7 @@ void aw_fel_dump_sid(feldev_handle *dev)
for (const sid_section *s = soc_info->sid_sections; s->name; s++) {
uint32_t count = s->size_bits / 32;

if (!fel_get_sid(dev, buffer, s->offset, count)) {
if (fel_read_sid(dev, buffer, s->offset, count * 4, false)) {
fprintf(stderr, "Read sid:%s failed\n", s->name);
return;
}
Expand Down
67 changes: 34 additions & 33 deletions fel_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,8 @@ void fel_clrsetbits_le32(feldev_handle *dev,
* SoCs. This function uses an alternative, register-based approach to retrieve
* the values.
*/
static void fel_get_sid_registers(feldev_handle *dev, uint32_t *result)
static void fel_get_sid_registers(feldev_handle *dev, uint32_t *result,
uint32_t offset, uint32_t length)
{
uint32_t arm_code[] = {
/* <sid_read_root_key>: */
Expand Down Expand Up @@ -576,54 +577,54 @@ static void fel_get_sid_registers(feldev_handle *dev, uint32_t *result)
/* <sid_base>: */
htole32(dev->soc_info->sid_base), /* SID base addr */
/* <offset>: */
htole32(0), /* first word to read */
htole32(offset), /* first word to read */
/* <end>: */
htole32(16), /* where to stop to read */
htole32(offset + length), /* where to stop to read */
/* retrieved SID values go here */
};
/* write and execute code */
aw_fel_write(dev, arm_code, dev->soc_info->scratch_addr, sizeof(arm_code));
aw_fel_execute(dev, dev->soc_info->scratch_addr);
/* read back the result */
aw_fel_read(dev, dev->soc_info->scratch_addr + sizeof(arm_code),
result, 4 * sizeof(uint32_t));
for (unsigned i = 0; i < 4; i++)
result, length);
for (unsigned i = 0; i < length / 4; i++)
result[i] = le32toh(result[i]);
}

/* Read the SID "root" key (128 bits). You need to pass the device handle,
* a pointer to a result array capable of receiving at least four 32-bit words,
* and a flag specifying if the register-access workaround should be enforced.
* Return value indicates whether the result is expected to be usable:
* The function will return `false` (and zero the result) if it cannot access
* the SID registers.
/**
* fel_read_sid() - Read the content of the SID eFuses.
* @dev: device handle for the FEL device
* @result: pointer of a buffer receiving the content of the eFuses
* @offset: beginning of the eFuses area to read, in bytes
* @length: length of the eFuses area to read, in bytes
* @force_workaround: whether to use the MMIO register based read method
*
* Read the contents of the non-volatile eFuses stored in the SoC. The size
* and supposed usage layout differs between SoCs, but the "root" key
* (containing some unique serial number) is always in the first 128 bits.
*
* Return: 0 if the operation was successful, a negative error code otherwise.
*/
bool fel_get_sid_root_key(feldev_handle *dev, uint32_t *result,
bool force_workaround)
int fel_read_sid(feldev_handle *dev, uint32_t *result,
unsigned int offset, unsigned int length,
bool force_workaround)
{
if (!dev->soc_info->sid_base) {
/* SID unavailable */
for (unsigned i = 0; i < 4; i++) result[i] = 0;
return false;
}
const soc_info_t *soc = dev->soc_info;

if (!soc->sid_base) /* SID unavailable */
return -2;
if ((offset & 3) || (length & 3)) /* needs to be 32-bit aligned */
return -3;

if (dev->soc_info->sid_fix || force_workaround)
if (soc->sid_fix || force_workaround)
/* Work around SID issues by using ARM thunk code */
fel_get_sid_registers(dev, result);
fel_get_sid_registers(dev, result, offset, length);
else
/* Read SID directly from memory */
fel_readl_n(dev, dev->soc_info->sid_base
+ dev->soc_info->sid_offset, result, 4);
return true;
}

bool fel_get_sid(feldev_handle *dev, uint32_t *result, uint32_t offset,
size_t count)
{
fel_readl_n(dev, dev->soc_info->sid_base
+ dev->soc_info->sid_offset + offset, result, count);

return true;
fel_readl_n(dev, soc->sid_base + soc->sid_offset + offset,
result, length);
return 0;
}

/* general functions, "FEL device" management */
Expand Down Expand Up @@ -859,7 +860,7 @@ feldev_list_entry *list_fel_devices(size_t *count)
strncpy(entry->soc_name, dev->soc_name, sizeof(soc_name_t));

/* retrieve SID bits */
fel_get_sid_root_key(dev, entry->SID, false);
fel_read_sid(dev, entry->SID, 0, 16, false);

feldev_close(dev);
free(dev);
Expand Down
8 changes: 3 additions & 5 deletions fel_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ void fel_clrsetbits_le32(feldev_handle *dev,
#define fel_setbits_le32(dev, addr, value) \
fel_clrsetbits_le32(dev, addr, 0, value)

/* retrieve SID root key */
bool fel_get_sid_root_key(feldev_handle *dev, uint32_t *result,
bool force_workaround);
bool fel_get_sid(feldev_handle *dev, uint32_t *result, uint32_t offset,
size_t count);
int fel_read_sid(feldev_handle *dev, uint32_t *result,
unsigned int offset, unsigned int length,
bool force_workaround);

bool aw_fel_remotefunc_prepare(feldev_handle *dev,
size_t stack_size,
Expand Down

0 comments on commit 4a0c8c7

Please sign in to comment.