After spending several hours studying the 930 page GICv3 manual, I decided to take a look at some driver code. A likely source would be the ATF (Arm trusted firmware) sources. Indeed, when I build this for the RK3399, I see this in the build log:
CC drivers/arm/cci/cci.c CC drivers/arm/gic/v3/arm_gicv3_common.c CC drivers/arm/gic/v3/gic-x00.c CC drivers/arm/gic/v3/gicdv3_helpers.c CC drivers/arm/gic/v3/gicrv3_helpers.c CC drivers/arm/gic/v3/gicv3_helpers.c CC drivers/arm/gic/v3/gicv3_main.cThe file "cci.c" may or may not be relevant.
After spending some time looking at this code, I had another idea. Why not extract the GICv3 driver from the ATF source tree and press it into service for my project? There is nothing sneaky or illegitemate about this -- this is what open source is all about, and I don't intend to misrepresent it as anything I wrote myself. Working with actual driver code will be at least as educational as studying the GIC document and will complement it nicely.
My own education is at least as important as getting things to work.
Of course, we almost immediately get into the need to drag in header files. It remains to be seen if header files in turn pull in more header files. It is useful to run the command "ls -lR >zzz" and have a file to search to find out where dependency files are located.
I begin with gicv3_main.c and keep pulling in header files until I get it to compile. We get into some difficult decisions almost right away.
We encounter things like the following. Do we create a multitude of subdirectories or edit the sources to get all include files from the current directory? We decide to edit the sources.
#includeIn debug.h, something more interesting comes up:
#includeAt first I was terrified thinking that the ATF build was referencing system include files, but I find this in "include/lib/libc". I am however starting to worry about a clutter of include files building up and obscuring the gic specific files when I run ls. I decide to go ahead and create an "include" directory and shove them all in there, modifying my fetch script accordingly. I will also need a -I./include line in my Makefile.
Another issue pops up. I notice that I am getting no complaints about files including stdint.h, and I have yet to copy that from the ATF sources. Now I see this error:
unknown type name ‘u_register_t’And indeed this is defined in ATF/include/lib/libc/stdint.h -- so we want that, not the standard system stdint.h that the compiler is finding somewhere.
Without a doubt, I will be able to prune away a lot of these files, but that will be a different sort of work from the mindless copying I have been doing.
I now get these errors as it tries to compile gicv3_main.c:
error: ‘NR_OF_IMAGES_IN_FW_BANK’ undeclared here (not in a function); did you mean ‘NR_OF_MAX_FW_BANKS’? error: ‘NR_OF_FW_BANKS’ undeclared here (not in a function); did you mean ‘NR_OF_MAX_FW_BANKS’? 47 | struct fwu_image_bank_info img_bank_info[NR_OF_FW_BANKS];On one hand, I have to wonder what went wrong that something is missing from the set of include files I copied. On the other hand, I wonder what a "FWU" is and if it matters at all to a GIC driver.
I do a recursive grep and find that these thinks seem to be defined dynamically in several Makefiles. The file docs/getting_started/build-options.rst talks about these macros, and says:
- ``NR_OF_FW_BANKS``: Define the number of firmware banks. This flag is used in defining the firmware update metadata structure. This flag is by default set to '2'. - ``NR_OF_IMAGES_IN_FW_BANK``: Define the number of firmware images in each firmware bank. Each firmware bank must have the same number of images as per the `PSA FW update specification`_. This flag is used in defining the firmware update metadata structure. This flag is by default set to '1'.The file that is looking for these values is fwu_metadata.h and the quick and easy thing to do (for now) is to add these lines to that file:
/* TJT */ #define NR_OF_FW_BANKS 2 #define NR_OF_IMAGES_IN_FW_BANK 1I add my initials, as shown, so I can track down any such edits I make, this one and any that arise in the future.
gic_common.h sysreg128.hI would be worth examing these in detail at some point and giving some thought. Knowing the include search path being used by gcc would resolve this, along perhaps with a careful examination of the locations where these files are included in case I made a mistake in my directory flattening.
Most of them are in other gic related C files. The list is:
$ATF/drivers/arm/gic/v3/gicv3_main.c $ATF/drivers/arm/gic/v3/arm_gicv3_common.c $ATF/drivers/arm/gic/v3/gic-x00.c $ATF/drivers/arm/gic/v3/gicdv3_helpers.c $ATF/drivers/arm/gic/v3/gicrv3_helpers.c $ATF/drivers/arm/gic/v3/gicv3_helpers.cThe other missing references are interesting in their own right, if not directly related to the GIC driver.
It turns out these come from a macro named panic() in debug.h. What I am going to do is to add a routine "gic_panic()" to my gic_compat.c. Then I'll change the panic() macros in debug.h to call this routine and things we be good. Or at least in my control.
func plat_my_core_pos
mrs x0, mpidr_el1
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
add x0, x1, x0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
ret
endfunc plat_my_core_pos
The file is only 179 lines, and is quite interesting,
but makes calls to a variety of other routines and pulls
in its own collection of include files.
We just need to track down the MASK and SHIFT values and we can add just this routine to our own assembly startup file.
Here are the header files it pulls in:
#includeThe file arch.h (include/arch/aarch64/arch.h) has the first two#include #include #include #include #include #include #include
#define MPIDR_AFFINITY_BITS U(8) #define MPIDR_AFFLVL_MASK ULL(0xff) #define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK #define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS)We find PLAT_RK_CLST_TO_CPUID_SHIFT in plat/rockchip/rk3399/include/platform_def.h
#define PLAT_RK_CLST_TO_CPUID_SHIFT 6I put together a file "my_core.S" and we see to be OK.
The code is in lib/aarch64/cache_helpers.S
Consider though that this is not just about the gicv3 driver. There is a lot of high quality ARM code here that is worth looking at. This is also a good introduction to the ATF source tree, which has been one of my goals for some time.
The next step is to study this enough to make calls to it and get it to handle interrupts for me. Once I have working code with source that I know my way around in, I will be in a much better position to study the GIC document.
Tom's electronics pages / tom@mmto.org