-
Notifications
You must be signed in to change notification settings - Fork 422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework uart0-helloworld-sdboot to use SoC table #211
Open
apritzel
wants to merge
11
commits into
linux-sunxi:master
Choose a base branch
from
apritzel:uart0-soc-table
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The SRAM controller's version register, which we use to identify a SoC, is mapped at different locations in the different SoC generations. To find the right MMIO address, we try to read some GICD_IIDR register, which tells us which SoC generation we are dealing with. Looking forward, this will need to be more flexible, as the A80 and A523 will not work with this scheme anymore: the A80 uses a completely different memory map, and the A523 has a GICv3. Rework the generation detection to be more flexible and easier to extend: - First read the MIDR, and check for a Cortex-A8 core. This is the early generation of SoCs (A10/A10s/A13), which don't have a GIC at all. Use the legacy SRAM controller address in this case. - Next check the address of the GIC in the H6 generation ("NCAT"). Its base address is unmapped at all the other SoCs tested, so this is safe. - Finally check the GIC address of the "legacy" generation of SoCs (A20-A64). - If nothing matches, we are dealing with an unknown SoC, and must stop. The A80 detection was a nice idea, but didn't work, since the boot cluster is the one with the A7 cores, so the boot CPU looks like all the other 32-bit SoCs. Remove that, as the A80 is not supported anyways. Signed-off-by: Andre Przywara <[email protected]>
At the moment the various SoC specific settings are scattered throughout the file, using mostly chains of "soc_is_xxx()" macros. While this might have initially worked with just a few SoCs supported, this is becoming more and more messy with our currently 22 supported SoCs. Also it is not easy to support new SoCs, and it looks like some SoCs are already broken (for instance the A80 is missing the GPIO setup). The make the code more readable and allow easier addition of future SoCs, let's add a table, where each entry holds all the various information we will need to know for each chip: the UART base address, the clock base address, the clock type, etc. This is conceptually similar to what sunxi-fel does in soc_info.c. To make review easier and avoid any regressions, add the table member by member, and convert the various "subsystems" over one by one. We start with the most simple table containing the SoC ID and the SoC name (as a string), and use that already when printing the SoC name. Since some SoCs share the same SoC ID, add a "flags" member and a in there a variants bit, and set this accordingly for the four SoCs that need it. The soc_detection_init() function gets re-written (and renamed), to return a pointer into the table, so that the other functions can use the information there directly. Signed-off-by: Andre Przywara <[email protected]>
While the actual UART IP has always been the same across all Allwinner SoC generations so far, the base address changed a few times recently. Add a field to the SoC to hold that UART0 base address, and fill the value in for each SoC. This is then used in the uart0_init() function, so we can remove the explicit setting in the bases_init() function. Signed-off-by: Andre Przywara <[email protected]>
To make the UART work, we have to open the clock gate and de-assert the reset for the UART0 peripheral. This is currently done by calling one of four functions, even though there are actually only two different ways: - Older SoCs need to set a bit in the APB1/2 bus clock register, and the same bit in the respective reset register. - Newer SoCs combines both the clock and the reset gate in one register, so it's only one write, setting two bits. Add a flag to the table to choose between the two methods for each SoC. The offsets for these clock registers are very stable, but the CCU base address changed a bit over time, so split this up and put the base address separately into the table. For the latest SoCs, the "new" clock structure is combined with an updated GPIO IP, and the Allwinner BSP calls this SoC generation "NCAT2". Add a symbolic name for this already, so we can mark those SoCs now, and add the respective GPIO flag later when this gets added. Signed-off-by: Andre Przywara <[email protected]>
To make the UART signal appear on the SoC pins, we have to select two pins from the supported output pins and set up their pinmux to connect to the UART peripheral. As the name suggests, uart0-helloworld-sdboot always uses UART0, which is used as a debug UART on most boards, and is also available as a multiplex on the SD card pins, to be used with a breakout board. At the moment there is a large if/else cascade, with each branch calling three GPIO setup functions, with the right arguments for each SoC. While this is easily extendable with copy&paste, it is very repetetive and duplicates quite some code. Use our new SoC table to put the pin number for the TX pin and the required pinmux value in there, alongside the PIO base address. The RX pin is so far always the pin after the TX pin, so we just need to store one pin. We also store a flag marking the PIO IP generation for each SoC, so we can just differentiate this easily in the GPIO setup functions. This also uses the opportunity to get rid of the idea to assign some names to the pinmux values, when they are just seemingly random SoC specific numbers. Instead just use a macro name with that number in it, to make it obvious that this is the mux value, but don't try to put some deeper meaning into them. On one SoC we decided to use the SD card pinmux, which is always on pins PF2 and PF4. Add a flag to allow a SoC to default to those pins. Also remove the unneeded GPIO functions, and mark the rest of them as static. Signed-off-by: Andre Przywara <[email protected]>
After we have printed our greeting message, the code tries to figure out from which media the devices has been booted, and prints that information. When we were booted via FEL, we return there, so further code can be uploaded. To access this boot source information, we need to read from offset 0x28 of SRAM A1. The SRAM base address is different between the SoC generations, so add this address to the table and use it directly. Signed-off-by: Andre Przywara <[email protected]>
Now that every SoC specific aspect of our tool is covered by the SoC table, we don't need the old macros testing for each SoC anymore. Remove them alongside the no longer needed versions to differentiate the few SoC variants, which are already covered by a flag in the table. Signed-off-by: Andre Przywara <[email protected]>
Our uart0-helloworld-sdboot tools lives in a single source file, so we don't need to export any functions we use. Nevertheless most functions were in the past not marked as "static". Mark the one function that hasn't been touched and updated in the last few patches as "static", to avoid the compiler exporting them, and to help it with inlining functions. Signed-off-by: Andre Przywara <[email protected]>
The Allwinner A523 is an SoC with eight Arm Cortex-A55 cores, and some updated peripherals. The basic IP is very close to other recent SoCs, so we just have to add the respective flags and base addresses to the new SoC table, to allow boards with this SoC to run uart0-helloworld-sdboot. The A523 comes with a GICv3, at a different address, so add this to the early generation detection code, and let it use the H6 SRAM controller address for further SoC-ID detection. Tested on an Avaota A1 board. Signed-off-by: Andre Przywara <[email protected]>
The Allwinner A83T is an older SoC, with eight Arm Cortex-A7 cores, but otherwise being very similar to the "classic" SoCs like the A20. Add support for this SoC, by simply adding its SoC ID and the respective SoC data into our SoC table. Tested on a Cubietruck Plus. Signed-off-by: Andre Przywara <[email protected]>
The Allwinner A80 is quite an oddball: it uses a big.LITTLE configuration with Arm Cortex-A7 and A15 cores, and has a completely different memory map compared to all the other Allwinner SoCs. Add support for this SoC, by adding the respective base addresses for its peripherals and the pinmux into our SoC table. It also requires a small extension to the SoC detection routine, to accommodate for the different GIC mapping. Tested on an Cubieboard 4 (CC-A80). Signed-off-by: Andre Przywara <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Over time the seemingly simple uart0-helloworld-sdboot program became a bit of a mess: new SoCs tend to mix and match various properties, and people adding support for them needed to find the right group to put them into. This lead to long
if (soc_is_xxx() || soc_is_yyy() ...)
chains, which are not only hardly readable, but made any changes quite error-prone.This series reworks the whole design, by adding a SoC table (inspired by soc_info.c), where we hold various values for each SoC: among the SoC ID and its name things like the UART base address, the clock base, and the UART0 pins.
This not only simplifies the whole code, but makes adding support for new SoCs a breeze: as a bonus the last three patches add support for the A83T, the A80 and the A523. And even though this table takes about 1KB of RAM (for all the 23 supported SoCs), the whole binary got actually much smaller:
Please review, I split the patches up to help with that process.