This mostly boils down to initialising the Cache Coherent Interconnect (CCI). We do this by looking in the device-tree for a CCI node, that way the same semihosting bootwrapper binary can be used on both the big.LITTLE models and on the A15 models which don't have a CCI.
Changes sinces v1: - Added in-source comment to configure_from_fdt() - Reworded commit message for patch 2
[PATCH v2 1/3] bootwrapper: Allow for multiple clusters in boot CPU [PATCH v2 2/3] bootwrapper: Factor out parsing of fdt #address-cells [PATCH v2 3/3] bootwrapper: Initialise CCI device if found in the
From: Jon Medhurst tixy@linaro.org
Check all the CPU affinity fields of MPIDR, so we select only the first CPU of the first cluster as the one to boot on.
Signed-off-by: Jon Medhurst tixy@linaro.org --- boot.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/boot.S b/boot.S index 727119a..40ebd33 100644 --- a/boot.S +++ b/boot.S @@ -121,7 +121,7 @@ start:
@ Check CPU nr again mrc p15, 0, r0, c0, c0, 5 @ MPIDR (ARMv7 only) - and r0, r0, #15 @ CPU number + bfc r0, #24, #8 @ CPU number, taking multicluster into account cmp r0, #0 @ primary CPU? beq 2f
On Mon, Oct 08, 2012 at 02:59:17PM +0100, Jon Medhurst (Tixy) wrote:
From: Jon Medhurst tixy@linaro.org
Check all the CPU affinity fields of MPIDR, so we select only the first CPU of the first cluster as the one to boot on.
Shame, we can't run this on pre-v7 CPUs now ;) (Well, v6T2).
The chance of us wanting to do that (motivating bic instead of bfc) is minimal, though.
Acked-by: Dave Martin dave.martin@linaro.org
Signed-off-by: Jon Medhurst tixy@linaro.org
boot.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/boot.S b/boot.S index 727119a..40ebd33 100644 --- a/boot.S +++ b/boot.S @@ -121,7 +121,7 @@ start: @ Check CPU nr again mrc p15, 0, r0, c0, c0, 5 @ MPIDR (ARMv7 only)
- and r0, r0, #15 @ CPU number
- bfc r0, #24, #8 @ CPU number, taking multicluster into account cmp r0, #0 @ primary CPU? beq 2f
1.7.10.4
From: Jon Medhurst tixy@linaro.org
A subsequent patch will also need to obtain address-cells and size-cells, so lets factor out this code into a handy function.
Signed-off-by: Jon Medhurst tixy@linaro.org --- semi_loader.c | 56 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 22 deletions(-)
diff --git a/semi_loader.c b/semi_loader.c index cbe911c..c9750be 100644 --- a/semi_loader.c +++ b/semi_loader.c @@ -97,6 +97,39 @@ static int _fdt_make_node(void *fdt, int parentoffset, const char *name) return fdt_add_subnode(fdt, parentoffset, name); }
+static void _fdt_address_and_size_cells(void *fdt, int* addrcells, int* sizecells) +{ + int e; + uint32_t const *p; + + if(!(p = fdt_getprop(fdt, 0, "#address-cells", &e))) + goto libfdt_error; + else if(e != 4) + goto size_error; + *addrcells = fdt32_to_cpu(*p); + if(!(p = fdt_getprop(fdt, 0, "#size-cells", &e))) + goto libfdt_error; + else if(e != 4) + goto size_error; + *sizecells = fdt32_to_cpu(*p); + + /* + * Sanity-check address sizes, since addresses and sizes which do + * not take up exactly 4 or 8 bytes are not supported. + */ + if ((*addrcells != 1 && *addrcells != 2) || + (*sizecells != 1 && *sizecells != 2)) + goto size_error; + + return; + +libfdt_error: + fatal("libfdt: ", fdt_strerror(e), ", while looking for #address-cells/#size-cells\n"); + +size_error: + fatal("Unexpected/invalid #address-cells/#size-cells in device tree\n"); +} + static void update_fdt(void **dest, struct loader_info *info) { int e; @@ -112,25 +145,7 @@ static void update_fdt(void **dest, struct loader_info *info) if((e = fdt_open_into((void *)info->fdt_start, fdt, FDT_SIZE_MAX)) < 0) goto libfdt_error;
- /* - * Sanity-check address sizes, since addresses and sizes which do - * not take up exactly 4 or 8 bytes are not supported. - */ - { - if(!(p = fdt_getprop(fdt, 0, "#address-cells", &e))) - goto libfdt_error; - else if(e != 4) - goto size_error; - addrcells = fdt32_to_cpu(*p); - if(!(p = fdt_getprop(fdt, 0, "#size-cells", &e))) - goto libfdt_error; - else if(e != 4) - goto size_error; - sizecells = fdt32_to_cpu(*p); - if ((addrcells != 1 && addrcells != 2) || - (sizecells != 1 && sizecells != 2)) - goto size_error; - } + _fdt_address_and_size_cells(fdt, &addrcells, &sizecells);
/* * Add a memory node, but only if there isn't one already. If @@ -225,9 +240,6 @@ no_add_memory: libfdt_error: fatal("libfdt: ", fdt_strerror(e), ", while updating device tree\n"); - -size_error: - fatal("Unexpected/invalid #address-cells/#size-cells in device tree\n"); }
static int is_space(char c)
On Mon, Oct 08, 2012 at 02:59:18PM +0100, Jon Medhurst (Tixy) wrote:
From: Jon Medhurst tixy@linaro.org
A subsequent patch will also need to obtain address-cells and size-cells, so lets factor out this code into a handy function.
The code looks ok. There are a couple of stylistic things that could be tweaked, but it's not a big issue.
Cheers ---Dave
Signed-off-by: Jon Medhurst tixy@linaro.org
semi_loader.c | 56 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 22 deletions(-)
diff --git a/semi_loader.c b/semi_loader.c index cbe911c..c9750be 100644 --- a/semi_loader.c +++ b/semi_loader.c @@ -97,6 +97,39 @@ static int _fdt_make_node(void *fdt, int parentoffset, const char *name) return fdt_add_subnode(fdt, parentoffset, name); } +static void _fdt_address_and_size_cells(void *fdt, int* addrcells, int* sizecells)
Minor quibble: the rest of the code uses the type *decl spacing, not type* decl.
+{
- int e;
- uint32_t const *p;
- if(!(p = fdt_getprop(fdt, 0, "#address-cells", &e)))
goto libfdt_error;
- else if(e != 4)
goto size_error;
Another minor quibble: this could be simplified slightly by dropping any else which directly follows a goto.
(The superfluous elses were in the original code too, though.)
- *addrcells = fdt32_to_cpu(*p);
- if(!(p = fdt_getprop(fdt, 0, "#size-cells", &e)))
goto libfdt_error;
- else if(e != 4)
goto size_error;
- *sizecells = fdt32_to_cpu(*p);
- /*
* Sanity-check address sizes, since addresses and sizes which do
* not take up exactly 4 or 8 bytes are not supported.
*/
- if ((*addrcells != 1 && *addrcells != 2) ||
(*sizecells != 1 && *sizecells != 2))
goto size_error;
- return;
+libfdt_error:
- fatal("libfdt: ", fdt_strerror(e), ", while looking for #address-cells/#size-cells\n");
+size_error:
- fatal("Unexpected/invalid #address-cells/#size-cells in device tree\n");
+}
static void update_fdt(void **dest, struct loader_info *info) { int e; @@ -112,25 +145,7 @@ static void update_fdt(void **dest, struct loader_info *info) if((e = fdt_open_into((void *)info->fdt_start, fdt, FDT_SIZE_MAX)) < 0) goto libfdt_error;
- /*
* Sanity-check address sizes, since addresses and sizes which do
* not take up exactly 4 or 8 bytes are not supported.
*/
- {
if(!(p = fdt_getprop(fdt, 0, "#address-cells", &e)))
goto libfdt_error;
else if(e != 4)
goto size_error;
addrcells = fdt32_to_cpu(*p);
if(!(p = fdt_getprop(fdt, 0, "#size-cells", &e)))
goto libfdt_error;
else if(e != 4)
goto size_error;
sizecells = fdt32_to_cpu(*p);
if ((addrcells != 1 && addrcells != 2) ||
(sizecells != 1 && sizecells != 2))
goto size_error;
- }
- _fdt_address_and_size_cells(fdt, &addrcells, &sizecells);
/* * Add a memory node, but only if there isn't one already. If @@ -225,9 +240,6 @@ no_add_memory: libfdt_error: fatal("libfdt: ", fdt_strerror(e), ", while updating device tree\n");
-size_error:
- fatal("Unexpected/invalid #address-cells/#size-cells in device tree\n");
} static int is_space(char c) -- 1.7.10.4
From: Jon Medhurst tixy@linaro.org
The A15xA7 models simulate a Cache Coherent Interconnect (CCI) and this needs to be initialised correctly for Linux to boot.
To perform this initiation we add the new function configure_from_fdt() which will look in the fdt for devices to initialise. In this first case we look for the CCI node and if found then setup this device.
Signed-off-by: Jon Medhurst tixy@linaro.org --- semi_loader.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/semi_loader.c b/semi_loader.c index c9750be..b0c064c 100644 --- a/semi_loader.c +++ b/semi_loader.c @@ -242,6 +242,61 @@ libfdt_error: fatal("libfdt: ", fdt_strerror(e), ", while updating device tree\n"); }
+/* For accessing 32-bit device ports */ +#define io32(p) (*(volatile uint32_t *)(p)) + +static void init_cci(unsigned cci) +{ + info("Initialising CCI\n"); + + /* + * Ideally, the CCI device tree binding would include suitable + * information so we can correctly configure the CCI, but for + * now we'll just hard-code settings for the present A15xA7 + * models. + */ + + /* Turn on CCI snoops and DVM messages */ + io32(cci+0x4000) = 0x3; /* A15 cluster */ + io32(cci+0x5000) = 0x3; /* A7 cluster */ + + /* Wait while change pending bit of status register is set */ + while(io32(cci+0xc) & 0x1) + {} +} + +static void configure_from_fdt(struct loader_info *info) +{ + void *fdt = (void *)info->fdt_start; + uint32_t const *p; + int addrcells, sizecells; + int offset, len; + + if(!fdt) + return; + + _fdt_address_and_size_cells(fdt, &addrcells, &sizecells); + + /* See if there is a CCI device to initialise */ + offset = fdt_node_offset_by_compatible(fdt, 0, "arm,cci"); + if (offset >= 0) { + p = fdt_getprop(fdt, offset, "reg", &len); + if(len != (addrcells + sizecells) * 4) + info("Failed parsing device-tree node for CCI\n"); + else { + /* + * p[addrcells - 1] is the least significant 32-bits of + * the address for the CCI. On 32-bit CPUs any additional + * address bits had better be zero otherwise we can't + * access it as we don't enable the MMU. + */ + init_cci(fdt32_to_cpu(p[addrcells - 1])); + } + } + + return; +} + static int is_space(char c) { return c == ' '; @@ -598,4 +653,6 @@ args_done: atag_append(&atagp, ATAG_NONE, 0, 0);
update_fdt(&phys, info); + + configure_from_fdt(info); }
On Mon, Oct 08, 2012 at 02:59:19PM +0100, Jon Medhurst (Tixy) wrote:
From: Jon Medhurst tixy@linaro.org
The A15xA7 models simulate a Cache Coherent Interconnect (CCI) and this needs to be initialised correctly for Linux to boot.
To perform this initiation we add the new function configure_from_fdt() which will look in the fdt for devices to initialise. In this first case we look for the CCI node and if found then setup this device.
Acked-by: Dave Martin dave.martin@linaro.org
(Commentary below, but the patch looks OK to me.)
Signed-off-by: Jon Medhurst tixy@linaro.org
semi_loader.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/semi_loader.c b/semi_loader.c index c9750be..b0c064c 100644 --- a/semi_loader.c +++ b/semi_loader.c @@ -242,6 +242,61 @@ libfdt_error: fatal("libfdt: ", fdt_strerror(e), ", while updating device tree\n"); } +/* For accessing 32-bit device ports */ +#define io32(p) (*(volatile uint32_t *)(p))
I had a vague memory of something like this already existing somewhere, but I think I may be confusing this with another codebase.
+static void init_cci(unsigned cci) +{
- info("Initialising CCI\n");
- /*
* Ideally, the CCI device tree binding would include suitable
* information so we can correctly configure the CCI, but for
* now we'll just hard-code settings for the present A15xA7
* models.
*/
- /* Turn on CCI snoops and DVM messages */
- io32(cci+0x4000) = 0x3; /* A15 cluster */
- io32(cci+0x5000) = 0x3; /* A7 cluster */
We may want to be more sophisticated about this at some point, but this is a sensible compromise for now.
There is no official CCI binding yet, but this code makes reasonable- looking, minimal assumptions about its final form.
- /* Wait while change pending bit of status register is set */
- while(io32(cci+0xc) & 0x1)
{}
+}
+static void configure_from_fdt(struct loader_info *info) +{
- void *fdt = (void *)info->fdt_start;
- uint32_t const *p;
- int addrcells, sizecells;
- int offset, len;
- if(!fdt)
return;
- _fdt_address_and_size_cells(fdt, &addrcells, &sizecells);
- /* See if there is a CCI device to initialise */
- offset = fdt_node_offset_by_compatible(fdt, 0, "arm,cci");
- if (offset >= 0) {
p = fdt_getprop(fdt, offset, "reg", &len);
if(len != (addrcells + sizecells) * 4)
info("Failed parsing device-tree node for CCI\n");
else {
/*
* p[addrcells - 1] is the least significant 32-bits of
* the address for the CCI. On 32-bit CPUs any additional
* address bits had better be zero otherwise we can't
* access it as we don't enable the MMU.
*/
init_cci(fdt32_to_cpu(p[addrcells - 1]));
}
- }
- return;
+}
static int is_space(char c) { return c == ' '; @@ -598,4 +653,6 @@ args_done: atag_append(&atagp, ATAG_NONE, 0, 0); update_fdt(&phys, info);
- configure_from_fdt(info);
}
1.7.10.4
On 8 October 2012 14:59, Jon Medhurst (Tixy) tixy@linaro.org wrote:
This mostly boils down to initialising the Cache Coherent Interconnect (CCI). We do this by looking in the device-tree for a CCI node, that way the same semihosting bootwrapper binary can be used on both the big.LITTLE models and on the A15 models which don't have a CCI.
Changes sinces v1:
- Added in-source comment to configure_from_fdt()
- Reworded commit message for patch 2
[PATCH v2 1/3] bootwrapper: Allow for multiple clusters in boot CPU [PATCH v2 2/3] bootwrapper: Factor out parsing of fdt #address-cells [PATCH v2 3/3] bootwrapper: Initialise CCI device if found in the
All: Reviewed-by: Peter Maydell peter.maydell@linaro.org and tested that the KVM boot is still OK.
Patch 2 made git complain about trailing whitespace in one place but I'll just zap that in passing when I apply these.
Dave, unless you have any further review comments I propose to apply these Wednesday.
thanks -- PMM
On Tue, Oct 09, 2012 at 01:31:55PM +0100, Peter Maydell wrote:
On 8 October 2012 14:59, Jon Medhurst (Tixy) tixy@linaro.org wrote:
This mostly boils down to initialising the Cache Coherent Interconnect (CCI). We do this by looking in the device-tree for a CCI node, that way the same semihosting bootwrapper binary can be used on both the big.LITTLE models and on the A15 models which don't have a CCI.
Changes sinces v1:
- Added in-source comment to configure_from_fdt()
- Reworded commit message for patch 2
[PATCH v2 1/3] bootwrapper: Allow for multiple clusters in boot CPU [PATCH v2 2/3] bootwrapper: Factor out parsing of fdt #address-cells [PATCH v2 3/3] bootwrapper: Initialise CCI device if found in the
All: Reviewed-by: Peter Maydell peter.maydell@linaro.org and tested that the KVM boot is still OK.
Patch 2 made git complain about trailing whitespace in one place but I'll just zap that in passing when I apply these.
Thanks
Dave, unless you have any further review comments I propose to apply these Wednesday.
Apart from a couple of minor stylistic quibbles, the look good to me. Those aren't critical, but could be tweaked if you get a moment.
Cheers ---Dave
On 9 October 2012 14:06, Dave Martin dave.martin@linaro.org wrote:
On Tue, Oct 09, 2012 at 01:31:55PM +0100, Peter Maydell wrote:
Patch 2 made git complain about trailing whitespace in one place but I'll just zap that in passing when I apply these.
Thanks
Dave, unless you have any further review comments I propose to apply these Wednesday.
Apart from a couple of minor stylistic quibbles, the look good to me. Those aren't critical, but could be tweaked if you get a moment.
I've fixed the style quibbles and pushed the patches to master now.
-- PMM