Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
487c869d
Commit
487c869d
authored
Sep 12, 2017
by
davidcunado-arm
Committed by
GitHub
Sep 12, 2017
Browse files
Merge pull request #1088 from soby-mathew/sm/sds_scmi
Introduce SDS Driver
parents
800a55ea
18e279eb
Changes
24
Hide whitespace changes
Inline
Side-by-side
plat/arm/css/drivers/sds/aarch64/sds_helpers.S
0 → 100644
View file @
487c869d
/*
*
Copyright
(
c
)
2017
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
*
SPDX
-
License
-
Identifier
:
BSD
-
3
-
Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
#include "../sds.h"
#include "../sds_private.h"
.
globl
sds_get_primary_cpu_id
/
*
*
int
sds_get_primary_cpu_id
(
void
)
;
*
Return
the
primary
CPI
ID
from
SDS
Structure
*
Returns
CPUID
on
success
or
-
1
on
failure
*/
func
sds_get_primary_cpu_id
mov_imm
x0
,
PLAT_ARM_SDS_MEM_BASE
mov
w2
,
#
SDS_REGION_SIGNATURE
ldr
w1
,
[
x0
]
/
*
Check
if
the
SDS
region
signature
found
*/
cmp
w2
,
w1
,
uxth
b.ne
2
f
/
*
Get
the
structure
count
from
region
descriptor
in
`
w1
*/
ubfx
w1
,
w1
,
#
SDS_REGION_STRUCT_COUNT_SHIFT
,
#
SDS_REGION_STRUCT_COUNT_WIDTH
cbz
w1
,
2
f
add
x0
,
x0
,
#
SDS_REGION_DESC_SIZE
/
*
Initialize
the
loop
iterator
count
in
w3
*/
mov
w3
,
#
0
loop_begin
:
ldrh
w2
,
[
x0
]
cmp
w2
,
#
SDS_AP_CPU_INFO_STRUCT_ID
b.ne
continue_loop
/
*
We
have
found
the
required
structure
*/
ldr
w0
,
[
x0
,#(
SDS_HEADER_SIZE
+
SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET
)]
ret
continue_loop
:
/
*
Increment
the
loop
counter
and
exit
loop
if
counter
==
structure
count
*/
add
w3
,
w3
,
#
0x1
cmp
w1
,
w3
b.eq
2
f
/
*
Read
the
2
nd
word
in
header
*/
ldr
w2
,
[
x0
,#
4
]
/
*
Get
the
structure
size
from
header
*/
ubfx
x2
,
x2
,
#
SDS_HEADER_STRUCT_SIZE_SHIFT
,
#
SDS_HEADER_STRUCT_SIZE_WIDTH
/
*
Add
the
structure
size
and
SDS
HEADER
SIZE
to
point
to
next
header
*/
add
x2
,
x2
,
#
SDS_HEADER_SIZE
add
x0
,
x0
,
x2
b
loop_begin
2
:
mov
w0
,
#
0xffffffff
ret
endfunc
sds_get_primary_cpu_id
plat/arm/css/drivers/sds/sds.c
0 → 100644
View file @
487c869d
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <css_def.h>
#include <stdint.h>
#include <string.h>
#include "sds.h"
#include "sds_private.h"
/*
* Variables used to track and maintain the state of the memory region reserved
* for usage by the SDS framework.
*/
/* Pointer to the base of the SDS memory region */
static
uintptr_t
sds_mem_base
;
/* Size of the SDS memory region in bytes */
static
size_t
sds_mem_size
;
/*
* Perform some non-exhaustive tests to determine whether any of the fields
* within a Structure Header contain obviously invalid data.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
static
int
sds_struct_is_valid
(
uintptr_t
header
)
{
size_t
struct_size
=
GET_SDS_HEADER_STRUCT_SIZE
(
header
);
/* Zero is not a valid identifier */
if
(
GET_SDS_HEADER_ID
(
header
)
==
0
)
return
SDS_ERR_FAIL
;
/* Check SDS Schema version */
if
(
GET_SDS_HEADER_VERSION
(
header
)
==
SDS_REGION_SCH_VERSION
)
return
SDS_ERR_FAIL
;
/* The SDS Structure sizes have to be multiple of 8 */
if
((
struct_size
==
0
)
||
((
struct_size
%
8
)
!=
0
))
return
SDS_ERR_FAIL
;
if
(
struct_size
>
sds_mem_size
)
return
SDS_ERR_FAIL
;
return
SDS_OK
;
}
/*
* Validate the SDS structure headers.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
static
int
validate_sds_struct_headers
(
void
)
{
unsigned
int
i
,
structure_count
;
uintptr_t
header
;
structure_count
=
GET_SDS_REGION_STRUCTURE_COUNT
(
sds_mem_base
);
if
(
structure_count
==
0
)
return
SDS_ERR_FAIL
;
header
=
sds_mem_base
+
SDS_REGION_DESC_SIZE
;
/* Iterate over structure headers and validate each one */
for
(
i
=
0
;
i
<
structure_count
;
i
++
)
{
if
(
sds_struct_is_valid
(
header
)
!=
SDS_OK
)
{
WARN
(
"SDS: Invalid structure header detected
\n
"
);
return
SDS_ERR_FAIL
;
}
header
+=
GET_SDS_HEADER_STRUCT_SIZE
(
header
)
+
SDS_HEADER_SIZE
;
}
return
SDS_OK
;
}
/*
* Get the structure header pointer corresponding to the structure ID.
* Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error.
*/
static
int
get_struct_header
(
uint32_t
structure_id
,
struct_header_t
**
header
)
{
unsigned
int
i
,
structure_count
;
uintptr_t
current_header
;
assert
(
header
);
structure_count
=
GET_SDS_REGION_STRUCTURE_COUNT
(
sds_mem_base
);
if
(
structure_count
==
0
)
return
SDS_ERR_STRUCT_NOT_FOUND
;
current_header
=
((
uintptr_t
)
sds_mem_base
)
+
SDS_REGION_DESC_SIZE
;
/* Iterate over structure headers to find one with a matching ID */
for
(
i
=
0
;
i
<
structure_count
;
i
++
)
{
if
(
GET_SDS_HEADER_ID
(
current_header
)
==
structure_id
)
{
*
header
=
(
struct_header_t
*
)
current_header
;
return
SDS_OK
;
}
current_header
+=
GET_SDS_HEADER_STRUCT_SIZE
(
current_header
)
+
SDS_HEADER_SIZE
;
}
*
header
=
NULL
;
return
SDS_ERR_STRUCT_NOT_FOUND
;
}
/*
* Check if a structure header corresponding to the structure ID exists.
* Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND
* if not found.
*/
int
sds_struct_exists
(
unsigned
int
structure_id
)
{
struct_header_t
*
header
=
NULL
;
int
ret
;
ret
=
get_struct_header
(
structure_id
,
&
header
);
if
(
ret
==
SDS_OK
)
{
assert
(
header
);
}
return
ret
;
}
/*
* Read from field in the structure corresponding to `structure_id`.
* `fld_off` is the offset to the field in the structure and `mode`
* indicates whether cache maintenance need to performed prior to the read.
* The `data` is the pointer to store the read data of size specified by `size`.
* Returns SDS_OK on success or corresponding error codes on failure.
*/
int
sds_struct_read
(
uint32_t
structure_id
,
unsigned
int
fld_off
,
void
*
data
,
size_t
size
,
sds_access_mode_t
mode
)
{
int
status
;
uintptr_t
field_base
;
struct_header_t
*
header
=
NULL
;
if
(
!
data
)
return
SDS_ERR_INVALID_PARAMS
;
/* Check if a structure with this ID exists */
status
=
get_struct_header
(
structure_id
,
&
header
);
if
(
status
!=
SDS_OK
)
return
status
;
assert
(
header
);
if
(
mode
==
SDS_ACCESS_MODE_CACHED
)
inv_dcache_range
((
uintptr_t
)
header
,
SDS_HEADER_SIZE
+
size
);
if
(
!
IS_SDS_HEADER_VALID
(
header
))
{
WARN
(
"SDS: Reading from un-finalized structure 0x%x
\n
"
,
structure_id
);
return
SDS_ERR_STRUCT_NOT_FINALIZED
;
}
if
((
fld_off
+
size
)
>
GET_SDS_HEADER_STRUCT_SIZE
(
header
))
return
SDS_ERR_FAIL
;
field_base
=
(
uintptr_t
)
header
+
SDS_HEADER_SIZE
+
fld_off
;
if
(
check_uptr_overflow
(
field_base
,
size
-
1
))
return
SDS_ERR_FAIL
;
/* Copy the required field in the struct */
memcpy
(
data
,
(
void
*
)
field_base
,
size
);
return
SDS_OK
;
}
/*
* Write to the field in the structure corresponding to `structure_id`.
* `fld_off` is the offset to the field in the structure and `mode`
* indicates whether cache maintenance need to performed for the write.
* The `data` is the pointer to data of size specified by `size`.
* Returns SDS_OK on success or corresponding error codes on failure.
*/
int
sds_struct_write
(
uint32_t
structure_id
,
unsigned
int
fld_off
,
void
*
data
,
size_t
size
,
sds_access_mode_t
mode
)
{
int
status
;
uintptr_t
field_base
;
struct_header_t
*
header
=
NULL
;
if
(
!
data
)
return
SDS_ERR_INVALID_PARAMS
;
/* Check if a structure with this ID exists */
status
=
get_struct_header
(
structure_id
,
&
header
);
if
(
status
!=
SDS_OK
)
return
status
;
assert
(
header
);
if
(
mode
==
SDS_ACCESS_MODE_CACHED
)
inv_dcache_range
((
uintptr_t
)
header
,
SDS_HEADER_SIZE
+
size
);
if
(
!
IS_SDS_HEADER_VALID
(
header
))
{
WARN
(
"SDS: Writing to un-finalized structure 0x%x
\n
"
,
structure_id
);
return
SDS_ERR_STRUCT_NOT_FINALIZED
;
}
if
((
fld_off
+
size
)
>
GET_SDS_HEADER_STRUCT_SIZE
(
header
))
return
SDS_ERR_FAIL
;
field_base
=
(
uintptr_t
)
header
+
SDS_HEADER_SIZE
+
fld_off
;
if
(
check_uptr_overflow
(
field_base
,
size
-
1
))
return
SDS_ERR_FAIL
;
/* Copy the required field in the struct */
memcpy
((
void
*
)
field_base
,
data
,
size
);
if
(
mode
==
SDS_ACCESS_MODE_CACHED
)
flush_dcache_range
((
uintptr_t
)
field_base
,
size
);
return
SDS_OK
;
}
/*
* Initialize the SDS driver. Also verifies the SDS version and sanity of
* the SDS structure headers.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
int
sds_init
(
void
)
{
sds_mem_base
=
(
uintptr_t
)
PLAT_ARM_SDS_MEM_BASE
;
if
(
!
IS_SDS_REGION_VALID
(
sds_mem_base
))
{
WARN
(
"SDS: No valid SDS Memory Region found
\n
"
);
return
SDS_ERR_FAIL
;
}
if
(
GET_SDS_REGION_SCHEMA_VERSION
(
sds_mem_base
)
!=
SDS_REGION_SCH_VERSION
)
{
WARN
(
"SDS: Unsupported SDS schema version
\n
"
);
return
SDS_ERR_FAIL
;
}
sds_mem_size
=
GET_SDS_REGION_SIZE
(
sds_mem_base
);
if
(
sds_mem_size
>
PLAT_ARM_SDS_MEM_SIZE_MAX
)
{
WARN
(
"SDS: SDS Memory Region exceeds size limit
\n
"
);
return
SDS_ERR_FAIL
;
}
INFO
(
"SDS: Detected SDS Memory Region (%zu bytes)
\n
"
,
sds_mem_size
);
if
(
validate_sds_struct_headers
()
!=
SDS_OK
)
return
SDS_ERR_FAIL
;
return
SDS_OK
;
}
plat/arm/css/drivers/sds/sds.h
0 → 100644
View file @
487c869d
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SDS_H__
#define __SDS_H__
/* SDS Structure Identifier defines */
/* AP CPU INFO defines */
#define SDS_AP_CPU_INFO_STRUCT_ID 1
#define SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET 0x0
#define SDS_AP_CPU_INFO_PRIMARY_CPUID_SIZE 0x4
/* ROM Firmware Version defines */
#define SDS_ROM_VERSION_STRUCT_ID 2
#define SDS_ROM_VERSION_OFFSET 0x0
#define SDS_ROM_VERSION_SIZE 0x4
/* RAM Firmware version defines */
#define SDS_RAM_VERSION_STRUCT_ID 3
#define SDS_RAM_VERSION_OFFSET 0x0
#define SDS_RAM_VERSION_SIZE 0x4
/* Platform Identity defines */
#define SDS_PLATFORM_IDENTITY_STRUCT_ID 4
#define SDS_PLATFORM_IDENTITY_ID_OFFSET 0x0
#define SDS_PLATFORM_IDENTITY_ID_SIZE 0x4
#define SDS_PLATFORM_IDENTITY_ID_CONFIG_SHIFT 28
#define SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH 4
#define SDS_PLATFORM_IDENTITY_ID_CONFIG_MASK \
((1 << SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH) - 1)
#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_OFFSET 0x4
#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_SIZE 0x4
/* Reset Syndrome defines */
#define SDS_RESET_SYNDROME_STRUCT_ID 5
#define SDS_RESET_SYNDROME_OFFSET 0
#define SDS_RESET_SYNDROME_SIZE 4
#define SDS_RESET_SYNDROME_POW_ON_RESET_BIT (1 << 0)
#define SDS_RESET_SYNDROME_SCP_WD_RESET_BIT (1 << 1)
#define SDS_RESET_SYNDROME_AP_WD_RESET_BIT (1 << 2)
#define SDS_RESET_SYNDROME_SYS_RESET_REQ_BIT (1 << 3)
#define SDS_RESET_SYNDROME_M3_LOCKUP_BIT (1 << 4)
/* SCP Firmware Feature Availability defines */
#define SDS_FEATURE_AVAIL_STRUCT_ID 6
#define SDS_FEATURE_AVAIL_OFFSET 0
#define SDS_FEATURE_AVAIL_SIZE 4
#define SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT (1 << 0)
#define SDS_FEATURE_AVAIL_DMC_READY_BIT (1 << 1)
#define SDS_FEATURE_AVAIL_MSG_IF_READY_BIT (1 << 2)
/* SCP BL2 Image Metadata defines */
#define SDS_SCP_IMG_STRUCT_ID 9
#define SDS_SCP_IMG_FLAG_OFFSET 0
#define SDS_SCP_IMG_FLAG_SIZE 4
#define SDS_SCP_IMG_VALID_FLAG_BIT (1 << 0)
#define SDS_SCP_IMG_ADDR_OFFSET 4
#define SDS_SCP_IMG_ADDR_SIZE 4
#define SDS_SCP_IMG_SIZE_OFFSET 8
#define SDS_SCP_IMG_SIZE_SIZE 4
/* SDS Driver Error Codes */
#define SDS_OK 0
#define SDS_ERR_FAIL -1
#define SDS_ERR_INVALID_PARAMS -2
#define SDS_ERR_STRUCT_NOT_FOUND -3
#define SDS_ERR_STRUCT_NOT_FINALIZED -4
#ifndef __ASSEMBLY__
#include <stddef.h>
#include <stdint.h>
typedef
enum
{
SDS_ACCESS_MODE_NON_CACHED
,
SDS_ACCESS_MODE_CACHED
,
}
sds_access_mode_t
;
int
sds_init
(
void
);
int
sds_struct_exists
(
uint32_t
structure_id
);
int
sds_struct_read
(
uint32_t
structure_id
,
unsigned
int
fld_off
,
void
*
data
,
size_t
size
,
sds_access_mode_t
mode
);
int
sds_struct_write
(
uint32_t
structure_id
,
unsigned
int
fld_off
,
void
*
data
,
size_t
size
,
sds_access_mode_t
mode
);
#endif
/*__ASSEMBLY__ */
#endif
/* __SDS_H__ */
plat/arm/css/drivers/sds/sds_private.h
0 → 100644
View file @
487c869d
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SDS_PRIVATE_H__
#define __SDS_PRIVATE_H__
/* SDS Header defines */
#define SDS_HEADER_ID_SHIFT 0
#define SDS_HEADER_ID_WIDTH 16
#define SDS_HEADER_ID_MASK ((1 << SDS_HEADER_ID_WIDTH) - 1)
#define SDS_HEADER_MINOR_VERSION_WIDTH 8
#define SDS_HEADER_MINOR_VERSION_SHIFT 16
#define SDS_HEADER_MAJOR_VERSION_WIDTH 8
#define MAKE_SDS_HEADER_VERSION(major, minor) \
(((((major) & 0xff) << SDS_HEADER_MINOR_VERSION_WIDTH) | ((minor) & 0xff)))
#define SDS_HEADER_VERSION_MASK \
((1 << (SDS_HEADER_MINOR_VERSION_WIDTH + SDS_HEADER_MAJOR_VERSION_WIDTH)) - 1)
#define SDS_HEADER_VERSION MAKE_SDS_HEADER_VERSION(1, 0)
#define SDS_HEADER_STRUCT_SIZE_WIDTH 23
#define SDS_HEADER_STRUCT_SIZE_SHIFT 1
#define SDS_HEADER_STRUCT_SIZE_MASK ((1 << SDS_HEADER_STRUCT_SIZE_WIDTH) - 1)
#define SDS_HEADER_VALID_MASK 0x1
#define SDS_HEADER_VALID_SHIFT 0
#define SDS_HEADER_SIZE 0x8
/* Arbitrary, 16 bit value that indicates a valid SDS Memory Region */
#define SDS_REGION_SIGNATURE 0xAA7A
#define SDS_REGION_SIGNATURE_WIDTH 16
#define SDS_REGION_SIGNATURE_SHIFT 0
#define SDS_REGION_SIGNATURE_MASK ((1 << SDS_REGION_SIGNATURE_WIDTH) - 1)
#define SDS_REGION_STRUCT_COUNT_SHIFT 16
#define SDS_REGION_STRUCT_COUNT_WIDTH 8
#define SDS_REGION_STRUCT_COUNT_MASK ((1 << SDS_REGION_STRUCT_COUNT_WIDTH) - 1)
#define SDS_REGION_SCH_MINOR_SHIFT 24
#define SDS_REGION_SCH_MINOR_WIDTH 4
#define SDS_REGION_SCH_MINOR_MASK ((1 << SDS_REGION_SCH_MINOR_WIDTH) - 1)
#define SDS_REGION_SCH_MAJOR_SHIFT 28
#define SDS_REGION_SCH_MAJOR_WIDTH 4
#define SDS_REGION_SCH_MAJOR_MASK ((1 << SDS_REGION_SCH_MAJOR_WIDTH) - 1)
#define SDS_REGION_SCH_VERSION_MASK \
((1 << (SDS_REGION_SCH_MINOR_WIDTH + SDS_REGION_SCH_MAJOR_WIDTH)) - 1)
#define MAKE_SDS_REGION_SCH_VERSION(maj, min) \
((((maj) & SDS_REGION_SCH_MAJOR_MASK) << SDS_REGION_SCH_MINOR_WIDTH) | \
((min) & SDS_REGION_SCH_MINOR_MASK))
#define SDS_REGION_SCH_VERSION MAKE_SDS_REGION_SCH_VERSION(1, 0)
#define SDS_REGION_REGIONSIZE_OFFSET 0x4
#define SDS_REGION_DESC_SIZE 0x8
#ifndef __ASSEMBLY__
#include <stddef.h>
#include <stdint.h>
/* Header containing Shared Data Structure metadata */
typedef
struct
structure_header
{
uint32_t
reg
[
2
];
}
struct_header_t
;
#define GET_SDS_HEADER_ID(header) \
((((struct_header_t *)(header))->reg[0]) & SDS_HEADER_ID_MASK)
#define GET_SDS_HEADER_VERSION(header) \
(((((struct_header_t *)(header))->reg[0]) >> SDS_HEADER_MINOR_VERSION_SHIFT)\
& SDS_HEADER_VERSION_MASK)
#define GET_SDS_HEADER_STRUCT_SIZE(header) \
(((((struct_header_t *)(header))->reg[1]) >> SDS_HEADER_STRUCT_SIZE_SHIFT)\
& SDS_HEADER_STRUCT_SIZE_MASK)
#define IS_SDS_HEADER_VALID(header) \
((((struct_header_t *)(header))->reg[1]) & SDS_HEADER_VALID_MASK)
#define GET_SDS_STRUCT_FIELD(header, field_offset) \
((((uint8_t *)(header)) + sizeof(struct_header_t)) + (field_offset))
/* Region Descriptor describing the SDS Memory Region */
typedef
struct
region_descriptor
{
uint32_t
reg
[
2
];
}
region_desc_t
;
#define IS_SDS_REGION_VALID(region) \
(((((region_desc_t *)(region))->reg[0]) & SDS_REGION_SIGNATURE_MASK) == SDS_REGION_SIGNATURE)
#define GET_SDS_REGION_STRUCTURE_COUNT(region) \
(((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_STRUCT_COUNT_SHIFT)\
& SDS_REGION_STRUCT_COUNT_MASK)
#define GET_SDS_REGION_SCHEMA_VERSION(region) \
(((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_SCH_MINOR_SHIFT)\
& SDS_REGION_SCH_VERSION_MASK)
#define GET_SDS_REGION_SIZE(region) ((((region_desc_t *)(region))->reg[1]))
#endif
/* __ASSEMBLY__ */
#endif
/* __SDS_PRIVATE_H__ */
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment