Merge remote-tracking branch 'upstream/master' into system76_cleanup
This commit is contained in:
2
3rdparty/blobs
vendored
2
3rdparty/blobs
vendored
Submodule 3rdparty/blobs updated: d7600dd871...62aa0e0c54
2
3rdparty/libgfxinit
vendored
2
3rdparty/libgfxinit
vendored
Submodule 3rdparty/libgfxinit updated: b3b9fa34bb...a815704c84
2
3rdparty/opensbi
vendored
2
3rdparty/opensbi
vendored
Submodule 3rdparty/opensbi updated: 804b997ed4...ce228ee091
2
3rdparty/vboot
vendored
2
3rdparty/vboot
vendored
Submodule 3rdparty/vboot updated: dac763c782...9c90611097
14
AUTHORS
Normal file
14
AUTHORS
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# This is the list of coreboot authors for copyright purposes.
|
||||||
|
#
|
||||||
|
# This does not necessarily list everyone who has contributed code, since in
|
||||||
|
# some cases, their employer may be the copyright holder. To see the full list
|
||||||
|
# of contributors, see the revision history in source control.
|
||||||
|
# git log --pretty=format:%an | sort | uniq
|
||||||
|
#
|
||||||
|
|
||||||
|
Alexander Couzens
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Directories transferred
|
||||||
|
src/acpi
|
@@ -148,7 +148,6 @@ mv build/coreboot.rom.new build/coreboot.rom
|
|||||||
<li>Edit the src/soc/<Vendor>/<Chip Family>/memmap.c file
|
<li>Edit the src/soc/<Vendor>/<Chip Family>/memmap.c file
|
||||||
<ol type="A">
|
<ol type="A">
|
||||||
<li>Add the fsp/memmap.h include file</li>
|
<li>Add the fsp/memmap.h include file</li>
|
||||||
<li>Add the mmap_region_granularity routine</li>
|
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li>Add the necessary .h files to define the necessary values and structures</li>
|
<li>Add the necessary .h files to define the necessary values and structures</li>
|
||||||
|
@@ -23,8 +23,20 @@ On entry to a stage or payload (including SELF payloads),
|
|||||||
## Additional payload handoff requirements
|
## Additional payload handoff requirements
|
||||||
The location of cbmem should be placed in a node in the FDT.
|
The location of cbmem should be placed in a node in the FDT.
|
||||||
|
|
||||||
|
## OpenSBI
|
||||||
|
In case the payload doesn't install it's own SBI, like the [RISCV-PK] does,
|
||||||
|
[OpenSBI] can be used instead.
|
||||||
|
It's loaded into RAM after coreboot has finished loading the payload.
|
||||||
|
coreboot then will jump to OpenSBI providing a pointer to the real payload,
|
||||||
|
which OpenSBI will jump to once the SBI is installed.
|
||||||
|
|
||||||
|
Besides providing SBI it also sets protected memory regions and provides
|
||||||
|
a platform independent console.
|
||||||
|
|
||||||
|
The OpenSBI code is always run in M mode.
|
||||||
|
|
||||||
## Trap delegation
|
## Trap delegation
|
||||||
Traps are delegated in the ramstage.
|
Traps are delegated to the payload.
|
||||||
|
|
||||||
## SMP within a stage
|
## SMP within a stage
|
||||||
At the beginning of each stage, all harts save 0 are spinning in a loop on
|
At the beginning of each stage, all harts save 0 are spinning in a loop on
|
||||||
@@ -44,3 +56,6 @@ The hart blocks until fn is non-null, and then calls it. If fn returns, we
|
|||||||
will panic if possible, but behavior is largely undefined.
|
will panic if possible, but behavior is largely undefined.
|
||||||
|
|
||||||
Only hart 0 runs through most of the code in each stage.
|
Only hart 0 runs through most of the code in each stage.
|
||||||
|
|
||||||
|
[RISCV-PK]: https://github.com/riscv/riscv-pk
|
||||||
|
[OpenSBI]: https://github.com/riscv/opensbi
|
||||||
|
@@ -22,19 +22,30 @@ Refrain from insulting anyone or the group they belong to. Remember that
|
|||||||
people might be sensitive to other things than you are.
|
people might be sensitive to other things than you are.
|
||||||
|
|
||||||
Most of our community members are not native English speakers, thus
|
Most of our community members are not native English speakers, thus
|
||||||
misunderstandings can (and do) happen. Always assume that others are
|
misunderstandings can (and do) happen. Assume that others are friendly
|
||||||
friendly and may have picked less-than-stellar wording by accident.
|
and may have picked less-than-stellar wording by accident as long as
|
||||||
|
you possibly can.
|
||||||
|
|
||||||
If you have a grievance due to conduct in this community, we want to hear
|
## Reporting Issues
|
||||||
about it so we can handle the situation. Please contact our arbitration
|
|
||||||
team directly: They will listen to you and react in a timely fashion.
|
If you have a grievance due to conduct in this community, we're sorry
|
||||||
|
that you have had a bad experience, and we want to hear about it so
|
||||||
|
we can resolve the situation.
|
||||||
|
|
||||||
|
Please contact members of our arbitration team (listed below) promptly
|
||||||
|
and directly, in person (if available) or by email: They will listen
|
||||||
|
to you and react in a timely fashion.
|
||||||
|
|
||||||
|
If you feel uncomfortable, please don't wait it out, ask for help,
|
||||||
|
so we can work on setting things right.
|
||||||
|
|
||||||
For transparency there is no alias or private mailing list address for
|
For transparency there is no alias or private mailing list address for
|
||||||
you to reach out to, since we want to make sure that you know who will
|
you to reach out to, since we want to make sure that you know who will
|
||||||
(and who won't) read your message.
|
and who won't read your message.
|
||||||
|
|
||||||
However since people might be on travel or otherwise be unavailable at
|
However since people might be on travel or otherwise be unavailable
|
||||||
times, consider reaching out to multiple persons.
|
at times, please reach out to multiple persons at once, especially
|
||||||
|
when using email.
|
||||||
|
|
||||||
The team will treat your messages confidential as far as the law permits.
|
The team will treat your messages confidential as far as the law permits.
|
||||||
For the purpose of knowing what law applies, the list provides the usual
|
For the purpose of knowing what law applies, the list provides the usual
|
||||||
@@ -73,15 +84,10 @@ immediately.
|
|||||||
If a community member engages in unacceptable behavior, the community
|
If a community member engages in unacceptable behavior, the community
|
||||||
organizers may take any action they deem appropriate, up to and including
|
organizers may take any action they deem appropriate, up to and including
|
||||||
a temporary ban or permanent expulsion from the community without warning
|
a temporary ban or permanent expulsion from the community without warning
|
||||||
(and without refund in the case of a paid event). Community organizers
|
(and without refund in the case of a paid event).
|
||||||
can be part of the arbitration team, or organizers of events and online
|
|
||||||
communities.
|
|
||||||
|
|
||||||
## If You Witness or Are Subject to Unacceptable Behavior
|
|
||||||
|
|
||||||
If you are subject to or witness unacceptable behavior, or have any other
|
|
||||||
concerns, please notify someone from the arbitration team immediately.
|
|
||||||
|
|
||||||
|
Community organizers can be members of the arbitration team, or organizers
|
||||||
|
of events and online communities.
|
||||||
|
|
||||||
## Addressing Grievances
|
## Addressing Grievances
|
||||||
|
|
||||||
@@ -102,7 +108,7 @@ Our arbitration team consists of the following people
|
|||||||
* Stefan Reinauer <stefan.reinauer@coreboot.org> (USA)
|
* Stefan Reinauer <stefan.reinauer@coreboot.org> (USA)
|
||||||
* Patrick Georgi <patrick@coreboot.org> (Germany)
|
* Patrick Georgi <patrick@coreboot.org> (Germany)
|
||||||
* Ronald Minnich <rminnich@coreboot.org> (USA)
|
* Ronald Minnich <rminnich@coreboot.org> (USA)
|
||||||
* Marc Jones <mjones@coreboot.org> (USA)
|
* Martin Roth <martin@coreboot.org> (USA)
|
||||||
|
|
||||||
## License and attribution
|
## License and attribution
|
||||||
|
|
||||||
|
@@ -58,16 +58,6 @@ fixes not found in the stock firmware, and offer much broader OS compatibility
|
|||||||
microcode, as well as firmware updates for the device's embedded controller
|
microcode, as well as firmware updates for the device's embedded controller
|
||||||
(EC). This firmware "takes the training wheels off" your ChromeOS device :)
|
(EC). This firmware "takes the training wheels off" your ChromeOS device :)
|
||||||
|
|
||||||
### John Lewis
|
|
||||||
|
|
||||||
[John Lewis](https://johnlewis.ie/custom-chromebook-firmware) also provides
|
|
||||||
replacement firmware for ChromeOS devices, for the express purpose of
|
|
||||||
running Linux on Chromebooks. John Lewis' firmware supports a much smaller
|
|
||||||
set of devices, and uses SeaBIOS as the payload to support Legacy BIOS booting.
|
|
||||||
His firmware images are significantly older, and not actively maintained or
|
|
||||||
supported, but worth a look if you need Legacy Boot support and is not
|
|
||||||
available via Mr Chromebox's firmware.
|
|
||||||
|
|
||||||
### Heads
|
### Heads
|
||||||
|
|
||||||
[Heads](http://osresearch.net) is an open source custom firmware and OS
|
[Heads](http://osresearch.net) is an open source custom firmware and OS
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Platform indenpendend drivers documentation
|
# Platform independent drivers documentation
|
||||||
|
|
||||||
The drivers can be found in `src/drivers`. They are intended for onboard
|
The drivers can be found in `src/drivers`. They are intended for onboard
|
||||||
and plugin devices, significantly reducing integration complexity and
|
and plugin devices, significantly reducing integration complexity and
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
coreboot lesson 1 - Starting from scratch
|
coreboot Lesson 1: Starting from scratch
|
||||||
=========================================
|
========================================
|
||||||
|
|
||||||
From a fresh Ubuntu 16.04 or 18.04 install, here are all the steps required for
|
From a fresh Ubuntu 16.04 or 18.04 install, here are all the steps required for
|
||||||
a very basic build:
|
a very basic build:
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
## Supported architectures
|
## Supported architectures
|
||||||
|
|
||||||
* aarch64
|
* aarch64
|
||||||
|
* riscv
|
||||||
|
|
||||||
## Supported FIT sections
|
## Supported FIT sections
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ The section must be named in order to be found by the FIT parser:
|
|||||||
## Architecture specifics
|
## Architecture specifics
|
||||||
|
|
||||||
The FIT parser needs architecure support.
|
The FIT parser needs architecure support.
|
||||||
|
|
||||||
### aarch64
|
### aarch64
|
||||||
The source code can be found in `src/arch/arm64/fit_payload.c`.
|
The source code can be found in `src/arch/arm64/fit_payload.c`.
|
||||||
|
|
||||||
@@ -31,6 +33,13 @@ On aarch64 the kernel (a section named 'kernel') must be in **Image**
|
|||||||
format and it needs a devicetree (a section named 'fdt') to boot.
|
format and it needs a devicetree (a section named 'fdt') to boot.
|
||||||
The kernel will be placed close to "*DRAMSTART*".
|
The kernel will be placed close to "*DRAMSTART*".
|
||||||
|
|
||||||
|
### RISC-V
|
||||||
|
The source code can be found in `src/arch/riscv/fit_payload.c`.
|
||||||
|
|
||||||
|
On RISC-V the kernel (a section named 'kernel') must be in **Image**
|
||||||
|
format and it needs a devicetree (a section named 'fdt') to boot.
|
||||||
|
The kernel will be placed close to "*DRAMSTART*".
|
||||||
|
|
||||||
### Other
|
### Other
|
||||||
Other architectures aren't supported.
|
Other architectures aren't supported.
|
||||||
|
|
||||||
|
47
Documentation/mainboard/emulation/qemu-aarch64.md
Normal file
47
Documentation/mainboard/emulation/qemu-aarch64.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# QEMU AArch64 emulator
|
||||||
|
This page discribes how to build and run coreboot for QEMU/AArch64.
|
||||||
|
You can use LinuxBoot via `make menuconfig` or an arbitrary FIT image
|
||||||
|
as a payload for QEMU/AArch64.
|
||||||
|
|
||||||
|
## Running coreboot in QEMU
|
||||||
|
```bash
|
||||||
|
qemu-system-aarch64 -bios ./build/coreboot.rom \
|
||||||
|
-M virt,secure=on,virtualization=on -cpu cortex-a53 \
|
||||||
|
-nographic -m 8912M
|
||||||
|
```
|
||||||
|
|
||||||
|
- The default CPU in QEMU for AArch64 is a cortex-a15 which is 32-bit
|
||||||
|
ARM CPU. You need to specify 64-bit ARM CPU via `-cpu cortex-a53`.
|
||||||
|
- The default privilege level in QEMU for AArch64 is EL1 that we can't
|
||||||
|
have the right to access EL3/EL2 registers. You need to enable EL3/EL2
|
||||||
|
via `-machine secure=on,virtualization=on`.
|
||||||
|
- You need to specify the size of memory more than 544 MiB because 512
|
||||||
|
MiB is reserved for the kernel.
|
||||||
|
|
||||||
|
## Building coreboot with an arbitrary FIT payload
|
||||||
|
There are 3 steps to make coreboot.rom for QEMU/AArch64. If you select
|
||||||
|
LinuxBoot, step 2 and 3 have done by LinuxBoot.
|
||||||
|
1. Get a DTB (Device Tree Blob)
|
||||||
|
2. Build a FIT image with a DTB
|
||||||
|
3. Add a FIT image to coreboot.rom
|
||||||
|
|
||||||
|
### 1. Get a DTB
|
||||||
|
You can get the DTB from QEMU with the following command.
|
||||||
|
```
|
||||||
|
$ qemu-system-aarch64 \
|
||||||
|
-M virt,dumpdtb=virt.dtb,secure=on,virtualization=on \
|
||||||
|
-cpu cortex-a53 -nographic -m 2048M
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Build a FIT image with a DTB
|
||||||
|
You need to write an image source file that has an `.its` extension to
|
||||||
|
configure kernels, ramdisks, and DTBs.
|
||||||
|
See [Flattened uImage Tree documentation](../../lib/payloads/fit.md) for more details.
|
||||||
|
|
||||||
|
### 3. Add a FIT image to coreboot.rom
|
||||||
|
You can use cbfstool to add the payload you created in step 2 to
|
||||||
|
the coreboot.rom.
|
||||||
|
```
|
||||||
|
$ ./build/cbfstool ./build/coreboot.rom add -f <path-to-a-payload>/uImage \
|
||||||
|
-n fallback/payload -t fit -c lzma
|
||||||
|
```
|
@@ -24,6 +24,7 @@ The boards in this section are not real mainboards, but emulators.
|
|||||||
|
|
||||||
- [Spike RISC-V emulator](emulation/spike-riscv.md)
|
- [Spike RISC-V emulator](emulation/spike-riscv.md)
|
||||||
- [Qemu RISC-V emulator](emulation/qemu-riscv.md)
|
- [Qemu RISC-V emulator](emulation/qemu-riscv.md)
|
||||||
|
- [Qemu AArch64 emulator](emulation/qemu-aarch64.md)
|
||||||
|
|
||||||
## Intel
|
## Intel
|
||||||
|
|
||||||
@@ -69,6 +70,10 @@ The boards in this section are not real mainboards, but emulators.
|
|||||||
- [T4xx common](lenovo/t4xx_series.md)
|
- [T4xx common](lenovo/t4xx_series.md)
|
||||||
- [X2xx common](lenovo/x2xx_series.md)
|
- [X2xx common](lenovo/x2xx_series.md)
|
||||||
|
|
||||||
|
## Portwell
|
||||||
|
|
||||||
|
- [PQ7-M107](portwell/pq7-m107.md)
|
||||||
|
|
||||||
### Sandy Bridge series
|
### Sandy Bridge series
|
||||||
|
|
||||||
- [T420](lenovo/t420.md)
|
- [T420](lenovo/t420.md)
|
||||||
|
79
Documentation/mainboard/portwell/pq7-m107.md
Normal file
79
Documentation/mainboard/portwell/pq7-m107.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Portwell PQ7-M107
|
||||||
|
|
||||||
|
This page describes how to run coreboot on the [Portwell PQ7-M107].
|
||||||
|
|
||||||
|
PQ7-M107 are assembled with different onboard memory modules:
|
||||||
|
Rev 1.0 Onboard Samsung K4B8G1646D-MYKO memory
|
||||||
|
Rev 1.1 and 1.2 Onboard Micron MT41K512M16HA-125A memory
|
||||||
|
|
||||||
|
Use 'make menuconfig' to configure `onboard memory manufacture` in Mainboard
|
||||||
|
menu.
|
||||||
|
|
||||||
|
## Required blobs
|
||||||
|
|
||||||
|
This board currently requires:
|
||||||
|
fsp blob 3rdparty/fsp/BraswellFspBinPkg/FspBin/BSWFSP.fd
|
||||||
|
Microcode Intel Braswell cpuid 1046C4 version 410
|
||||||
|
(Used pre-built binary retrieved from Intel site)
|
||||||
|
|
||||||
|
## Flashing coreboot
|
||||||
|
|
||||||
|
### Internal programming
|
||||||
|
|
||||||
|
The main SPI flash can be accessed using [flashrom].
|
||||||
|
|
||||||
|
### External programming
|
||||||
|
|
||||||
|
The system has an internal flash chip which is a 8 MiB soldered SOIC-8 chip.
|
||||||
|
This chip is located on the top middle side of the board. It's located
|
||||||
|
between SoC and Q7 connector. Use clip (or solder wires) to program
|
||||||
|
the chip.
|
||||||
|
Specifically, it's a Winbond W25Q64FW (1.8V), whose datasheet can be found
|
||||||
|
[here][W25Q64FW].
|
||||||
|
|
||||||
|
## Known issues
|
||||||
|
|
||||||
|
- The PQ7 module contains Q7 connector only. Depending on the carrier
|
||||||
|
serial/video/pcie ports might be available.
|
||||||
|
|
||||||
|
## Untested
|
||||||
|
|
||||||
|
- hardware monitor
|
||||||
|
- SDIO
|
||||||
|
- Full Embedded Controller support
|
||||||
|
|
||||||
|
## Working (using carrier)
|
||||||
|
|
||||||
|
- USB
|
||||||
|
- Gigabit Ethernet
|
||||||
|
- integrated graphics
|
||||||
|
- flashrom
|
||||||
|
- external graphics
|
||||||
|
- PCIe
|
||||||
|
- eMMC
|
||||||
|
- SATA
|
||||||
|
- serial port
|
||||||
|
- SMbus
|
||||||
|
- HDA (codec on carrier)
|
||||||
|
- initialization with FSP MR2
|
||||||
|
- SeaBIOS payload (version rel-1.11.0-44-g7961917)
|
||||||
|
- Embedded Linux (Ubuntu 4.15+)
|
||||||
|
|
||||||
|
## Technology
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+------------------+--------------------------------------------------+
|
||||||
|
| SoC | Intel Atom Processor N3710 |
|
||||||
|
+------------------+--------------------------------------------------+
|
||||||
|
| CPU | Intel Braswell (N3710) |
|
||||||
|
+------------------+--------------------------------------------------+
|
||||||
|
| Super I/O, EC | ITE8256 |
|
||||||
|
+------------------+--------------------------------------------------+
|
||||||
|
| Coprocessor | Intel Management Engine |
|
||||||
|
+------------------+--------------------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
[Portwell PQ7-M107]: http://portwell.com/products/detail.php?CUSTCHAR1=PQ7-M107
|
||||||
|
[W25Q64FW]: https://www.winbond.com/resource-files/w25q64fw%20revn%2005182017%20sfdp.pdf
|
||||||
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
[Board manual]: www.portwell.com/pdf/embedded/PQ7-M107.pdf
|
@@ -17,7 +17,6 @@ The following things are still missing from this coreboot port:
|
|||||||
- Provide serial number to payload (e.g. in device tree)
|
- Provide serial number to payload (e.g. in device tree)
|
||||||
- Implement instruction emulation
|
- Implement instruction emulation
|
||||||
- Support for booting Linux on RISC-V
|
- Support for booting Linux on RISC-V
|
||||||
- Add support to run OpenSBI payload in m-mode
|
|
||||||
- SMP support in trap handler
|
- SMP support in trap handler
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@@ -68,6 +68,7 @@ be more frequent than was needed, so we scaled it back to twice a year.
|
|||||||
- [ ] Announce that the release tag is done on IRC
|
- [ ] Announce that the release tag is done on IRC
|
||||||
- [ ] Update release notes with actual commit id, push to repo
|
- [ ] Update release notes with actual commit id, push to repo
|
||||||
- [ ] Upload release files to web server
|
- [ ] Upload release files to web server
|
||||||
|
- [ ] Upload crossgcc sources to web server
|
||||||
- [ ] Update download page to point to files, push to repo
|
- [ ] Update download page to point to files, push to repo
|
||||||
- [ ] Write and publish blog post with release notes.
|
- [ ] Write and publish blog post with release notes.
|
||||||
- [ ] Update the topic in the irc channel that the release is done.
|
- [ ] Update the topic in the irc channel that the release is done.
|
||||||
@@ -195,6 +196,22 @@ The downloads page is the official place to download the releases from, and it n
|
|||||||
|
|
||||||
Here is an example commit to change it: https://review.coreboot.org/#/c/19515/
|
Here is an example commit to change it: https://review.coreboot.org/#/c/19515/
|
||||||
|
|
||||||
|
## Upload crossgcc sources
|
||||||
|
Sometimes the source files for older revisions of
|
||||||
|
crossgcc disappear. To deal with that we maintain a mirror at
|
||||||
|
https://www.coreboot.org/releases/crossgcc-sources/ where we host the
|
||||||
|
sources used by the crossgcc scripts that are part of coreboot releases.
|
||||||
|
|
||||||
|
Run
|
||||||
|
|
||||||
|
````
|
||||||
|
% util/crossgcc/buildgcc -u
|
||||||
|
````
|
||||||
|
|
||||||
|
This will output the set of URLs that the script uses to download the
|
||||||
|
sources. Download them yourself and copy them into the crossgcc-sources
|
||||||
|
directory on the server.
|
||||||
|
|
||||||
## After the release is complete
|
## After the release is complete
|
||||||
Post the release notes on https://blogs.coreboot.org
|
Post the release notes on https://blogs.coreboot.org
|
||||||
|
|
||||||
|
@@ -1,18 +1,39 @@
|
|||||||
Upcoming release - coreboot 4.10
|
coreboot 4.10 release notes
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
The 4.10 release is planned for April/May 2019
|
The 4.10 release covers commit a2faaa9a2 to commit ae317695e3
|
||||||
|
There is a pgp signed 4.10 tag in the git repository, and a branch will
|
||||||
|
be created as needed.
|
||||||
|
|
||||||
Update this document with changes that should be in the release
|
In nearly 8 months since 4.9 we had 198 authors commit 2538 changes
|
||||||
notes.
|
to master. Of these, 85 authors made their first commit to coreboot:
|
||||||
* Please use Markdown.
|
Welcome!
|
||||||
* See the [4.7](coreboot-4.7-relnotes.md) and [4.9](coreboot-4.9-relnotes.md)
|
|
||||||
release notes for the general format.
|
|
||||||
* The chip and board additions and removals will be updated right
|
|
||||||
before the release, so those do not need to be added.
|
|
||||||
|
|
||||||
Significant changes
|
Between the releases the tree grew by about 11000 lines of code plus
|
||||||
-------------------
|
5000 lines of comments.
|
||||||
|
|
||||||
|
Again, a big Thank You to all contributors who helped shape the coreboot
|
||||||
|
project, community and code with their effort, no matter if through
|
||||||
|
development, review, testing, documentation or by helping people asking
|
||||||
|
questions on our venues like IRC or our mailing list.
|
||||||
|
|
||||||
|
What's New
|
||||||
|
----------
|
||||||
|
|
||||||
|
Most of the changes were to mainboards, and on the chipset side, lots
|
||||||
|
of activity concentrated on x86. However compared to previous releases
|
||||||
|
activity (and therefore interest, probably) increased in vboot and in
|
||||||
|
non-x86 architectures. However it's harder this time to give this release
|
||||||
|
a single topic like the last: This release accumulates some of everything.
|
||||||
|
|
||||||
|
Clean Up
|
||||||
|
--------
|
||||||
|
As usual, there was a lot of cleaning up going on, and there notably,
|
||||||
|
a good chunk of this year's Google Summer of Code project to clean out
|
||||||
|
the issues reported by Coverity Scan is already in.
|
||||||
|
|
||||||
|
The only larger scale change that was registered in the pre-release
|
||||||
|
notes was also about cleaning up the tree:
|
||||||
|
|
||||||
### `device_t` is no more
|
### `device_t` is no more
|
||||||
coreboot used to have a data type, `device_t` that changed shape depending on
|
coreboot used to have a data type, `device_t` that changed shape depending on
|
||||||
@@ -22,3 +43,97 @@ time when romstage wasn't operated in Cache-As-RAM mode, but compiled with
|
|||||||
our romcc compiler.
|
our romcc compiler.
|
||||||
|
|
||||||
That data type is now gone.
|
That data type is now gone.
|
||||||
|
|
||||||
|
Release Notes maintenance
|
||||||
|
-------------------------
|
||||||
|
Speaking of pre-release notes: After 4.10 we'll start a document for
|
||||||
|
4.11 in the git repository. Feel free to add notable achievements there
|
||||||
|
so we remember to give them a shout out in the next release's notes.
|
||||||
|
|
||||||
|
Known Issues
|
||||||
|
------------
|
||||||
|
Sadly, Google Cyan is broken in this release. It doesn't work with the
|
||||||
|
"C environment" bootblock (as compared to the old romcc type bootblock)
|
||||||
|
which is now the default. Sadly it doesn't help to simply revert that
|
||||||
|
change because doing so breaks other boards.
|
||||||
|
|
||||||
|
If you want to use Google Cyan with the release (or if
|
||||||
|
you're tracking the master branch), please keep an eye on
|
||||||
|
https://review.coreboot.org/c/coreboot/+/34304 where a solution for this
|
||||||
|
issue is sought.
|
||||||
|
|
||||||
|
Deprecations
|
||||||
|
------------
|
||||||
|
As announced in the 4.9 release notes, there are no deprecations after 4.10.
|
||||||
|
While 4.10 is also released late and we target a 4.11 release in October we
|
||||||
|
nonetheless want to announce deprecations this time: These are under
|
||||||
|
discussion since January, people are working on mitigations for about as long
|
||||||
|
and so it should be possible to resolve the outstanding issues by the end of
|
||||||
|
October.
|
||||||
|
|
||||||
|
Specifically, we want to require code to work with the following Kconfig
|
||||||
|
options so we can remove the options and the code they disable:
|
||||||
|
|
||||||
|
* C\_ENVIRONMENT\_BOOTBLOCK
|
||||||
|
* NO\_CAR\_GLOBAL\_MIGRATION
|
||||||
|
* RELOCATABLE\_RAMSTAGE
|
||||||
|
|
||||||
|
These only affect x86. If your platform only works without them, please
|
||||||
|
look into fixing that.
|
||||||
|
|
||||||
|
Added 28 mainboards:
|
||||||
|
--------------------
|
||||||
|
* ASROCK H110M-DVS
|
||||||
|
* ASUS H61M-CS
|
||||||
|
* ASUS P5G41T-M-LX
|
||||||
|
* ASUS P5QPL-AM
|
||||||
|
* ASUS P8Z77-M-PRO
|
||||||
|
* FACEBOOK FBG1701
|
||||||
|
* FOXCONN G41M
|
||||||
|
* GIGABYTE GA-H61MA-D3V
|
||||||
|
* GOOGLE BLOOG
|
||||||
|
* GOOGLE FLAPJACK
|
||||||
|
* GOOGLE GARG
|
||||||
|
* GOOGLE HATCH-WHL
|
||||||
|
* GOOGLE HELIOS
|
||||||
|
* GOOGLE KINDRED
|
||||||
|
* GOOGLE KODAMA
|
||||||
|
* GOOGLE KOHAKU
|
||||||
|
* GOOGLE KRANE
|
||||||
|
* GOOGLE MISTRAL
|
||||||
|
* HP COMPAQ-8200-ELITE-SFF-PC
|
||||||
|
* INTEL COMETLAKE-RVP
|
||||||
|
* INTEL KBLRVP11
|
||||||
|
* LENOVO R500
|
||||||
|
* LENOVO X1
|
||||||
|
* MSI MS7707
|
||||||
|
* PORTWELL M107
|
||||||
|
* PURISM LIBREM13-V4
|
||||||
|
* PURISM LIBREM15-V4
|
||||||
|
* SUPERMICRO X10SLM-PLUS-F
|
||||||
|
* UP SQUARED
|
||||||
|
|
||||||
|
Removed 7 mainboards:
|
||||||
|
---------------------
|
||||||
|
* GOOGLE BIP
|
||||||
|
* GOOGLE DELAN
|
||||||
|
* GOOGLE ROWAN
|
||||||
|
* PCENGINES ALIX1C
|
||||||
|
* PCENGINES ALIX2C
|
||||||
|
* PCENGINES ALIX2D
|
||||||
|
* PCENGINES ALIX6
|
||||||
|
|
||||||
|
Removed 3 processors:
|
||||||
|
---------------------
|
||||||
|
* src/cpu/amd/geode\_lx
|
||||||
|
* src/cpu/intel/model\_69x
|
||||||
|
* src/cpu/intel/model\_6dx
|
||||||
|
|
||||||
|
Added 2 socs:
|
||||||
|
-------------
|
||||||
|
* src/soc/amd/picasso
|
||||||
|
* src/soc/qualcomm/qcs405
|
||||||
|
|
||||||
|
Toolchain
|
||||||
|
---------
|
||||||
|
* Update to gcc 8.3.0, binutils 2.32, IASL 20190509, clang 8
|
||||||
|
17
Documentation/releases/coreboot-4.11-relnotes.md
Normal file
17
Documentation/releases/coreboot-4.11-relnotes.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
Upcoming release - coreboot 4.11
|
||||||
|
================================
|
||||||
|
|
||||||
|
The 4.11 release is planned for October 2019
|
||||||
|
|
||||||
|
Update this document with changes that should be in the release
|
||||||
|
notes.
|
||||||
|
* Please use Markdown.
|
||||||
|
* See the [4.9](coreboot-4.9-relnotes.md) and [4.10](coreboot-4.10-relnotes.md)
|
||||||
|
release notes for the general format.
|
||||||
|
* The chip and board additions and removals will be updated right
|
||||||
|
before the release, so those do not need to be added.
|
||||||
|
|
||||||
|
Significant changes
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### Add significant changes here
|
@@ -7,3 +7,9 @@ This section describes documentation about the security architecture of coreboot
|
|||||||
- [Verified Boot](vboot/index.md)
|
- [Verified Boot](vboot/index.md)
|
||||||
- [Measured Boot](vboot/measured_boot.md)
|
- [Measured Boot](vboot/measured_boot.md)
|
||||||
- [Memory clearing](memory_clearing.md)
|
- [Memory clearing](memory_clearing.md)
|
||||||
|
|
||||||
|
## Intel TXT
|
||||||
|
|
||||||
|
- [Intel TXT in general](intel/txt.md)
|
||||||
|
- [Intel TXT Initial Boot Block](intel/txt_ibb.md)
|
||||||
|
- [Intel Authenticated Code Modules](intel/acm.md)
|
||||||
|
57
Documentation/security/intel/acm.md
Normal file
57
Documentation/security/intel/acm.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Intel Authenticated Code Modules
|
||||||
|
|
||||||
|
The Authenticated Code Modules (ACMs) are Intel digitally signed modules
|
||||||
|
that contain code to be run before the traditional x86 CPU reset vector.
|
||||||
|
The ACMs can be invoked at runtime through the GETSEC instruction, too.
|
||||||
|
|
||||||
|
A platform that wants to use Intel TXT must use two ACMs:
|
||||||
|
1. BIOS ACM
|
||||||
|
* The BIOS ACM must be present in the boot flash.
|
||||||
|
* The BIOS ACM must be referenced by the [FIT].
|
||||||
|
2. SINIT ACM
|
||||||
|
* The SINIT ACM isn't referenced by the [FIT].
|
||||||
|
* The SINIT ACM should be provided by the boot firmware, but bootloaders
|
||||||
|
like [TBOOT] are able to load them from the filesystem as well.
|
||||||
|
|
||||||
|
## Retrieving ACMs
|
||||||
|
|
||||||
|
The ACMs can be downloaded on Intel's website:
|
||||||
|
[Intel Trusted Execution Technology](https://software.intel.com/en-us/articles/intel-trusted-execution-technology)
|
||||||
|
|
||||||
|
If you want to extract the BLOB from vendor firmware you can search for the
|
||||||
|
string ``LCP_POLICY_DATA`` or ``TXT``.
|
||||||
|
|
||||||
|
## Header
|
||||||
|
|
||||||
|
Every ACM has a fixed size header:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/*
|
||||||
|
* ACM Header v0.0 without dynamic part
|
||||||
|
* Chapter A.1
|
||||||
|
* Intel TXT Software Development Guide (Document: 315168-015)
|
||||||
|
*/
|
||||||
|
struct acm_header_v0 {
|
||||||
|
uint16_t module_type;
|
||||||
|
uint16_t module_sub_type;
|
||||||
|
uint32_t header_len;
|
||||||
|
uint16_t header_version[2];
|
||||||
|
uint16_t chipset_id;
|
||||||
|
uint16_t flags;
|
||||||
|
uint32_t module_vendor;
|
||||||
|
uint32_t date;
|
||||||
|
uint32_t size;
|
||||||
|
uint16_t txt_svn;
|
||||||
|
uint16_t se_svn;
|
||||||
|
uint32_t code_control;
|
||||||
|
uint32_t error_entry_point;
|
||||||
|
uint32_t gdt_limit;
|
||||||
|
uint32_t gdt_ptr;
|
||||||
|
uint32_t seg_sel;
|
||||||
|
uint32_t entry_point;
|
||||||
|
uint8_t reserved2[63];
|
||||||
|
} __packed;
|
||||||
|
```
|
||||||
|
|
||||||
|
[FIT]: ../../soc/intel/fit.md
|
||||||
|
[TBOOT]: https://sourceforge.net/p/tboot/wiki/Home/
|
BIN
Documentation/security/intel/fit_ibb.dia
Normal file
BIN
Documentation/security/intel/fit_ibb.dia
Normal file
Binary file not shown.
153
Documentation/security/intel/fit_ibb.svg
Normal file
153
Documentation/security/intel/fit_ibb.svg
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
|
||||||
|
<svg width="16cm" height="36cm" viewBox="522 318 306 714" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="523.768" y="829.25" width="296.25" height="201.75"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ffffff" x="523.768" y="829.25" width="296.25" height="201.75"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="689.334" y="321.666" width="72.375" height="269.168"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="689.334" y="321.666" width="72.375" height="269.168"/>
|
||||||
|
<text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="725.522" y="460.15">
|
||||||
|
<tspan x="725.522" y="460.15"></tspan>
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="686.166" y1="352" x2="781.166" y2="352"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="685.8" y1="334.434" x2="780.8" y2="334.434"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="682.8" y1="410.934" x2="777.8" y2="410.934"/>
|
||||||
|
<g>
|
||||||
|
<path style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #0000ff" d="M 684.5,342.584 A 30.4704,30.4704 0 0 0 676.673,403.011"/>
|
||||||
|
<polygon style="fill: #0000ff" points="679.632,403.321 675.608,405.273 676.632,403.285 675.656,401.273 "/>
|
||||||
|
<polygon style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #0000ff" points="679.632,403.321 675.608,405.273 676.632,403.285 675.656,401.273 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="694.75" y="367" width="60.2083" height="10.5"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #0000ff" x="694.75" y="367" width="60.2083" height="10.5"/>
|
||||||
|
</g>
|
||||||
|
<text font-size="5.64444" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="653" y="323.334">
|
||||||
|
<tspan x="653" y="323.334">4 GiB </tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="7.90222" style="fill: #0000ff;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="707.958" y="348.25">
|
||||||
|
<tspan x="707.958" y="348.25">FIT Ptr</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="7.90222" style="fill: #ff0000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="692.934" y="330.55">
|
||||||
|
<tspan x="692.934" y="330.55">IA32 reset vec</tspan>
|
||||||
|
</text>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="694.684" y="415.25" width="60.2083" height="41.5333"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #ff0000" x="694.684" y="415.25" width="60.2083" height="41.5333"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #ff0000" d="M 654.458,327 A 65.5176,65.5176 0 0 0 675.175,449.031"/>
|
||||||
|
<polygon style="fill: #ff0000" points="678.138,449.469 673.953,451.045 675.154,449.159 674.366,447.066 "/>
|
||||||
|
<polygon style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #ff0000" points="678.138,449.469 673.953,451.045 675.154,449.159 674.366,447.066 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="694.934" y="462.5" width="60.2083" height="28.7474"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #ff0000" x="694.934" y="462.5" width="60.2083" height="28.7474"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="695.434" y="518.45" width="60.2083" height="12.134"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #00ff00" x="695.434" y="518.45" width="60.2083" height="12.134"/>
|
||||||
|
</g>
|
||||||
|
<text font-size="6.77333" style="fill: #ff0000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="708.208" y="479.25">
|
||||||
|
<tspan x="708.208" y="479.25">BIOS ACM</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="6.77333" style="fill: #ff0000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="707.184" y="432.25">
|
||||||
|
<tspan x="707.184" y="432.25">BOOTBLOCK</tspan>
|
||||||
|
<tspan x="707.184" y="440.717">CODE</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="6.77333" style="fill: #00ff00;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="714.934" y="527">
|
||||||
|
<tspan x="714.934" y="527">uCode</tspan>
|
||||||
|
</text>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #ff0000" x1="655.186" y1="327.12" x2="687.728" y2="326.952"/>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="694.684" y="377.45" width="60.2083" height="10.5"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #0000ff" x="694.684" y="377.45" width="60.2083" height="10.5"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="694.75" y="387.95" width="60.2083" height="10.5"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #0000ff" x="694.75" y="387.95" width="60.2083" height="10.5"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="694.684" y="398.4" width="60.2083" height="10.5"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #0000ff" x="694.684" y="398.4" width="60.2083" height="10.5"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="691.018" y="588.75" width="68.5" height="4.25"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ffffff" x="691.018" y="588.75" width="68.5" height="4.25"/>
|
||||||
|
</g>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="689.334" y1="590.834" x2="689.018" y2="509.25"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="683.092" y1="493.9" x2="778.092" y2="493.9"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="682.592" y1="459.4" x2="777.592" y2="459.4"/>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="695.776" y="533.91" width="60.2083" height="12.134"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #00ff00" x="695.776" y="533.91" width="60.2083" height="12.134"/>
|
||||||
|
</g>
|
||||||
|
<text font-size="6.77333" style="fill: #00ff00;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="714.026" y="542.21">
|
||||||
|
<tspan x="714.026" y="542.21">uCode</tspan>
|
||||||
|
</text>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="695.276" y="497.072" width="60.2083" height="15.675"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #ff0000" x="695.276" y="497.072" width="60.2083" height="15.675"/>
|
||||||
|
</g>
|
||||||
|
<text font-size="6.77333" style="fill: #ff0000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="715.276" y="546.122">
|
||||||
|
<tspan x="715.276" y="546.122"></tspan>
|
||||||
|
</text>
|
||||||
|
<g>
|
||||||
|
<rect style="fill: #ffffff" x="695.776" y="551.072" width="60.2083" height="15.3485"/>
|
||||||
|
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #ff0000" x="695.776" y="551.072" width="60.2083" height="15.3485"/>
|
||||||
|
</g>
|
||||||
|
<text font-size="6.77333" style="fill: #ff0000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="705.1" y="506.148">
|
||||||
|
<tspan x="705.1" y="506.148">verstage</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="6.77333" style="fill: #ff0000;text-anchor:start;font-family:monospace;font-style:normal;font-weight:normal" x="719.35" y="561.32">
|
||||||
|
<tspan x="719.35" y="561.32">FSP</tspan>
|
||||||
|
</text>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="682.1" y1="515.408" x2="777.1" y2="515.408"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="682.85" y1="548.738" x2="777.85" y2="548.738"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="789.75" y1="322.584" x2="789.75" y2="458.408"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="789.5" y1="457.908" x2="783" y2="457.908"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="789.6" y1="322.508" x2="783.1" y2="322.508"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="789.75" y1="493.226" x2="790.1" y2="513.834"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="789.85" y1="513.334" x2="783.35" y2="513.334"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="790.2" y1="493.934" x2="783.7" y2="493.934"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="789.65" y1="549.094" x2="790" y2="569.7"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="789.75" y1="569.2" x2="783.25" y2="569.2"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" x1="790.1" y1="549.8" x2="783.6" y2="549.8"/>
|
||||||
|
<g>
|
||||||
|
<path style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 2; stroke: #ff8484" d="M 753.708,392.75 A 49.3538,49.3538 0 0 0 783.042,393.053"/>
|
||||||
|
<polygon style="fill: #ffffff" points="784.252,395.824 787.724,391.442 782.136,391.293 "/>
|
||||||
|
<polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" points="784.252,395.824 787.724,391.442 782.136,391.293 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 2; stroke: #ff8484" d="M 796.338,500.253 A 63.4678,63.4678 0 0 0 754.892,382.7"/>
|
||||||
|
<polygon style="fill: #ffffff" points="795.536,498.321 791.972,502.627 797.555,502.895 "/>
|
||||||
|
<polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" points="795.536,498.321 791.972,502.627 797.555,502.895 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 2; stroke: #ff8484" d="M 795.51,554.953 A 86.6963,86.6963 0 0 0 754.892,403.65"/>
|
||||||
|
<polygon style="fill: #ffffff" points="794.249,553.15 791.641,558.095 797.162,557.214 "/>
|
||||||
|
<polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff8484" points="794.249,553.15 791.641,558.095 797.162,557.214 "/>
|
||||||
|
</g>
|
||||||
|
<text font-size="12.8" style="fill: #ff8484;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="792.75" y="458.584">
|
||||||
|
<tspan x="792.75" y="458.584">IBB</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="12.8" style="fill: #ff8484;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="792" y="516.808">
|
||||||
|
<tspan x="792" y="516.808">IBB</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="12.8" style="fill: #ff8484;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="791.75" y="571.384">
|
||||||
|
<tspan x="791.75" y="571.384">IBB</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="6.77333" style="fill: #0000ff;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="713.25" y="394.834">
|
||||||
|
<tspan x="713.25" y="394.834">type 7</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="6.77333" style="fill: #0000ff;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="713" y="384.958">
|
||||||
|
<tspan x="713" y="384.958">type 7</tspan>
|
||||||
|
</text>
|
||||||
|
<text font-size="6.77333" style="fill: #0000ff;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="713.25" y="405.458">
|
||||||
|
<tspan x="713.25" y="405.458">type 7</tspan>
|
||||||
|
</text>
|
||||||
|
<path style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" d="M 689.334 590.834 C 714.206,590.834 736.628,598.912 761.5,598.912"/>
|
||||||
|
<line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="761.71" y1="590.834" x2="761.5" y2="599.412"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 12 KiB |
117
Documentation/security/intel/txt.md
Normal file
117
Documentation/security/intel/txt.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# Intel Trusted Execution Technology
|
||||||
|
|
||||||
|
Intel TXT allows
|
||||||
|
1. Attestation of the authenticity of a platform and its operating system.
|
||||||
|
2. Assuring that an authentic operating system starts in a
|
||||||
|
trusted environment, which can then be considered trusted.
|
||||||
|
3. Providing of a trusted operating system with additional
|
||||||
|
security capabilities not available to an unproven one.
|
||||||
|
|
||||||
|
Intel TXT requirements:
|
||||||
|
|
||||||
|
1. Intel TXT requires a **TPM** to measure parts of the firmware before it's
|
||||||
|
run on the BSP.
|
||||||
|
2. Intel TXT requires signed **Authenticated Code Modules** ([ACM]s), provided
|
||||||
|
by Intel.
|
||||||
|
3. Intel TXT requires **CPU and Chipset** support (supported since
|
||||||
|
Intel Core 2 Duo/ICH9).
|
||||||
|
|
||||||
|
## Authenticated Code Modules
|
||||||
|
|
||||||
|
The ACMs are Intel digitally signed modules that contain code to be run
|
||||||
|
before the traditional x86 CPU reset vector.
|
||||||
|
|
||||||
|
More details can be found here: [Intel ACM].
|
||||||
|
|
||||||
|
## Modified bootflow with Intel TXT
|
||||||
|
|
||||||
|
With Intel TXT the first instruction executed on the BSP isn't the
|
||||||
|
*reset vector*, but the [Intel ACM].
|
||||||
|
It initializes the TPM and measures parts of the firmware, the IBB.
|
||||||
|
|
||||||
|
### Marking the Initial Boot Block
|
||||||
|
|
||||||
|
Individual files in the CBFS can be marked as IBB.
|
||||||
|
|
||||||
|
More details can be found in the [Intel TXT IBB] chapter.
|
||||||
|
|
||||||
|
### Measurements
|
||||||
|
The IBBs (Initial Boot Blocks) are measured into TPM's PCR0 by the BIOS [ACM]
|
||||||
|
before the CPU reset vector is executed. To indentify the regions that need
|
||||||
|
to be measured, the [FIT] contains one ore multiple *Type 7* entries, that
|
||||||
|
point to the IBBs.
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
After the IBBs have been measured, the ACM decides if the boot firmware is
|
||||||
|
trusted. There exists two validation modes:
|
||||||
|
1. HASH Autopromotion
|
||||||
|
* Uses a known good HASH stored in TPM NVRAM
|
||||||
|
* Doesn't allow to boot a fallback IBB
|
||||||
|
2. Signed BIOS policy
|
||||||
|
* Uses a signed policy stored in flash containing multiple HASHes
|
||||||
|
* The public key HASH of BIOS policy is burned into TPM by manufacturer
|
||||||
|
* Can be updated by firmware
|
||||||
|
* Allows to boot a fallback IBB
|
||||||
|
|
||||||
|
At the moment only *Autopromotion mode* is implemented and tested well.
|
||||||
|
|
||||||
|
In the next step the ACM terminates and the regular x86 CPU reset vector
|
||||||
|
is being executed on the BSP.
|
||||||
|
|
||||||
|
### Protecting Secrets in Memory
|
||||||
|
|
||||||
|
Intel TXT sets the `Secrets in Memory` bit, whenever the launch of the SINIT
|
||||||
|
ACM was successful.
|
||||||
|
The bit is reset when leaving the *MLE* by a regular shutdown or by removing
|
||||||
|
the CMOS battery.
|
||||||
|
|
||||||
|
When `Secrets in Memory` bit is set and the IBB isn't trusted, the memory
|
||||||
|
controller won't be unlocked, resulting in a platform that cannot access DRAM.
|
||||||
|
|
||||||
|
When `Secrets in Memory` bit is set and the IBB is trusted, the memory
|
||||||
|
controller will be unlocked, and it's the responsibility of the firmware to
|
||||||
|
[clear all DRAM] and wipe any secrets of the MLE.
|
||||||
|
The platform will be reset after all DRAM has been wiped and will boot
|
||||||
|
with the `Secrets in Memory` bit cleared.
|
||||||
|
|
||||||
|
### Configuring protected regions for SINIT ACM
|
||||||
|
|
||||||
|
The memory regions used by the SINIT ACM need to be prepared and protected
|
||||||
|
against DMA attacks.
|
||||||
|
The SINIT ACM as well as the SINIT handoff data are placed in memory.
|
||||||
|
|
||||||
|
### Locking TXT register
|
||||||
|
|
||||||
|
As last step the TXT registers are locked.
|
||||||
|
|
||||||
|
Whenever the SINIT ACM is invoked, it verifies that the hardware is in the
|
||||||
|
correct state. If it's not the SINIT ACM will reset the platform.
|
||||||
|
|
||||||
|
## For developers
|
||||||
|
### Configuring Intel TXT in Kconfig
|
||||||
|
Enable ``TEE_INTEL_TXT`` and set the following:
|
||||||
|
|
||||||
|
``TEE_INTEL_TXT_BIOSACM_FILE`` to the path of the BIOS ACM provided by Intel
|
||||||
|
|
||||||
|
``TEE_INTEL_TXT_SINITACM_FILE`` to the path of the SINIT ACM provided by Intel
|
||||||
|
### Print TXT status as early as possible
|
||||||
|
Add platform code to print the TXT status as early as possible, as the register
|
||||||
|
is cleared on cold reset.
|
||||||
|
|
||||||
|
## References
|
||||||
|
More information can be found here:
|
||||||
|
* [Intel TXT Software Development Guide]
|
||||||
|
* [Intel TXT enabling]
|
||||||
|
* [FIT]
|
||||||
|
* [Intel TXT Lab Handout]
|
||||||
|
|
||||||
|
[Intel TXT IBB]: txt_ibb.md
|
||||||
|
[FIT]: ../../soc/intel/fit.md
|
||||||
|
[Intel ACM]: acm.md
|
||||||
|
[ACM]: acm.md
|
||||||
|
[FIT table]: ../../soc/intel/fit.md
|
||||||
|
[clear all DRAM]: ../memory_clearing.md
|
||||||
|
[Intel TXT Lab Handout]: https://downloadmirror.intel.com/18931/eng/Intel%20TXT%20LAB%20Handout.pdf
|
||||||
|
[Intel TXT Software Development Guide]: https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
|
||||||
|
[Intel TXT enabling]: https://www.intel.com/content/dam/www/public/us/en/documents/guides/txt-enabling-guide.pdf
|
39
Documentation/security/intel/txt_ibb.md
Normal file
39
Documentation/security/intel/txt_ibb.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Intel TXT Initial Boot Block
|
||||||
|
|
||||||
|
The Initial Boot Block (IBB) consists out of one or more files in the CBFS.
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
The IBB must follow the following constrains:
|
||||||
|
* One IBB must contain the reset vector as well as the [FIT table].
|
||||||
|
* The IBB should be as small as possible.
|
||||||
|
* The IBBs must not overlap each other.
|
||||||
|
* The IBB might overlap with microcode.
|
||||||
|
* The IBB must not overlap the BIOS ACM.
|
||||||
|
* The IBB size must be a multiple of 16.
|
||||||
|
* Either one of the following:
|
||||||
|
* The IBB must be able to train the main system memory and clear all secrets.
|
||||||
|
* If the IBB cannot train the main system memory it must verify the code
|
||||||
|
that can train the main system memory and is able to clear all secrets.
|
||||||
|
|
||||||
|
## Identification
|
||||||
|
|
||||||
|
To add the IBBs to the [FIT], all CBFS files are added using the `cbfstool`
|
||||||
|
with the `--ibb` flag set.
|
||||||
|
The flags sets the CBFS file attribute tag to LE `' IBB'`.
|
||||||
|
|
||||||
|
The make system in turn adds all those files to the [FIT] as type 7.
|
||||||
|
|
||||||
|
## Intel TXT measurements
|
||||||
|
|
||||||
|
Each IBB is measured and extended into PCR0 by [Intel TXT], before the CPU
|
||||||
|
reset vector is executed.
|
||||||
|
The IBBs are measured in the order they are listed in the [FIT].
|
||||||
|
|
||||||
|
## FIT schematic
|
||||||
|
|
||||||
|
![][fit_ibb]
|
||||||
|
|
||||||
|
[fit_ibb]: fit_ibb.svg
|
||||||
|
[FIT]: ../../soc/intel/fit.md
|
||||||
|
[Intel TXT]: txt.md
|
15
MAINTAINERS
15
MAINTAINERS
@@ -135,7 +135,6 @@ Maintainers List (try to look for most precise areas first)
|
|||||||
|
|
||||||
RISC-V ARCHITECTURE
|
RISC-V ARCHITECTURE
|
||||||
M: Ronald Minnich <rminnich@gmail.com>
|
M: Ronald Minnich <rminnich@gmail.com>
|
||||||
M: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
|
|
||||||
R: Philipp Hug <philipp@hug.cx>
|
R: Philipp Hug <philipp@hug.cx>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: src/arch/riscv/
|
F: src/arch/riscv/
|
||||||
@@ -398,6 +397,12 @@ M: Wim Vervoorn <wvervoorn@eltan.com>
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: src/mainboard/facebook/fbg1701/
|
F: src/mainboard/facebook/fbg1701/
|
||||||
|
|
||||||
|
PORTWELL PQ-M107 MAINBOARD
|
||||||
|
M: Frans Hendriks <fhendriks@eltan.com>
|
||||||
|
M: Wim Vervoorn <wvervoorn@eltan.com>
|
||||||
|
S: Maintained
|
||||||
|
F: src/mainboard/portwell/m107/
|
||||||
|
|
||||||
AMD FAMILY10H & FAMILY15H (NON-AGESA) CPUS & NORTHBRIDGE
|
AMD FAMILY10H & FAMILY15H (NON-AGESA) CPUS & NORTHBRIDGE
|
||||||
M: Timothy Pearson <tpearson@raptorengineeringinc.com>
|
M: Timothy Pearson <tpearson@raptorengineeringinc.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
@@ -674,6 +679,14 @@ MISSING: SPI
|
|||||||
# Owners: Patrick, Philipp
|
# Owners: Patrick, Philipp
|
||||||
# Backups:
|
# Backups:
|
||||||
|
|
||||||
|
CODE OF CONDUCT
|
||||||
|
M: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
||||||
|
M: Patrick Georgi <patrick@coreboot.org>
|
||||||
|
M: Ronald Minnich <rminnich@coreboot.org>
|
||||||
|
M: Martin Roth <martin@coreboot.org>
|
||||||
|
S: Maintained
|
||||||
|
F: Documentation/community/code_of_conduct.md
|
||||||
|
|
||||||
# Wiki
|
# Wiki
|
||||||
# Owners: Stefan, Patrick
|
# Owners: Stefan, Patrick
|
||||||
# Backups:
|
# Backups:
|
||||||
|
5
Makefile
5
Makefile
@@ -124,16 +124,17 @@ ifneq ($(MAKECMDGOALS),)
|
|||||||
ifneq ($(filter %config %clean cross% clang iasl gnumake lint% help% what-jenkins-does,$(MAKECMDGOALS)),)
|
ifneq ($(filter %config %clean cross% clang iasl gnumake lint% help% what-jenkins-does,$(MAKECMDGOALS)),)
|
||||||
NOCOMPILE:=1
|
NOCOMPILE:=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(MAKECMDGOALS), %clean)
|
ifneq ($(filter %clean lint% help% what-jenkins-does,$(MAKECMDGOALS)),)
|
||||||
NOMKDIR:=1
|
NOMKDIR:=1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
-include $(TOPLEVEL)/site-local/Makefile.inc
|
||||||
|
|
||||||
ifeq ($(NOCOMPILE),1)
|
ifeq ($(NOCOMPILE),1)
|
||||||
include $(TOPLEVEL)/Makefile.inc
|
include $(TOPLEVEL)/Makefile.inc
|
||||||
include $(TOPLEVEL)/payloads/Makefile.inc
|
include $(TOPLEVEL)/payloads/Makefile.inc
|
||||||
include $(TOPLEVEL)/util/testing/Makefile.inc
|
include $(TOPLEVEL)/util/testing/Makefile.inc
|
||||||
-include $(TOPLEVEL)/site-local/Makefile.inc
|
|
||||||
real-all:
|
real-all:
|
||||||
@echo "Error: Expected config file ($(DOTCONFIG)) not present." >&2
|
@echo "Error: Expected config file ($(DOTCONFIG)) not present." >&2
|
||||||
@echo "Please specify a config file or run 'make menuconfig' to" >&2
|
@echo "Please specify a config file or run 'make menuconfig' to" >&2
|
||||||
|
@@ -401,7 +401,7 @@ endif
|
|||||||
|
|
||||||
CFLAGS_common += -pipe -g -nostdinc -std=gnu11
|
CFLAGS_common += -pipe -g -nostdinc -std=gnu11
|
||||||
CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes
|
CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes
|
||||||
CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs
|
CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -Wimplicit-fallthrough
|
||||||
CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits
|
CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits
|
||||||
CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer
|
CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer
|
||||||
CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie
|
CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie
|
||||||
@@ -705,6 +705,11 @@ $(objcbfs)/bootblock.raw.bin: $(objcbfs)/bootblock.raw.elf
|
|||||||
@printf " OBJCOPY $(notdir $(@))\n"
|
@printf " OBJCOPY $(notdir $(@))\n"
|
||||||
$(OBJCOPY_bootblock) -O binary $< $@
|
$(OBJCOPY_bootblock) -O binary $< $@
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_HAVE_BOOTBLOCK),y)
|
||||||
|
$(objcbfs)/bootblock.bin:
|
||||||
|
dd if=/dev/zero of=$@ bs=64 count=1
|
||||||
|
endif
|
||||||
|
|
||||||
$(objcbfs)/%.bin: $(objcbfs)/%.raw.bin
|
$(objcbfs)/%.bin: $(objcbfs)/%.raw.bin
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
|
2
configs/config.emulation_qemu_riscv_rv64
Normal file
2
configs/config.emulation_qemu_riscv_rv64
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_BOARD_EMULATION_QEMU_RISCV_RV64=y
|
||||||
|
CONFIG_RISCV_OPENSBI=y
|
2
configs/config.up_squared.vboot
Normal file
2
configs/config.up_squared.vboot
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_VENDOR_UP=y
|
||||||
|
CONFIG_VBOOT=y
|
@@ -30,7 +30,7 @@ config PAYLOAD_ELF
|
|||||||
|
|
||||||
config PAYLOAD_FIT
|
config PAYLOAD_FIT
|
||||||
bool "A FIT payload"
|
bool "A FIT payload"
|
||||||
depends on ARCH_ARM64
|
depends on ARCH_ARM64 || ARCH_RISCV
|
||||||
select PAYLOAD_FIT_SUPPORT
|
select PAYLOAD_FIT_SUPPORT
|
||||||
help
|
help
|
||||||
Select this option if you have a payload image (a FIT file) which
|
Select this option if you have a payload image (a FIT file) which
|
||||||
@@ -99,8 +99,8 @@ config PAYLOAD_IS_FLAT_BINARY
|
|||||||
config PAYLOAD_FIT_SUPPORT
|
config PAYLOAD_FIT_SUPPORT
|
||||||
bool "FIT support"
|
bool "FIT support"
|
||||||
default n
|
default n
|
||||||
default y if PAYLOAD_LINUX && (ARCH_ARM || ARCH_ARM64)
|
default y if PAYLOAD_LINUX && (ARCH_ARM || ARCH_ARM64 || ARCH_RISCV)
|
||||||
depends on ARCH_ARM64
|
depends on ARCH_ARM64 || ARCH_RISCV
|
||||||
select FLATTENED_DEVICE_TREE
|
select FLATTENED_DEVICE_TREE
|
||||||
help
|
help
|
||||||
Select this option if your payload is of type FIT.
|
Select this option if your payload is of type FIT.
|
||||||
|
2
payloads/external/GRUB2/Makefile
vendored
2
payloads/external/GRUB2/Makefile
vendored
@@ -28,7 +28,7 @@ grub2/build/config.h: $(CONFIG_DEP) | checkout
|
|||||||
echo " CONFIG GRUB2 $(NAME-y)"
|
echo " CONFIG GRUB2 $(NAME-y)"
|
||||||
rm -rf grub2/build
|
rm -rf grub2/build
|
||||||
mkdir grub2/build
|
mkdir grub2/build
|
||||||
cd grub2 && ./bootstrap.sh ; ./autogen.sh
|
cd grub2 && ./bootstrap ; ./autogen.sh
|
||||||
cd grub2/build && ../configure CC="$(HOSTCC)" LD="$(LD)" \
|
cd grub2/build && ../configure CC="$(HOSTCC)" LD="$(LD)" \
|
||||||
FREETYPE="pkg-config freetype2" BUILD_FREETYPE="pkg-config freetype2" \
|
FREETYPE="pkg-config freetype2" BUILD_FREETYPE="pkg-config freetype2" \
|
||||||
TARGET_CC="$(CC)" TARGET_OBJCOPY="$(OBJCOPY)" TARGET_STRIP="$(STRIP)" \
|
TARGET_CC="$(CC)" TARGET_OBJCOPY="$(OBJCOPY)" TARGET_STRIP="$(STRIP)" \
|
||||||
|
15
payloads/external/LinuxBoot/Kconfig
vendored
15
payloads/external/LinuxBoot/Kconfig
vendored
@@ -39,6 +39,13 @@ config LINUXBOOT_ARM64
|
|||||||
help
|
help
|
||||||
AARCH64 kernel and initramfs
|
AARCH64 kernel and initramfs
|
||||||
|
|
||||||
|
config LINUXBOOT_RISCV
|
||||||
|
bool "RISC-V"
|
||||||
|
depends on ARCH_RISCV
|
||||||
|
select PAYLOAD_FIT_SUPPORT
|
||||||
|
help
|
||||||
|
RISC-V kernel and initramfs
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
comment "Linux kernel"
|
comment "Linux kernel"
|
||||||
@@ -126,7 +133,7 @@ config LINUXBOOT_KERNEL_CONFIGFILE
|
|||||||
choice
|
choice
|
||||||
prompt "Kernel binary format"
|
prompt "Kernel binary format"
|
||||||
default LINUXBOOT_KERNEL_BZIMAGE if LINUXBOOT_X86 || LINUXBOOT_X86_64
|
default LINUXBOOT_KERNEL_BZIMAGE if LINUXBOOT_X86 || LINUXBOOT_X86_64
|
||||||
default LINUXBOOT_KERNEL_UIMAGE if LINUXBOOT_ARM64
|
default LINUXBOOT_KERNEL_UIMAGE if LINUXBOOT_ARM64 || LINUXBOOT_RISCV
|
||||||
|
|
||||||
config LINUXBOOT_KERNEL_BZIMAGE
|
config LINUXBOOT_KERNEL_BZIMAGE
|
||||||
bool "bzImage"
|
bool "bzImage"
|
||||||
@@ -134,14 +141,14 @@ config LINUXBOOT_KERNEL_BZIMAGE
|
|||||||
|
|
||||||
config LINUXBOOT_KERNEL_UIMAGE
|
config LINUXBOOT_KERNEL_UIMAGE
|
||||||
bool "uImage"
|
bool "uImage"
|
||||||
depends on LINUXBOOT_ARM64
|
depends on LINUXBOOT_ARM64 || LINUXBOOT_RISCV
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
|
||||||
config LINUXBOOT_DTB_FILE
|
config LINUXBOOT_DTB_FILE
|
||||||
string "Compiled devicetree file"
|
string "Compiled devicetree file"
|
||||||
depends on LINUXBOOT_ARM64
|
depends on LINUXBOOT_ARM64 || LINUXBOOT_RISCV
|
||||||
default ""
|
default ""
|
||||||
|
|
||||||
endif #LINUXBOOT_COMPILE_KERNEL
|
endif #LINUXBOOT_COMPILE_KERNEL
|
||||||
@@ -154,7 +161,7 @@ config LINUX_COMMAND_LINE
|
|||||||
|
|
||||||
config PAYLOAD_FILE
|
config PAYLOAD_FILE
|
||||||
default "payloads/external/LinuxBoot/linuxboot/bzImage" if LINUXBOOT_COMPILE_KERNEL && ( LINUXBOOT_X86 || LINUXBOOT_X86_64 )
|
default "payloads/external/LinuxBoot/linuxboot/bzImage" if LINUXBOOT_COMPILE_KERNEL && ( LINUXBOOT_X86 || LINUXBOOT_X86_64 )
|
||||||
default "payloads/external/LinuxBoot/linuxboot/uImage" if LINUXBOOT_COMPILE_KERNEL && LINUXBOOT_ARM64
|
default "payloads/external/LinuxBoot/linuxboot/uImage" if LINUXBOOT_COMPILE_KERNEL && (LINUXBOOT_ARM64 || LINUXBOOT_RISCV)
|
||||||
default LINUXBOOT_KERNEL_PATH if !LINUXBOOT_COMPILE_KERNEL
|
default LINUXBOOT_KERNEL_PATH if !LINUXBOOT_COMPILE_KERNEL
|
||||||
|
|
||||||
comment "Linux initramfs"
|
comment "Linux initramfs"
|
||||||
|
2
payloads/external/LinuxBoot/Kconfig.name
vendored
2
payloads/external/LinuxBoot/Kconfig.name
vendored
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
config PAYLOAD_LINUXBOOT
|
config PAYLOAD_LINUXBOOT
|
||||||
bool "LinuxBoot"
|
bool "LinuxBoot"
|
||||||
depends on ARCH_X86 || ARCH_ARM64
|
depends on ARCH_X86 || ARCH_ARM64 || ARCH_RISCV
|
||||||
help
|
help
|
||||||
Select this option if you want to build a coreboot image
|
Select this option if you want to build a coreboot image
|
||||||
with a LinuxBoot payload. If you don't know what this is
|
with a LinuxBoot payload. If you don't know what this is
|
||||||
|
5
payloads/external/Makefile.inc
vendored
5
payloads/external/Makefile.inc
vendored
@@ -300,10 +300,7 @@ payloads/external/LinuxBoot/linuxboot/initramfs_u-root.cpio: linuxboot
|
|||||||
|
|
||||||
payloads/external/Yabits/uefi/build/uefi.elf yabits:
|
payloads/external/Yabits/uefi/build/uefi.elf yabits:
|
||||||
$(MAKE) -C payloads/external/Yabits all \
|
$(MAKE) -C payloads/external/Yabits all \
|
||||||
CC="$(CC_x86_32)" \
|
XGCCPATH="$(XGCCPATH)" \
|
||||||
LD="$(LD_x86_32)" \
|
|
||||||
OBJCOPY="$(OBJCOPY_x86_32)" \
|
|
||||||
AS="$(AS_x86_32)" \
|
|
||||||
CONFIG_YABITS_REVISION=$(CONFIG_YABITS_REVISION) \
|
CONFIG_YABITS_REVISION=$(CONFIG_YABITS_REVISION) \
|
||||||
CONFIG_YABITS_REVISION_ID=$(CONFIG_YABITS_REVISION_ID) \
|
CONFIG_YABITS_REVISION_ID=$(CONFIG_YABITS_REVISION_ID) \
|
||||||
CONFIG_YABITS_MASTER=$(CONFIG_YABITS_MASTER) \
|
CONFIG_YABITS_MASTER=$(CONFIG_YABITS_MASTER) \
|
||||||
|
2
payloads/external/linux/Kconfig.name
vendored
2
payloads/external/linux/Kconfig.name
vendored
@@ -1,6 +1,6 @@
|
|||||||
config PAYLOAD_LINUX
|
config PAYLOAD_LINUX
|
||||||
bool "A Linux payload"
|
bool "A Linux payload"
|
||||||
depends on ARCH_X86 || ARCH_ARM
|
depends on ARCH_X86 || ARCH_ARM || ARCH_RISCV
|
||||||
help
|
help
|
||||||
Select this option if you have a Linux bzImage which coreboot
|
Select this option if you have a Linux bzImage which coreboot
|
||||||
should run as soon as the basic hardware initialization
|
should run as soon as the basic hardware initialization
|
||||||
|
@@ -63,7 +63,7 @@ CFLAGS += $(EXTRA_CFLAGS) $(INCLUDES) -Os -pipe -nostdinc -ggdb3
|
|||||||
CFLAGS += -nostdlib -fno-builtin -ffreestanding -fomit-frame-pointer
|
CFLAGS += -nostdlib -fno-builtin -ffreestanding -fomit-frame-pointer
|
||||||
CFLAGS += -ffunction-sections -fdata-sections
|
CFLAGS += -ffunction-sections -fdata-sections
|
||||||
CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes
|
CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes
|
||||||
CFLAGS += -Wwrite-strings -Wredundant-decls -Wno-trigraphs
|
CFLAGS += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -Wimplicit-fallthrough
|
||||||
CFLAGS += -Wstrict-aliasing -Wshadow -Werror
|
CFLAGS += -Wstrict-aliasing -Wshadow -Werror
|
||||||
|
|
||||||
$(obj)/libpayload-config.h: $(KCONFIG_AUTOHEADER)
|
$(obj)/libpayload-config.h: $(KCONFIG_AUTOHEADER)
|
||||||
|
@@ -274,7 +274,7 @@ static int _pdc_vsscanf(const char *buf, const char *fmt, va_list arg_ptr)
|
|||||||
NEXT(c);
|
NEXT(c);
|
||||||
goto string;
|
goto string;
|
||||||
}
|
}
|
||||||
/* no break */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
if (fmt[1] == '-' && fmt[2]
|
if (fmt[1] == '-' && fmt[2]
|
||||||
&& f < (unsigned char)fmt[2])
|
&& f < (unsigned char)fmt[2])
|
||||||
|
@@ -285,6 +285,7 @@ struct uart_params_t {
|
|||||||
static struct console_input_driver consin = {
|
static struct console_input_driver consin = {
|
||||||
.havekey = serial_havechar,
|
.havekey = serial_havechar,
|
||||||
.getchar = serial_getchar,
|
.getchar = serial_getchar,
|
||||||
|
.input_type = CONSOLE_INPUT_TYPE_UART,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct console_output_driver consout = {
|
static struct console_output_driver consout = {
|
||||||
|
@@ -129,8 +129,30 @@ static inline void set_pixel(struct vector *coord, uint32_t color)
|
|||||||
{
|
{
|
||||||
const int bpp = fbinfo->bits_per_pixel;
|
const int bpp = fbinfo->bits_per_pixel;
|
||||||
const int bpl = fbinfo->bytes_per_line;
|
const int bpl = fbinfo->bytes_per_line;
|
||||||
|
struct vector rcoord;
|
||||||
int i;
|
int i;
|
||||||
uint8_t * const pixel = fbaddr + coord->y * bpl + coord->x * bpp / 8;
|
|
||||||
|
switch (fbinfo->orientation) {
|
||||||
|
case CB_FB_ORIENTATION_NORMAL:
|
||||||
|
default:
|
||||||
|
rcoord.x = coord->x;
|
||||||
|
rcoord.y = coord->y;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_BOTTOM_UP:
|
||||||
|
rcoord.x = screen.size.width - 1 - coord->x;
|
||||||
|
rcoord.y = screen.size.height - 1 - coord->y;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_LEFT_UP:
|
||||||
|
rcoord.x = coord->y;
|
||||||
|
rcoord.y = screen.size.width - 1 - coord->x;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_RIGHT_UP:
|
||||||
|
rcoord.x = screen.size.height - 1 - coord->y;
|
||||||
|
rcoord.y = coord->x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * const pixel = fbaddr + rcoord.y * bpl + rcoord.x * bpp / 8;
|
||||||
for (i = 0; i < bpp / 8; i++)
|
for (i = 0; i < bpp / 8; i++)
|
||||||
pixel[i] = (color >> (i * 8));
|
pixel[i] = (color >> (i * 8));
|
||||||
}
|
}
|
||||||
@@ -152,8 +174,17 @@ static int cbgfx_init(void)
|
|||||||
if (!fbaddr)
|
if (!fbaddr)
|
||||||
return CBGFX_ERROR_FRAMEBUFFER_ADDR;
|
return CBGFX_ERROR_FRAMEBUFFER_ADDR;
|
||||||
|
|
||||||
|
switch (fbinfo->orientation) {
|
||||||
|
default: /* Normal or rotated 180 degrees. */
|
||||||
screen.size.width = fbinfo->x_resolution;
|
screen.size.width = fbinfo->x_resolution;
|
||||||
screen.size.height = fbinfo->y_resolution;
|
screen.size.height = fbinfo->y_resolution;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_LEFT_UP: /* 90 degree rotation. */
|
||||||
|
case CB_FB_ORIENTATION_RIGHT_UP:
|
||||||
|
screen.size.width = fbinfo->y_resolution;
|
||||||
|
screen.size.height = fbinfo->x_resolution;
|
||||||
|
break;
|
||||||
|
}
|
||||||
screen.offset.x = 0;
|
screen.offset.x = 0;
|
||||||
screen.offset.y = 0;
|
screen.offset.y = 0;
|
||||||
|
|
||||||
@@ -242,7 +273,7 @@ int clear_screen(const struct rgb_color *rgb)
|
|||||||
* We assume that for 32bpp the high byte gets ignored anyway. */
|
* We assume that for 32bpp the high byte gets ignored anyway. */
|
||||||
if ((((color >> 8) & 0xff) == (color & 0xff)) && (bpp == 16 ||
|
if ((((color >> 8) & 0xff) == (color & 0xff)) && (bpp == 16 ||
|
||||||
(((color >> 16) & 0xff) == (color & 0xff)))) {
|
(((color >> 16) & 0xff) == (color & 0xff)))) {
|
||||||
memset(fbaddr, color & 0xff, screen.size.height * bpl);
|
memset(fbaddr, color & 0xff, fbinfo->y_resolution * bpl);
|
||||||
} else {
|
} else {
|
||||||
for (p.y = 0; p.y < screen.size.height; p.y++)
|
for (p.y = 0; p.y < screen.size.height; p.y++)
|
||||||
for (p.x = 0; p.x < screen.size.width; p.x++)
|
for (p.x = 0; p.x < screen.size.width; p.x++)
|
||||||
|
@@ -57,7 +57,7 @@ enum {
|
|||||||
CB_TAG_CBMEM_CONSOLE = 0x0017,
|
CB_TAG_CBMEM_CONSOLE = 0x0017,
|
||||||
CB_TAG_MRC_CACHE = 0x0018,
|
CB_TAG_MRC_CACHE = 0x0018,
|
||||||
CB_TAG_VBNV = 0x0019,
|
CB_TAG_VBNV = 0x0019,
|
||||||
CB_TAG_VBOOT_HANDOFF = 0x0020,
|
CB_TAG_VBOOT_HANDOFF = 0x0020, /* deprecated */
|
||||||
CB_TAG_X86_ROM_MTRR = 0x0021,
|
CB_TAG_X86_ROM_MTRR = 0x0021,
|
||||||
CB_TAG_DMA = 0x0022,
|
CB_TAG_DMA = 0x0022,
|
||||||
CB_TAG_RAM_OOPS = 0x0023,
|
CB_TAG_RAM_OOPS = 0x0023,
|
||||||
@@ -189,6 +189,14 @@ struct cb_forward {
|
|||||||
u64 forward;
|
u64 forward;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Panel orientation, matches drm_connector.h in the Linux kernel. */
|
||||||
|
enum cb_fb_orientation {
|
||||||
|
CB_FB_ORIENTATION_NORMAL = 0,
|
||||||
|
CB_FB_ORIENTATION_BOTTOM_UP = 1,
|
||||||
|
CB_FB_ORIENTATION_LEFT_UP = 2,
|
||||||
|
CB_FB_ORIENTATION_RIGHT_UP = 3,
|
||||||
|
};
|
||||||
|
|
||||||
struct cb_framebuffer {
|
struct cb_framebuffer {
|
||||||
u32 tag;
|
u32 tag;
|
||||||
u32 size;
|
u32 size;
|
||||||
@@ -206,6 +214,7 @@ struct cb_framebuffer {
|
|||||||
u8 blue_mask_size;
|
u8 blue_mask_size;
|
||||||
u8 reserved_mask_pos;
|
u8 reserved_mask_pos;
|
||||||
u8 reserved_mask_size;
|
u8 reserved_mask_size;
|
||||||
|
u8 orientation;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CB_GPIO_ACTIVE_LOW 0
|
#define CB_GPIO_ACTIVE_LOW 0
|
||||||
|
@@ -73,7 +73,7 @@ char *strerror(int errnum);
|
|||||||
* @defgroup string Unicode functions
|
* @defgroup string Unicode functions
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
char *utf16le_to_ascii(uint16_t *utf16_string, int maxlen);
|
char *utf16le_to_ascii(const uint16_t *utf16_string, size_t maxlen);
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -95,8 +95,6 @@ struct sysinfo_t {
|
|||||||
struct cb_header *header;
|
struct cb_header *header;
|
||||||
struct cb_mainboard *mainboard;
|
struct cb_mainboard *mainboard;
|
||||||
|
|
||||||
void *vboot_handoff;
|
|
||||||
u32 vboot_handoff_size;
|
|
||||||
void *vboot_workbuf;
|
void *vboot_workbuf;
|
||||||
uint32_t vboot_workbuf_size;
|
uint32_t vboot_workbuf_size;
|
||||||
|
|
||||||
|
@@ -78,14 +78,6 @@ static void cb_parse_serial(void *ptr, struct sysinfo_t *info)
|
|||||||
info->serial = ((struct cb_serial *)ptr);
|
info->serial = ((struct cb_serial *)ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info)
|
|
||||||
{
|
|
||||||
struct lb_range *vbho = (struct lb_range *)ptr;
|
|
||||||
|
|
||||||
info->vboot_handoff = (void *)(uintptr_t)vbho->range_start;
|
|
||||||
info->vboot_handoff_size = vbho->range_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cb_parse_vboot_workbuf(unsigned char *ptr, struct sysinfo_t *info)
|
static void cb_parse_vboot_workbuf(unsigned char *ptr, struct sysinfo_t *info)
|
||||||
{
|
{
|
||||||
struct lb_range *vbwb = (struct lb_range *)ptr;
|
struct lb_range *vbwb = (struct lb_range *)ptr;
|
||||||
@@ -367,9 +359,6 @@ int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
|
|||||||
case CB_TAG_VBNV:
|
case CB_TAG_VBNV:
|
||||||
cb_parse_vbnv(ptr, info);
|
cb_parse_vbnv(ptr, info);
|
||||||
break;
|
break;
|
||||||
case CB_TAG_VBOOT_HANDOFF:
|
|
||||||
cb_parse_vboot_handoff(ptr, info);
|
|
||||||
break;
|
|
||||||
case CB_TAG_VBOOT_WORKBUF:
|
case CB_TAG_VBOOT_WORKBUF:
|
||||||
cb_parse_vboot_workbuf(ptr, info);
|
cb_parse_vboot_workbuf(ptr, info);
|
||||||
break;
|
break;
|
||||||
|
@@ -585,6 +585,7 @@ static int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
|
|||||||
/* Integer values */
|
/* Integer values */
|
||||||
case 'P': /* pointer */
|
case 'P': /* pointer */
|
||||||
flags |= __PRINTF_FLAG_BIGCHARS;
|
flags |= __PRINTF_FLAG_BIGCHARS;
|
||||||
|
/* fall through */
|
||||||
case 'p':
|
case 'p':
|
||||||
flags |= __PRINTF_FLAG_PREFIX;
|
flags |= __PRINTF_FLAG_PREFIX;
|
||||||
base = 16;
|
base = 16;
|
||||||
@@ -599,10 +600,12 @@ static int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
|
|||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
flags |= __PRINTF_FLAG_SIGNED;
|
flags |= __PRINTF_FLAG_SIGNED;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
break;
|
break;
|
||||||
case 'X':
|
case 'X':
|
||||||
flags |= __PRINTF_FLAG_BIGCHARS;
|
flags |= __PRINTF_FLAG_BIGCHARS;
|
||||||
|
/* fall through */
|
||||||
case 'x':
|
case 'x':
|
||||||
base = 16;
|
base = 16;
|
||||||
break;
|
break;
|
||||||
|
@@ -91,9 +91,9 @@ size_t strlen(const char *str)
|
|||||||
*/
|
*/
|
||||||
int strcasecmp(const char *s1, const char *s2)
|
int strcasecmp(const char *s1, const char *s2)
|
||||||
{
|
{
|
||||||
int i, res;
|
int res;
|
||||||
|
|
||||||
for (i = 0; 1; i++) {
|
for (size_t i = 0; 1; i++) {
|
||||||
res = tolower(s1[i]) - tolower(s2[i]);
|
res = tolower(s1[i]) - tolower(s2[i]);
|
||||||
if (res || (s1[i] == '\0'))
|
if (res || (s1[i] == '\0'))
|
||||||
break;
|
break;
|
||||||
@@ -112,10 +112,9 @@ int strcasecmp(const char *s1, const char *s2)
|
|||||||
*/
|
*/
|
||||||
int strncasecmp(const char *s1, const char *s2, size_t maxlen)
|
int strncasecmp(const char *s1, const char *s2, size_t maxlen)
|
||||||
{
|
{
|
||||||
int i, res;
|
int res = 0;
|
||||||
|
|
||||||
res = 0;
|
for (size_t i = 0; i < maxlen; i++) {
|
||||||
for (i = 0; i < maxlen; i++) {
|
|
||||||
res = tolower(s1[i]) - tolower(s2[i]);
|
res = tolower(s1[i]) - tolower(s2[i]);
|
||||||
if (res || (s1[i] == '\0'))
|
if (res || (s1[i] == '\0'))
|
||||||
break;
|
break;
|
||||||
@@ -135,9 +134,9 @@ int strncasecmp(const char *s1, const char *s2, size_t maxlen)
|
|||||||
*/
|
*/
|
||||||
int strcmp(const char *s1, const char *s2)
|
int strcmp(const char *s1, const char *s2)
|
||||||
{
|
{
|
||||||
int i, res;
|
int res;
|
||||||
|
|
||||||
for (i = 0; 1; i++) {
|
for (size_t i = 0; 1; i++) {
|
||||||
res = s1[i] - s2[i];
|
res = s1[i] - s2[i];
|
||||||
if (res || (s1[i] == '\0'))
|
if (res || (s1[i] == '\0'))
|
||||||
break;
|
break;
|
||||||
@@ -156,10 +155,9 @@ int strcmp(const char *s1, const char *s2)
|
|||||||
*/
|
*/
|
||||||
int strncmp(const char *s1, const char *s2, size_t maxlen)
|
int strncmp(const char *s1, const char *s2, size_t maxlen)
|
||||||
{
|
{
|
||||||
int i, res;
|
int res = 0;
|
||||||
|
|
||||||
res = 0;
|
for (size_t i = 0; i < maxlen; i++) {
|
||||||
for (i = 0; i < maxlen; i++) {
|
|
||||||
res = s1[i] - s2[i];
|
res = s1[i] - s2[i];
|
||||||
if (res || (s1[i] == '\0'))
|
if (res || (s1[i] == '\0'))
|
||||||
break;
|
break;
|
||||||
@@ -179,10 +177,9 @@ int strncmp(const char *s1, const char *s2, size_t maxlen)
|
|||||||
char *strncpy(char *d, const char *s, size_t n)
|
char *strncpy(char *d, const char *s, size_t n)
|
||||||
{
|
{
|
||||||
/* Use +1 to get the NUL terminator. */
|
/* Use +1 to get the NUL terminator. */
|
||||||
int max = n > strlen(s) + 1 ? strlen(s) + 1 : n;
|
size_t max = n > strlen(s) + 1 ? strlen(s) + 1 : n;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++)
|
for (size_t i = 0; i < max; i++)
|
||||||
d[i] = (char)s[i];
|
d[i] = (char)s[i];
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
@@ -210,13 +207,12 @@ char *strcpy(char *d, const char *s)
|
|||||||
char *strcat(char *d, const char *s)
|
char *strcat(char *d, const char *s)
|
||||||
{
|
{
|
||||||
char *p = d + strlen(d);
|
char *p = d + strlen(d);
|
||||||
int sl = strlen(s);
|
size_t sl = strlen(s);
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < sl; i++)
|
for (size_t i = 0; i < sl; i++)
|
||||||
p[i] = s[i];
|
p[i] = s[i];
|
||||||
|
|
||||||
p[i] = '\0';
|
p[sl] = '\0';
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,15 +227,13 @@ char *strcat(char *d, const char *s)
|
|||||||
char *strncat(char *d, const char *s, size_t n)
|
char *strncat(char *d, const char *s, size_t n)
|
||||||
{
|
{
|
||||||
char *p = d + strlen(d);
|
char *p = d + strlen(d);
|
||||||
int sl = strlen(s);
|
size_t sl = strlen(s);
|
||||||
int max = n > sl ? sl : n;
|
size_t max = n > sl ? sl : n;
|
||||||
// int max = n > strlen(s) ? strlen(s) : n;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++)
|
for (size_t i = 0; i < max; i++)
|
||||||
p[i] = s[i];
|
p[i] = s[i];
|
||||||
|
|
||||||
p[i] = '\0';
|
p[max] = '\0';
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,22 +243,24 @@ char *strncat(char *d, const char *s, size_t n)
|
|||||||
* @param d The destination string.
|
* @param d The destination string.
|
||||||
* @param s The source string.
|
* @param s The source string.
|
||||||
* @param n d will have at most n-1 characters (plus NUL) after invocation.
|
* @param n d will have at most n-1 characters (plus NUL) after invocation.
|
||||||
* @return A pointer to the destination string.
|
* @return The total length of the concatenated string.
|
||||||
*/
|
*/
|
||||||
size_t strlcat(char *d, const char *s, size_t n)
|
size_t strlcat(char *d, const char *s, size_t n)
|
||||||
{
|
{
|
||||||
int sl = strlen(s);
|
size_t sl = strlen(s);
|
||||||
int dl = strlen(d);
|
size_t dl = strlen(d);
|
||||||
|
|
||||||
|
if (n <= dl + 1)
|
||||||
|
return sl + dl;
|
||||||
|
|
||||||
char *p = d + dl;
|
char *p = d + dl;
|
||||||
int max = n > (sl + dl) ? sl : (n - dl - 1);
|
size_t max = n > (sl + dl) ? sl : (n - dl - 1);
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++)
|
for (size_t i = 0; i < max; i++)
|
||||||
p[i] = s[i];
|
p[i] = s[i];
|
||||||
|
|
||||||
p[i] = '\0';
|
p[max] = '\0';
|
||||||
return max;
|
return sl + dl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -316,7 +312,7 @@ char *strrchr(const char *s, int c)
|
|||||||
*/
|
*/
|
||||||
char *strdup(const char *s)
|
char *strdup(const char *s)
|
||||||
{
|
{
|
||||||
int n = strlen(s);
|
size_t n = strlen(s);
|
||||||
char *p = malloc(n + 1);
|
char *p = malloc(n + 1);
|
||||||
|
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
@@ -336,11 +332,13 @@ char *strdup(const char *s)
|
|||||||
*/
|
*/
|
||||||
char *strstr(const char *h, const char *n)
|
char *strstr(const char *h, const char *n)
|
||||||
{
|
{
|
||||||
int hn = strlen(h);
|
size_t hn = strlen(h);
|
||||||
int nn = strlen(n);
|
size_t nn = strlen(n);
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i <= hn - nn; i++)
|
if (hn < nn)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= hn - nn; i++)
|
||||||
if (!memcmp(&h[i], n, nn))
|
if (!memcmp(&h[i], n, nn))
|
||||||
return (char *)&h[i];
|
return (char *)&h[i];
|
||||||
|
|
||||||
@@ -532,11 +530,11 @@ unsigned long int strtoul(const char *ptr, char **endptr, int base)
|
|||||||
*/
|
*/
|
||||||
size_t strspn(const char *s, const char *a)
|
size_t strspn(const char *s, const char *a)
|
||||||
{
|
{
|
||||||
int i, j;
|
size_t i;
|
||||||
int al = strlen(a);
|
size_t al = strlen(a);
|
||||||
for (i = 0; s[i] != 0; i++) {
|
for (i = 0; s[i] != 0; i++) {
|
||||||
int found = 0;
|
int found = 0;
|
||||||
for (j = 0; j < al; j++) {
|
for (size_t j = 0; j < al; j++) {
|
||||||
if (s[i] == a[j]) {
|
if (s[i] == a[j]) {
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
@@ -556,11 +554,11 @@ size_t strspn(const char *s, const char *a)
|
|||||||
*/
|
*/
|
||||||
size_t strcspn(const char *s, const char *a)
|
size_t strcspn(const char *s, const char *a)
|
||||||
{
|
{
|
||||||
int i, j;
|
size_t i;
|
||||||
int al = strlen(a);
|
size_t al = strlen(a);
|
||||||
for (i = 0; s[i] != 0; i++) {
|
for (i = 0; s[i] != 0; i++) {
|
||||||
int found = 0;
|
int found = 0;
|
||||||
for (j = 0; j < al; j++) {
|
for (size_t j = 0; j < al; j++) {
|
||||||
if (s[i] == a[j]) {
|
if (s[i] == a[j]) {
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
@@ -645,12 +643,11 @@ char *strerror(int errnum)
|
|||||||
* @param maxlen Maximum possible length of the string in code points
|
* @param maxlen Maximum possible length of the string in code points
|
||||||
* @return Newly allocated ASCII string
|
* @return Newly allocated ASCII string
|
||||||
*/
|
*/
|
||||||
char *utf16le_to_ascii(uint16_t *utf16_string, int maxlen)
|
char *utf16le_to_ascii(const uint16_t *utf16_string, size_t maxlen)
|
||||||
{
|
{
|
||||||
char *ascii_string = xmalloc(maxlen + 1); /* +1 for trailing \0 */
|
char *ascii_string = xmalloc(maxlen + 1); /* +1 for trailing \0 */
|
||||||
ascii_string[maxlen] = '\0';
|
ascii_string[maxlen] = '\0';
|
||||||
int i;
|
for (size_t i = 0; i < maxlen; i++) {
|
||||||
for (i = 0; i < maxlen; i++) {
|
|
||||||
uint16_t wchar = utf16_string[i];
|
uint16_t wchar = utf16_string[i];
|
||||||
ascii_string[i] = wchar > 0x7f ? '?' : (char)wchar;
|
ascii_string[i] = wchar > 0x7f ? '?' : (char)wchar;
|
||||||
}
|
}
|
||||||
|
26
src/Kconfig
26
src/Kconfig
@@ -250,12 +250,28 @@ config RELOCATABLE_RAMSTAGE
|
|||||||
wake. When selecting this option the romstage is responsible for
|
wake. When selecting this option the romstage is responsible for
|
||||||
determing a stack location to use for loading the ramstage.
|
determing a stack location to use for loading the ramstage.
|
||||||
|
|
||||||
config CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
|
config TSEG_STAGE_CACHE
|
||||||
depends on RELOCATABLE_RAMSTAGE
|
|
||||||
bool
|
bool
|
||||||
|
default y
|
||||||
|
depends on !NO_STAGE_CACHE && SMM_TSEG
|
||||||
help
|
help
|
||||||
The relocated ramstage is saved in an area specified by the
|
The option enables stage cache support for platform. Platform
|
||||||
by the board and/or chipset.
|
can stash copies of postcar, ramstage and raw runtime data
|
||||||
|
inside SMM TSEG, to be restored on S3 resume path.
|
||||||
|
|
||||||
|
config CBMEM_STAGE_CACHE
|
||||||
|
bool "Cache stages in CBMEM"
|
||||||
|
depends on !NO_STAGE_CACHE && !TSEG_STAGE_CACHE
|
||||||
|
help
|
||||||
|
The option enables stage cache support for platform. Platform
|
||||||
|
can stash copies of postcar, ramstage and raw runtime data
|
||||||
|
inside CBMEM.
|
||||||
|
|
||||||
|
While the approach is faster than reloading stages from boot media
|
||||||
|
it is also a possible attack scenario via which OS can possibly
|
||||||
|
circumvent SMM locks and SPI write protections.
|
||||||
|
|
||||||
|
If unsure, select 'N'
|
||||||
|
|
||||||
config UPDATE_IMAGE
|
config UPDATE_IMAGE
|
||||||
bool "Update existing coreboot.rom image"
|
bool "Update existing coreboot.rom image"
|
||||||
@@ -1143,7 +1159,7 @@ config RELOCATABLE_MODULES
|
|||||||
|
|
||||||
config NO_STAGE_CACHE
|
config NO_STAGE_CACHE
|
||||||
bool
|
bool
|
||||||
default y if !HAVE_ACPI_RESUME
|
default y if !HAVE_ACPI_RESUME || !RELOCATABLE_RAMSTAGE
|
||||||
help
|
help
|
||||||
Do not save any component in stage cache for resume path. On resume,
|
Do not save any component in stage cache for resume path. On resume,
|
||||||
all components would be read back from CBFS again.
|
all components would be read back from CBFS again.
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Alexander Couzens <lynxis@fe80.eu>
|
* This file is part of the coreboot project.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@@ -33,7 +33,7 @@ _start:
|
|||||||
addi $t0, $t0, 4
|
addi $t0, $t0, 4
|
||||||
|
|
||||||
/* Run main */
|
/* Run main */
|
||||||
b main
|
b mips_main
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Should never return from main. Make sure there is no branch in the
|
* Should never return from main. Make sure there is no branch in the
|
||||||
|
@@ -19,7 +19,10 @@
|
|||||||
#include <halt.h>
|
#include <halt.h>
|
||||||
#include <program_loading.h>
|
#include <program_loading.h>
|
||||||
|
|
||||||
void main(void)
|
/* called from assembly in bootblock.S */
|
||||||
|
void mips_main(void);
|
||||||
|
|
||||||
|
void mips_main(void)
|
||||||
{
|
{
|
||||||
bootblock_cpu_init();
|
bootblock_cpu_init();
|
||||||
|
|
||||||
|
@@ -1,25 +1,20 @@
|
|||||||
config ARCH_PPC64
|
config ARCH_PPC64
|
||||||
bool
|
bool
|
||||||
default n
|
|
||||||
|
|
||||||
config ARCH_BOOTBLOCK_PPC64
|
config ARCH_BOOTBLOCK_PPC64
|
||||||
bool
|
bool
|
||||||
default n
|
|
||||||
select ARCH_PPC64
|
select ARCH_PPC64
|
||||||
select BOOTBLOCK_CUSTOM
|
select BOOTBLOCK_CUSTOM
|
||||||
select C_ENVIRONMENT_BOOTBLOCK
|
select C_ENVIRONMENT_BOOTBLOCK
|
||||||
select ARCH_VERSTAGE_PPC64
|
|
||||||
select ARCH_ROMSTAGE_PPC64
|
|
||||||
select ARCH_RAMSTAGE_PPC64
|
|
||||||
|
|
||||||
config ARCH_VERSTAGE_PPC64
|
config ARCH_VERSTAGE_PPC64
|
||||||
bool
|
bool
|
||||||
default n
|
select ARCH_PPC64
|
||||||
|
|
||||||
config ARCH_ROMSTAGE_PPC64
|
config ARCH_ROMSTAGE_PPC64
|
||||||
bool
|
bool
|
||||||
default n
|
select ARCH_PPC64
|
||||||
|
|
||||||
config ARCH_RAMSTAGE_PPC64
|
config ARCH_RAMSTAGE_PPC64
|
||||||
bool
|
bool
|
||||||
default n
|
select ARCH_PPC64
|
||||||
|
@@ -41,6 +41,30 @@ config ARCH_RISCV_S
|
|||||||
bool
|
bool
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config RISCV_HAS_OPENSBI
|
||||||
|
def_bool n
|
||||||
|
|
||||||
|
config RISCV_OPENSBI
|
||||||
|
bool "Use OpenSBI to hand over control to payload"
|
||||||
|
depends on ARCH_RISCV_M && ARCH_RISCV_S
|
||||||
|
depends on RISCV_HAS_OPENSBI
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Load OpenSBI after payload has been loaded and use it to
|
||||||
|
provide the SBI and to handover control to payload.
|
||||||
|
|
||||||
|
config OPENSBI_PLATFORM
|
||||||
|
string
|
||||||
|
depends on RISCV_HAS_OPENSBI
|
||||||
|
help
|
||||||
|
The OpenSBI platform to build for.
|
||||||
|
|
||||||
|
config OPENSBI_TEXT_START
|
||||||
|
hex
|
||||||
|
depends on RISCV_HAS_OPENSBI
|
||||||
|
help
|
||||||
|
The linking address used to build opensbi.
|
||||||
|
|
||||||
config ARCH_RISCV_U
|
config ARCH_RISCV_U
|
||||||
# U (user) mode is for programs.
|
# U (user) mode is for programs.
|
||||||
bool
|
bool
|
||||||
|
@@ -147,6 +147,7 @@ ramstage-y += boot.c
|
|||||||
ramstage-y += tables.c
|
ramstage-y += tables.c
|
||||||
ramstage-y += payload.c
|
ramstage-y += payload.c
|
||||||
ramstage-$(ARCH_RISCV_PMP) += pmp.c
|
ramstage-$(ARCH_RISCV_PMP) += pmp.c
|
||||||
|
ramstage-y += fit_payload.c
|
||||||
ramstage-y += \
|
ramstage-y += \
|
||||||
$(top)/src/lib/memchr.c \
|
$(top)/src/lib/memchr.c \
|
||||||
$(top)/src/lib/memcmp.c \
|
$(top)/src/lib/memcmp.c \
|
||||||
@@ -174,4 +175,45 @@ LDFLAGS_ramstage += -m elf32lriscv
|
|||||||
endif #CONFIG_ARCH_RISCV_RV32
|
endif #CONFIG_ARCH_RISCV_RV32
|
||||||
|
|
||||||
endif #CONFIG_ARCH_RAMSTAGE_RISCV
|
endif #CONFIG_ARCH_RAMSTAGE_RISCV
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_RISCV_OPENSBI),y)
|
||||||
|
|
||||||
|
OPENSBI_SOURCE := $(top)/3rdparty/opensbi
|
||||||
|
OPENSBI_BUILD := $(abspath $(obj)/3rdparty/opensbi)
|
||||||
|
OPENSBI_TARGET := $(OPENSBI_BUILD)/platform/$(CONFIG_OPENSBI_PLATFORM)/firmware/fw_dynamic.elf
|
||||||
|
OPENSBI := $(obj)/opensbi.elf
|
||||||
|
|
||||||
|
$(OPENSBI_TARGET): $(obj)/config.h | $(OPENSBI_SOURCE)
|
||||||
|
printf " MAKE $(subst $(obj)/,,$(@))\n"
|
||||||
|
mkdir -p $(OPENSBI_BUILD)
|
||||||
|
$(MAKE) \
|
||||||
|
-C "$(OPENSBI_SOURCE)" \
|
||||||
|
CC="$(CC_ramstage)" \
|
||||||
|
LD="$(LD_ramstage)" \
|
||||||
|
OBJCOPY="$(OBJCOPY_ramstage)" \
|
||||||
|
AR="$(AR_ramstage)" \
|
||||||
|
PLATFORM=$(CONFIG_OPENSBI_PLATFORM) \
|
||||||
|
O="$(OPENSBI_BUILD)" \
|
||||||
|
FW_JUMP=y \
|
||||||
|
FW_DYNAMIC=y \
|
||||||
|
FW_PAYLOAD=n \
|
||||||
|
FW_PAYLOAD_OFFSET=0 \
|
||||||
|
FW_TEXT_START=$(CONFIG_OPENSBI_TEXT_START)
|
||||||
|
|
||||||
|
$(OPENSBI): $(OPENSBI_TARGET)
|
||||||
|
cp $< $@
|
||||||
|
|
||||||
|
OPENSBI_CBFS := $(CONFIG_CBFS_PREFIX)/opensbi
|
||||||
|
$(OPENSBI_CBFS)-file := $(OPENSBI)
|
||||||
|
$(OPENSBI_CBFS)-type := payload
|
||||||
|
$(OPENSBI_CBFS)-compression := $(CBFS_COMPRESS_FLAG)
|
||||||
|
cbfs-files-y += $(OPENSBI_CBFS)
|
||||||
|
|
||||||
|
check-ramstage-overlap-files += $(OPENSBI_CBFS)
|
||||||
|
|
||||||
|
CPPFLAGS_common += -I$(OPENSBI_SOURCE)/include
|
||||||
|
ramstage-y += opensbi.c
|
||||||
|
|
||||||
|
endif #CONFIG_RISCV_OPENSBI
|
||||||
|
|
||||||
endif #CONFIG_ARCH_RISCV
|
endif #CONFIG_ARCH_RISCV
|
||||||
|
@@ -20,6 +20,12 @@
|
|||||||
#include <arch/smp/smp.h>
|
#include <arch/smp/smp.h>
|
||||||
#include <mcall.h>
|
#include <mcall.h>
|
||||||
#include <commonlib/cbfs_serialized.h>
|
#include <commonlib/cbfs_serialized.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
|
||||||
|
struct arch_prog_run_args {
|
||||||
|
struct prog *prog;
|
||||||
|
struct prog *opensbi;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A pointer to the Flattened Device Tree passed to coreboot by the boot ROM.
|
* A pointer to the Flattened Device Tree passed to coreboot by the boot ROM.
|
||||||
@@ -28,10 +34,10 @@
|
|||||||
* This pointer is only used in ramstage!
|
* This pointer is only used in ramstage!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void do_arch_prog_run(struct prog *prog)
|
static void do_arch_prog_run(struct arch_prog_run_args *args)
|
||||||
{
|
{
|
||||||
void (*doit)(int hart_id, void *fdt);
|
|
||||||
int hart_id;
|
int hart_id;
|
||||||
|
struct prog *prog = args->prog;
|
||||||
void *fdt = prog_entry_arg(prog);
|
void *fdt = prog_entry_arg(prog);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -48,17 +54,39 @@ static void do_arch_prog_run(struct prog *prog)
|
|||||||
fdt = HLS()->fdt;
|
fdt = HLS()->fdt;
|
||||||
|
|
||||||
if (ENV_RAMSTAGE && prog_type(prog) == PROG_PAYLOAD) {
|
if (ENV_RAMSTAGE && prog_type(prog) == PROG_PAYLOAD) {
|
||||||
|
if (CONFIG(RISCV_OPENSBI))
|
||||||
|
run_payload_opensbi(prog, fdt, args->opensbi, RISCV_PAYLOAD_MODE_S);
|
||||||
|
else
|
||||||
run_payload(prog, fdt, RISCV_PAYLOAD_MODE_S);
|
run_payload(prog, fdt, RISCV_PAYLOAD_MODE_S);
|
||||||
return;
|
} else {
|
||||||
}
|
void (*doit)(int hart_id, void *fdt) = prog_entry(prog);
|
||||||
|
|
||||||
doit = prog_entry(prog);
|
|
||||||
hart_id = HLS()->hart_id;
|
hart_id = HLS()->hart_id;
|
||||||
|
|
||||||
doit(hart_id, fdt);
|
doit(hart_id, fdt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
die("Failed to run stage");
|
||||||
|
}
|
||||||
|
|
||||||
void arch_prog_run(struct prog *prog)
|
void arch_prog_run(struct prog *prog)
|
||||||
{
|
{
|
||||||
smp_resume((void (*)(void *))do_arch_prog_run, prog);
|
struct arch_prog_run_args args = {};
|
||||||
|
|
||||||
|
args.prog = prog;
|
||||||
|
|
||||||
|
/* In case of OpenSBI we have to load it before resuming all HARTs */
|
||||||
|
if (ENV_RAMSTAGE && CONFIG(RISCV_OPENSBI)) {
|
||||||
|
struct prog sbi = PROG_INIT(PROG_OPENSBI, CONFIG_CBFS_PREFIX"/opensbi");
|
||||||
|
|
||||||
|
if (prog_locate(&sbi))
|
||||||
|
die("OpenSBI not found");
|
||||||
|
|
||||||
|
if (!selfload_check(&sbi, BM_MEM_OPENSBI))
|
||||||
|
die("OpenSBI load failed");
|
||||||
|
|
||||||
|
args.opensbi = &sbi;
|
||||||
|
}
|
||||||
|
|
||||||
|
smp_resume((void (*)(void *))do_arch_prog_run, &args);
|
||||||
}
|
}
|
||||||
|
141
src/arch/riscv/fit_payload.c
Normal file
141
src/arch/riscv/fit_payload.c
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
* Copyright 2018 Facebook, Inc.
|
||||||
|
* Copyright 2019 9elements Agency GmbH <patrick.rudolph@9elements.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <bootmem.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <program_loading.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <commonlib/compression.h>
|
||||||
|
#include <commonlib/cbfs_serialized.h>
|
||||||
|
#include <lib.h>
|
||||||
|
#include <fit.h>
|
||||||
|
#include <endian.h>
|
||||||
|
|
||||||
|
/* Implements a Berkley Boot Loader (BBL) compatible payload loading */
|
||||||
|
|
||||||
|
#define MAX_KERNEL_SIZE (64*MiB)
|
||||||
|
|
||||||
|
#if CONFIG(ARCH_RISCV_RV32)
|
||||||
|
#define SECTION_ALIGN (4 * MiB)
|
||||||
|
#endif
|
||||||
|
#if CONFIG(ARCH_RISCV_RV64)
|
||||||
|
#define SECTION_ALIGN (2 * MiB)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static size_t get_kernel_size(const struct fit_image_node *node)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Since we don't have a way to determine the uncompressed size of the
|
||||||
|
* kernel, we have to keep as much memory as possible free for use by
|
||||||
|
* the kernel immediately after the end of the kernel image. The amount
|
||||||
|
* of space required will vary depending on selected features, and is
|
||||||
|
* effectively unbound.
|
||||||
|
*/
|
||||||
|
|
||||||
|
printk(BIOS_INFO,
|
||||||
|
"FIT: Leaving additional %u MiB of free space after kernel.\n",
|
||||||
|
MAX_KERNEL_SIZE >> 20);
|
||||||
|
|
||||||
|
return node->size + MAX_KERNEL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place the region in free memory range.
|
||||||
|
*
|
||||||
|
* The caller has to set region->offset to the minimum allowed address.
|
||||||
|
*/
|
||||||
|
static bool fit_place_mem(const struct range_entry *r, void *arg)
|
||||||
|
{
|
||||||
|
struct region *region = arg;
|
||||||
|
resource_t start;
|
||||||
|
|
||||||
|
if (range_entry_tag(r) != BM_MEM_RAM)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Section must be aligned at page boundary */
|
||||||
|
start = ALIGN_UP(MAX(region->offset, range_entry_base(r)), SECTION_ALIGN);
|
||||||
|
|
||||||
|
if (start + region->size < range_entry_end(r)) {
|
||||||
|
region->offset = (size_t)start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fit_payload_arch(struct prog *payload, struct fit_config_node *config,
|
||||||
|
struct region *kernel,
|
||||||
|
struct region *fdt,
|
||||||
|
struct region *initrd)
|
||||||
|
{
|
||||||
|
void *arg = NULL;
|
||||||
|
|
||||||
|
if (!config->fdt || !fdt) {
|
||||||
|
printk(BIOS_CRIT, "CRIT: Providing a valid FDT is mandatory to "
|
||||||
|
"boot a RISC-V kernel!\n");
|
||||||
|
return false;
|
||||||
|
/* TODO: Fall back to the ROM FDT? */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update kernel size from image header, if possible */
|
||||||
|
kernel->size = get_kernel_size(config->kernel);
|
||||||
|
printk(BIOS_DEBUG, "FIT: Using kernel size of 0x%zx bytes\n",
|
||||||
|
kernel->size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code assumes that bootmem_walk provides a sorted list of memory
|
||||||
|
* regions, starting from the lowest address.
|
||||||
|
* The order of the calls here doesn't matter, as the placement is
|
||||||
|
* enforced in the called functions.
|
||||||
|
* For details check code on top.
|
||||||
|
*/
|
||||||
|
kernel->offset = 0;
|
||||||
|
if (!bootmem_walk(fit_place_mem, kernel))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Mark as reserved for future allocations. */
|
||||||
|
bootmem_add_range(kernel->offset, kernel->size, BM_MEM_PAYLOAD);
|
||||||
|
|
||||||
|
/* Place FDT and INITRD after kernel. */
|
||||||
|
|
||||||
|
/* Place INITRD */
|
||||||
|
if (config->ramdisk) {
|
||||||
|
initrd->offset = kernel->offset + kernel->size;
|
||||||
|
|
||||||
|
if (!bootmem_walk(fit_place_mem, initrd))
|
||||||
|
return false;
|
||||||
|
/* Mark as reserved for future allocations. */
|
||||||
|
bootmem_add_range(initrd->offset, initrd->size, BM_MEM_PAYLOAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Place FDT */
|
||||||
|
fdt->offset = kernel->offset + kernel->size;
|
||||||
|
|
||||||
|
if (!bootmem_walk(fit_place_mem, fdt))
|
||||||
|
return false;
|
||||||
|
/* Mark as reserved for future allocations. */
|
||||||
|
bootmem_add_range(fdt->offset, fdt->size, BM_MEM_PAYLOAD);
|
||||||
|
|
||||||
|
/* Kernel expects FDT as argument */
|
||||||
|
arg = (void *)fdt->offset;
|
||||||
|
|
||||||
|
prog_set_entry(payload, (void *)kernel->offset, arg);
|
||||||
|
|
||||||
|
bootmem_dump_ranges();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@@ -16,12 +16,17 @@
|
|||||||
#ifndef ARCH_RISCV_INCLUDE_ARCH_BOOT_H
|
#ifndef ARCH_RISCV_INCLUDE_ARCH_BOOT_H
|
||||||
#define ARCH_RISCV_INCLUDE_ARCH_BOOT_H
|
#define ARCH_RISCV_INCLUDE_ARCH_BOOT_H
|
||||||
|
|
||||||
#include <program_loading.h>
|
|
||||||
|
|
||||||
#define RISCV_PAYLOAD_MODE_U 0
|
#define RISCV_PAYLOAD_MODE_U 0
|
||||||
#define RISCV_PAYLOAD_MODE_S 1
|
#define RISCV_PAYLOAD_MODE_S 1
|
||||||
#define RISCV_PAYLOAD_MODE_M 3
|
#define RISCV_PAYLOAD_MODE_M 3
|
||||||
|
|
||||||
|
struct prog;
|
||||||
void run_payload(struct prog *prog, void *fdt, int payload_mode);
|
void run_payload(struct prog *prog, void *fdt, int payload_mode);
|
||||||
|
void run_payload_opensbi(struct prog *prog, void *fdt, struct prog *opensbi, int payload_mode);
|
||||||
|
|
||||||
|
void run_opensbi(const int hart_id,
|
||||||
|
const void *opensbi,
|
||||||
|
const void *fdt,
|
||||||
|
const void *payload,
|
||||||
|
const int payload_mode);
|
||||||
#endif
|
#endif
|
||||||
|
41
src/arch/riscv/opensbi.c
Normal file
41
src/arch/riscv/opensbi.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 9elements Agency GmbH <patrick.rudolph@9elements.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/fw_dynamic.h>
|
||||||
|
#include <arch/boot.h>
|
||||||
|
/* DO NOT INLCUDE COREBOOT HEADERS HERE */
|
||||||
|
|
||||||
|
void run_opensbi(const int hart_id,
|
||||||
|
const void *fdt,
|
||||||
|
const void *opensbi,
|
||||||
|
const void *payload,
|
||||||
|
const int payload_mode)
|
||||||
|
{
|
||||||
|
struct fw_dynamic_info info = {
|
||||||
|
.magic = FW_DYNAMIC_INFO_MAGIC_VALUE,
|
||||||
|
.version = FW_DYNAMIC_INFO_VERSION_MAX,
|
||||||
|
.next_mode = payload_mode,
|
||||||
|
.next_addr = (uintptr_t)payload,
|
||||||
|
};
|
||||||
|
|
||||||
|
csr_write(mepc, opensbi);
|
||||||
|
asm volatile (
|
||||||
|
"mv a0, %0\n\t"
|
||||||
|
"mv a1, %1\n\t"
|
||||||
|
"mv a2, %2\n\t"
|
||||||
|
"mret" :
|
||||||
|
: "r"(hart_id), "r"(fdt), "r"(&info)
|
||||||
|
: "a0", "a1", "a2");
|
||||||
|
}
|
@@ -15,18 +15,44 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <program_loading.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <arch/boot.h>
|
#include <arch/boot.h>
|
||||||
#include <arch/encoding.h>
|
#include <arch/encoding.h>
|
||||||
|
#include <arch/smp/atomic.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
|
|
||||||
|
/* Run OpenSBI and let OpenSBI hand over control to the payload */
|
||||||
|
void run_payload_opensbi(struct prog *prog, void *fdt, struct prog *opensbi, int payload_mode)
|
||||||
|
{
|
||||||
|
int hart_id = read_csr(mhartid);
|
||||||
|
uintptr_t status = read_csr(mstatus);
|
||||||
|
status = INSERT_FIELD(status, MSTATUS_MPIE, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case of OpenSBI we always run it in M-Mode.
|
||||||
|
* OpenSBI will switch to payload_mode when done.
|
||||||
|
*/
|
||||||
|
|
||||||
|
status = INSERT_FIELD(status, MSTATUS_MPP, PRV_M);
|
||||||
|
/* Trap vector base address point to the payload */
|
||||||
|
write_csr(mtvec, prog_entry(opensbi));
|
||||||
|
/* disable M-Mode interrupt */
|
||||||
|
write_csr(mie, 0);
|
||||||
|
write_csr(mstatus, status);
|
||||||
|
|
||||||
|
run_opensbi(hart_id, fdt, prog_entry(opensbi), prog_entry(prog), payload_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Runs the payload without OpenSBI integration */
|
||||||
void run_payload(struct prog *prog, void *fdt, int payload_mode)
|
void run_payload(struct prog *prog, void *fdt, int payload_mode)
|
||||||
{
|
{
|
||||||
void (*doit)(int hart_id, void *fdt) = prog_entry(prog);
|
void (*doit)(int hart_id, void *fdt) = prog_entry(prog);
|
||||||
int hart_id = read_csr(mhartid);
|
int hart_id = read_csr(mhartid);
|
||||||
uintptr_t status = read_csr(mstatus);
|
uintptr_t status = read_csr(mstatus);
|
||||||
status = INSERT_FIELD(status, MSTATUS_MPIE, 0);
|
status = INSERT_FIELD(status, MSTATUS_MPIE, 0);
|
||||||
|
|
||||||
switch (payload_mode) {
|
switch (payload_mode) {
|
||||||
case RISCV_PAYLOAD_MODE_U:
|
case RISCV_PAYLOAD_MODE_U:
|
||||||
status = INSERT_FIELD(status, MSTATUS_MPP, PRV_U);
|
status = INSERT_FIELD(status, MSTATUS_MPP, PRV_U);
|
||||||
|
@@ -24,8 +24,6 @@
|
|||||||
* linker script.
|
* linker script.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arch/boot.h>
|
|
||||||
#include <arch/encoding.h>
|
|
||||||
#include <arch/stages.h>
|
#include <arch/stages.h>
|
||||||
#include <arch/smp/smp.h>
|
#include <arch/smp/smp.h>
|
||||||
#include <rules.h>
|
#include <rules.h>
|
||||||
|
@@ -18,6 +18,9 @@
|
|||||||
#include <bootmem.h>
|
#include <bootmem.h>
|
||||||
#include <boot/tables.h>
|
#include <boot/tables.h>
|
||||||
#include <boot/coreboot_tables.h>
|
#include <boot/coreboot_tables.h>
|
||||||
|
#include <symbols.h>
|
||||||
|
|
||||||
|
DECLARE_OPTIONAL_REGION(opensbi);
|
||||||
|
|
||||||
void arch_write_tables(uintptr_t coreboot_table)
|
void arch_write_tables(uintptr_t coreboot_table)
|
||||||
{
|
{
|
||||||
@@ -25,6 +28,9 @@ void arch_write_tables(uintptr_t coreboot_table)
|
|||||||
|
|
||||||
void bootmem_arch_add_ranges(void)
|
void bootmem_arch_add_ranges(void)
|
||||||
{
|
{
|
||||||
|
if (CONFIG(RISCV_OPENSBI) && REGION_SIZE(opensbi) > 0)
|
||||||
|
bootmem_add_range((uintptr_t)_opensbi, REGION_SIZE(opensbi),
|
||||||
|
BM_MEM_OPENSBI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lb_arch_add_records(struct lb_header *header)
|
void lb_arch_add_records(struct lb_header *header)
|
||||||
|
@@ -386,10 +386,15 @@ static void acpi_create_tpm2(acpi_tpm2_t *tpm2)
|
|||||||
|
|
||||||
/* Hard to detect for coreboot. Just set it to 0 */
|
/* Hard to detect for coreboot. Just set it to 0 */
|
||||||
tpm2->platform_class = 0;
|
tpm2->platform_class = 0;
|
||||||
/* Must be set to 0 for TIS interface support */
|
if (CONFIG(CRB_TPM)) {
|
||||||
|
/* Must be set to 7 for CRB Support */
|
||||||
|
tpm2->control_area = CONFIG_CRB_TPM_BASE_ADDRESS + 0x40;
|
||||||
|
tpm2->start_method = 7;
|
||||||
|
} else {
|
||||||
|
/* Must be set to 0 for FIFO interface support */
|
||||||
tpm2->control_area = 0;
|
tpm2->control_area = 0;
|
||||||
/* coreboot only supports the TIS interface driver. */
|
|
||||||
tpm2->start_method = 6;
|
tpm2->start_method = 6;
|
||||||
|
}
|
||||||
memset(tpm2->msp, 0, sizeof(tpm2->msp));
|
memset(tpm2->msp, 0, sizeof(tpm2->msp));
|
||||||
|
|
||||||
/* Fill the log area size and start address fields. */
|
/* Fill the log area size and start address fields. */
|
||||||
@@ -946,7 +951,7 @@ void acpi_create_dbg2(acpi_dbg2_header_t *dbg2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
|
unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
|
||||||
struct device *dev, uint8_t access_size)
|
const struct device *dev, uint8_t access_size)
|
||||||
{
|
{
|
||||||
acpi_dbg2_header_t *dbg2 = (acpi_dbg2_header_t *)current;
|
acpi_dbg2_header_t *dbg2 = (acpi_dbg2_header_t *)current;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
@@ -53,9 +53,9 @@ static void acpi_device_fill_len(void *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Locate and return the ACPI name for this device */
|
/* Locate and return the ACPI name for this device */
|
||||||
const char *acpi_device_name(struct device *dev)
|
const char *acpi_device_name(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct device *pdev = dev;
|
const struct device *pdev = dev;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
@@ -82,7 +82,7 @@ const char *acpi_device_name(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Recursive function to find the root device and print a path from there */
|
/* Recursive function to find the root device and print a path from there */
|
||||||
static ssize_t acpi_device_path_fill(struct device *dev, char *buf,
|
static ssize_t acpi_device_path_fill(const struct device *dev, char *buf,
|
||||||
size_t buf_len, size_t cur)
|
size_t buf_len, size_t cur)
|
||||||
{
|
{
|
||||||
const char *name = acpi_device_name(dev);
|
const char *name = acpi_device_name(dev);
|
||||||
@@ -117,7 +117,7 @@ static ssize_t acpi_device_path_fill(struct device *dev, char *buf,
|
|||||||
* Warning: just as with dev_path() this uses a static buffer
|
* Warning: just as with dev_path() this uses a static buffer
|
||||||
* so should not be called mulitple times in one statement
|
* so should not be called mulitple times in one statement
|
||||||
*/
|
*/
|
||||||
const char *acpi_device_path(struct device *dev)
|
const char *acpi_device_path(const struct device *dev)
|
||||||
{
|
{
|
||||||
static char buf[DEVICE_PATH_MAX] = {};
|
static char buf[DEVICE_PATH_MAX] = {};
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ const char *acpi_device_path(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the path of the parent device as the ACPI Scope for this device */
|
/* Return the path of the parent device as the ACPI Scope for this device */
|
||||||
const char *acpi_device_scope(struct device *dev)
|
const char *acpi_device_scope(const struct device *dev)
|
||||||
{
|
{
|
||||||
static char buf[DEVICE_PATH_MAX] = {};
|
static char buf[DEVICE_PATH_MAX] = {};
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ const char *acpi_device_scope(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Concatentate the device path and provided name suffix */
|
/* Concatentate the device path and provided name suffix */
|
||||||
const char *acpi_device_path_join(struct device *dev, const char *name)
|
const char *acpi_device_path_join(const struct device *dev, const char *name)
|
||||||
{
|
{
|
||||||
static char buf[DEVICE_PATH_MAX] = {};
|
static char buf[DEVICE_PATH_MAX] = {};
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
@@ -901,7 +901,7 @@ void acpi_create_dbg2(acpi_dbg2_header_t *dbg2_header,
|
|||||||
const char *device_path);
|
const char *device_path);
|
||||||
|
|
||||||
unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
|
unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
|
||||||
struct device *dev, uint8_t access_size);
|
const struct device *dev, uint8_t access_size);
|
||||||
void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
|
void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
|
||||||
unsigned long (*acpi_fill_dmar)(unsigned long));
|
unsigned long (*acpi_fill_dmar)(unsigned long));
|
||||||
unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
|
unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
|
||||||
|
@@ -62,10 +62,10 @@ struct acpi_dp {
|
|||||||
#define ACPI_DT_NAMESPACE_HID "PRP0001"
|
#define ACPI_DT_NAMESPACE_HID "PRP0001"
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
const char *acpi_device_name(struct device *dev);
|
const char *acpi_device_name(const struct device *dev);
|
||||||
const char *acpi_device_path(struct device *dev);
|
const char *acpi_device_path(const struct device *dev);
|
||||||
const char *acpi_device_scope(struct device *dev);
|
const char *acpi_device_scope(const struct device *dev);
|
||||||
const char *acpi_device_path_join(struct device *dev, const char *name);
|
const char *acpi_device_path_join(const struct device *dev, const char *name);
|
||||||
int acpi_device_status(const struct device *dev);
|
int acpi_device_status(const struct device *dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -500,6 +500,11 @@ smbios_board_type __weak smbios_mainboard_board_type(void)
|
|||||||
return SMBIOS_BOARD_TYPE_UNKNOWN;
|
return SMBIOS_BOARD_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 __weak smbios_mainboard_enclosure_type(void)
|
||||||
|
{
|
||||||
|
return CONFIG_SMBIOS_ENCLOSURE_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
const char *__weak smbios_system_serial_number(void)
|
const char *__weak smbios_system_serial_number(void)
|
||||||
{
|
{
|
||||||
return smbios_mainboard_serial_number();
|
return smbios_mainboard_serial_number();
|
||||||
@@ -620,7 +625,7 @@ static int smbios_write_type3(unsigned long *current, int handle)
|
|||||||
t->bootup_state = SMBIOS_STATE_SAFE;
|
t->bootup_state = SMBIOS_STATE_SAFE;
|
||||||
t->power_supply_state = SMBIOS_STATE_SAFE;
|
t->power_supply_state = SMBIOS_STATE_SAFE;
|
||||||
t->thermal_state = SMBIOS_STATE_SAFE;
|
t->thermal_state = SMBIOS_STATE_SAFE;
|
||||||
t->_type = CONFIG_SMBIOS_ENCLOSURE_TYPE;
|
t->_type = smbios_mainboard_enclosure_type();
|
||||||
t->security_status = SMBIOS_STATE_SAFE;
|
t->security_status = SMBIOS_STATE_SAFE;
|
||||||
len = t->length + smbios_string_table_len(t->eos);
|
len = t->length + smbios_string_table_len(t->eos);
|
||||||
*current += len;
|
*current += len;
|
||||||
|
@@ -68,7 +68,7 @@
|
|||||||
#define CBMEM_ID_TCPA_TCG_LOG 0x54445041
|
#define CBMEM_ID_TCPA_TCG_LOG 0x54445041
|
||||||
#define CBMEM_ID_TIMESTAMP 0x54494d45
|
#define CBMEM_ID_TIMESTAMP 0x54494d45
|
||||||
#define CBMEM_ID_TPM2_TCG_LOG 0x54504d32
|
#define CBMEM_ID_TPM2_TCG_LOG 0x54504d32
|
||||||
#define CBMEM_ID_VBOOT_HANDOFF 0x780074f0
|
#define CBMEM_ID_VBOOT_HANDOFF 0x780074f0 /* deprecated */
|
||||||
#define CBMEM_ID_VBOOT_SEL_REG 0x780074f1 /* deprecated */
|
#define CBMEM_ID_VBOOT_SEL_REG 0x780074f1 /* deprecated */
|
||||||
#define CBMEM_ID_VBOOT_WORKBUF 0x78007343
|
#define CBMEM_ID_VBOOT_WORKBUF 0x78007343
|
||||||
#define CBMEM_ID_VPD 0x56504420
|
#define CBMEM_ID_VPD 0x56504420
|
||||||
|
@@ -68,7 +68,7 @@ enum {
|
|||||||
LB_TAG_CBMEM_CONSOLE = 0x0017,
|
LB_TAG_CBMEM_CONSOLE = 0x0017,
|
||||||
LB_TAG_MRC_CACHE = 0x0018,
|
LB_TAG_MRC_CACHE = 0x0018,
|
||||||
LB_TAG_VBNV = 0x0019,
|
LB_TAG_VBNV = 0x0019,
|
||||||
LB_TAG_VBOOT_HANDOFF = 0x0020,
|
LB_TAG_VBOOT_HANDOFF = 0x0020, /* deprecated */
|
||||||
LB_TAG_X86_ROM_MTRR = 0x0021,
|
LB_TAG_X86_ROM_MTRR = 0x0021,
|
||||||
LB_TAG_DMA = 0x0022,
|
LB_TAG_DMA = 0x0022,
|
||||||
LB_TAG_RAM_OOPS = 0x0023,
|
LB_TAG_RAM_OOPS = 0x0023,
|
||||||
@@ -283,6 +283,18 @@ struct lb_forward {
|
|||||||
* fields described above. It may, however, only implement a subset
|
* fields described above. It may, however, only implement a subset
|
||||||
* of the possible color formats.
|
* of the possible color formats.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Framebuffer orientation, matches drm_connector.h drm_panel_orientation in the
|
||||||
|
* Linux kernel.
|
||||||
|
*/
|
||||||
|
enum lb_fb_orientation {
|
||||||
|
LB_FB_ORIENTATION_NORMAL = 0,
|
||||||
|
LB_FB_ORIENTATION_BOTTOM_UP = 1,
|
||||||
|
LB_FB_ORIENTATION_LEFT_UP = 2,
|
||||||
|
LB_FB_ORIENTATION_RIGHT_UP = 3,
|
||||||
|
};
|
||||||
|
|
||||||
struct lb_framebuffer {
|
struct lb_framebuffer {
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@@ -300,6 +312,7 @@ struct lb_framebuffer {
|
|||||||
uint8_t blue_mask_size;
|
uint8_t blue_mask_size;
|
||||||
uint8_t reserved_mask_pos;
|
uint8_t reserved_mask_pos;
|
||||||
uint8_t reserved_mask_size;
|
uint8_t reserved_mask_size;
|
||||||
|
uint8_t orientation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -271,6 +271,7 @@ repeat:
|
|||||||
|
|
||||||
case 'X':
|
case 'X':
|
||||||
flags |= LARGE;
|
flags |= LARGE;
|
||||||
|
/* fall through */
|
||||||
case 'x':
|
case 'x':
|
||||||
base = 16;
|
base = 16;
|
||||||
break;
|
break;
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
source src/cpu/allwinner/a10/Kconfig
|
|
@@ -1 +0,0 @@
|
|||||||
subdirs-$(CONFIG_CPU_ALLWINNER_A10) += a10
|
|
@@ -1,18 +0,0 @@
|
|||||||
config CPU_ALLWINNER_A10
|
|
||||||
bool
|
|
||||||
default n
|
|
||||||
|
|
||||||
if CPU_ALLWINNER_A10
|
|
||||||
|
|
||||||
config CPU_SPECIFIC_OPTIONS
|
|
||||||
def_bool y
|
|
||||||
select ARCH_BOOTBLOCK_ARMV7
|
|
||||||
select ARCH_VERSTAGE_ARMV7
|
|
||||||
select ARCH_ROMSTAGE_ARMV7
|
|
||||||
select ARCH_RAMSTAGE_ARMV7
|
|
||||||
select NO_MONOTONIC_TIMER
|
|
||||||
select HAVE_UART_SPECIAL
|
|
||||||
select UART_OVERRIDE_REFCLK
|
|
||||||
select BOOT_DEVICE_NOT_SPI_FLASH
|
|
||||||
|
|
||||||
endif # if CPU_ALLWINNER_A10
|
|
@@ -1,55 +0,0 @@
|
|||||||
bootblock-y += bootblock.c
|
|
||||||
bootblock-y += bootblock_media.c
|
|
||||||
bootblock-y += clock.c
|
|
||||||
bootblock-y += gpio.c
|
|
||||||
bootblock-y += pinmux.c
|
|
||||||
bootblock-y += raminit.c
|
|
||||||
bootblock-y += timer.c
|
|
||||||
|
|
||||||
romstage-y += bootblock_media.c
|
|
||||||
romstage-y += cbmem.c
|
|
||||||
romstage-y += clock.c
|
|
||||||
romstage-y += pinmux.c
|
|
||||||
romstage-y += timer.c
|
|
||||||
romstage-y += twi.c
|
|
||||||
|
|
||||||
ramstage-y += bootblock_media.c
|
|
||||||
ramstage-y += cbmem.c
|
|
||||||
ramstage-y += clock.c
|
|
||||||
ramstage-y += cpu.c
|
|
||||||
ramstage-y += timer.c
|
|
||||||
ramstage-y += twi.c
|
|
||||||
|
|
||||||
bootblock-y += uart.c uart_console.c
|
|
||||||
romstage-y += uart.c uart_console.c
|
|
||||||
ramstage-y += uart.c uart_console.c
|
|
||||||
|
|
||||||
real-target: $(obj)/BOOT0
|
|
||||||
|
|
||||||
get_bootblock_size= \
|
|
||||||
$(eval bb_s=$(shell $(CBFSTOOL) $(1) print | grep bootblocksize | \
|
|
||||||
sed 's/[^0-9 ]//g')) \
|
|
||||||
$(shell echo $$(($(word 2, $(strip $(bb_s))))))
|
|
||||||
|
|
||||||
# This tool is used to prepend a header to coreboot.rom to trick the SoC into
|
|
||||||
# loading out bootblock
|
|
||||||
#
|
|
||||||
MKSUNXIBOOT:=$(objutil)/mksunxiboot
|
|
||||||
$(MKSUNXIBOOT): $(top)/util/arm_boot_tools/mksunxiboot/mksunxiboot.c
|
|
||||||
@printf " HOSTCC $(subst $(obj)/,,$(@))\n"
|
|
||||||
$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
|
|
||||||
|
|
||||||
# The boot ROM in the SoC will start loading code if a special BOOT0 header is
|
|
||||||
# found (at an offset of 8KiB in either NAND or SD), and the checksum is
|
|
||||||
# correct. This header is added by the 'mxsunxiboot' tool, which is provided
|
|
||||||
# under util/arm_boot_tools/mksunxiboot. The boot ROM will load at most 24KiB of
|
|
||||||
# data to SRAM. The BOOT0 header takes 32 bytes, so bootblock is limited to
|
|
||||||
# 24KiB - 32 bytes.
|
|
||||||
# TODO: make mksunxiboot take the bootblock size as a parameter
|
|
||||||
# TODO: print an error if bootblock is too large (maybe place ROMSTAGE at the
|
|
||||||
# exact offset needed to collide with the bootblock)
|
|
||||||
# FIXME: A10 loads 24KiB. According to Oliver other chips load a little more
|
|
||||||
#
|
|
||||||
$(obj)/BOOT0: $(obj)/coreboot.rom $(MKSUNXIBOOT)
|
|
||||||
@printf " BOOT0 $(subst $(obj)/,,$(^))\n"
|
|
||||||
$(MKSUNXIBOOT) $(word 1, $^) $@
|
|
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Google Inc.
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Allwinner A10 bootblock initialization
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
#include <arch/cache.h>
|
|
||||||
#include <bootblock_common.h>
|
|
||||||
|
|
||||||
void bootblock_soc_init(void)
|
|
||||||
{
|
|
||||||
uint32_t sctlr;
|
|
||||||
|
|
||||||
/* enable dcache */
|
|
||||||
sctlr = read_sctlr();
|
|
||||||
sctlr |= SCTLR_C;
|
|
||||||
write_sctlr(sctlr);
|
|
||||||
}
|
|
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* CBFS accessors for bootblock stage.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include <boot_device.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
|
|
||||||
const struct region_device *boot_device_ro(void)
|
|
||||||
{
|
|
||||||
printk(BIOS_ERR, "Oh my! I don't know how to access CBFS yet.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Provides cbmem utilities for romstage and ramstage
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ram_segs.h"
|
|
||||||
#include <cbmem.h>
|
|
||||||
|
|
||||||
void *cbmem_top(void)
|
|
||||||
{
|
|
||||||
return a1x_get_cbmem_top();
|
|
||||||
}
|
|
@@ -1,283 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Helpers for clock control and gating on Allwinner CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clock.h"
|
|
||||||
|
|
||||||
#include <device/mmio.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
#include <delay.h>
|
|
||||||
#include <lib.h>
|
|
||||||
|
|
||||||
static struct a10_ccm *const ccm = (void *)A1X_CCM_BASE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Enable the clock source for the peripheral
|
|
||||||
*
|
|
||||||
* @param[in] periph peripheral and clock type to enable @see a1x_clken
|
|
||||||
*/
|
|
||||||
void a1x_periph_clock_enable(enum a1x_clken periph)
|
|
||||||
{
|
|
||||||
void *addr;
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
addr = (void *)A1X_CCM_BASE + (periph >> 5);
|
|
||||||
reg32 = read32(addr);
|
|
||||||
reg32 |= 1 << (periph & 0x1f);
|
|
||||||
write32(addr, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Disable the clock source for the peripheral
|
|
||||||
*
|
|
||||||
* @param[in] periph peripheral and clock type to disable @see a1x_clken
|
|
||||||
*/
|
|
||||||
void a1x_periph_clock_disable(enum a1x_clken periph)
|
|
||||||
{
|
|
||||||
void *addr;
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
addr = (void *)A1X_CCM_BASE + (periph >> 5);
|
|
||||||
reg32 = read32(addr);
|
|
||||||
reg32 &= ~(1 << (periph & 0x1f));
|
|
||||||
write32(addr, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Configure PLL5 factors
|
|
||||||
*
|
|
||||||
* This is a low-level accessor to configure the divisors and multipliers of
|
|
||||||
* PLL5. PLL5 uses two factors to multiply the 24MHz oscillator clock to
|
|
||||||
* generate a pre-clock. The pre-divided clock is then divided by one of two
|
|
||||||
* independent divisors, one for DRAM, and another for peripherals clocked from
|
|
||||||
* this PLL. If the PLL was previously disabled, this function will enable it.
|
|
||||||
* Other than that, this function only modifies these factors, and leaves the
|
|
||||||
* other settings unchanged.
|
|
||||||
*
|
|
||||||
* The output clocks are given by the following formulas:
|
|
||||||
*
|
|
||||||
* Pre-clock = (24 MHz * N * K) <- Must be between 240MHz and 2GHz
|
|
||||||
* DRAM clock = pre / M
|
|
||||||
* Other module = pre / P
|
|
||||||
*
|
|
||||||
* It is the caller's responsibility to make sure the pre-divided clock falls
|
|
||||||
* within the operational range of the PLL, and that the divisors and
|
|
||||||
* multipliers are within their ranges.
|
|
||||||
*
|
|
||||||
* @param[in] mul_n Multiplier N, between 0 and 32
|
|
||||||
* @param[in] mul_k Multiplier K, between 1 and 4
|
|
||||||
* @param[in] div_m DRAM clock divisor, between 1 and 4
|
|
||||||
* @param[in] exp_div_p Peripheral clock divisor exponent, between 0 and 3
|
|
||||||
* (P = 1/2/4/8, respectively)
|
|
||||||
*/
|
|
||||||
void a1x_pll5_configure(u8 mul_n, u8 mul_k, u8 div_m, u8 exp_div_p)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
reg32 = read32(&ccm->pll5_cfg);
|
|
||||||
reg32 &= ~(PLL5_FACTOR_M_MASK | PLL5_FACTOR_N_MASK |
|
|
||||||
PLL5_FACTOR_K_MASK | PLL5_DIV_EXP_P_MASK);
|
|
||||||
/* The M1 factor is not documented in the datasheet, and the reference
|
|
||||||
* raminit code does not use it. Whether this is a fractional divisor,
|
|
||||||
* or an additional divisor is unknown, so don't use it for now */
|
|
||||||
reg32 &= ~PLL5_FACTOR_M1_MASK;
|
|
||||||
reg32 |= (PLL5_FACTOR_M(div_m) | PLL5_FACTOR_N(mul_n) |
|
|
||||||
PLL5_FACTOR_K(mul_k) | PLL5_DIV_EXP_P(exp_div_p));
|
|
||||||
reg32 |= PLL5_PLL_ENABLE;
|
|
||||||
write32(&ccm->pll5_cfg, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Enable the clock output to DRAM chips
|
|
||||||
*
|
|
||||||
* This enables the DRAM clock to be sent to DRAM chips. This should normally be
|
|
||||||
* done after PLL5 is configured and locked. Note that the clock may be gated,
|
|
||||||
* and also needs to be ungated in order to reach the DDR chips.
|
|
||||||
* Also see @ref clock_ungate_dram_clk_output
|
|
||||||
*/
|
|
||||||
void a1x_pll5_enable_dram_clock_output(void)
|
|
||||||
{
|
|
||||||
setbits_le32(&ccm->pll5_cfg, PLL5_DDR_CLK_OUT_EN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Ungate the clock to DRAM chips
|
|
||||||
*
|
|
||||||
* Although the DRAM clock output may be enabled, it is by default gated. It
|
|
||||||
* needs to be ungated before reaching DRAM.
|
|
||||||
*/
|
|
||||||
void a1x_ungate_dram_clock_output(void)
|
|
||||||
{
|
|
||||||
setbits_le32(&ccm->dram_clk_cfg, DRAM_CTRL_DCLK_OUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Gate the clock to DRAM chips
|
|
||||||
*
|
|
||||||
* Disable the clock to DRAM without altering PLL configuration, by closing the
|
|
||||||
* DRAM clock gate.
|
|
||||||
*/
|
|
||||||
void a1x_gate_dram_clock_output(void)
|
|
||||||
{
|
|
||||||
clrbits_le32(&ccm->dram_clk_cfg, DRAM_CTRL_DCLK_OUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Linker doesn't garbage collect and the function below adds about half
|
|
||||||
* kilobyte to the bootblock, and log2_ceil is not available in the bootblock.
|
|
||||||
*/
|
|
||||||
#ifndef __BOOTBLOCK__
|
|
||||||
|
|
||||||
#define PLL1_CFG(N, K, M, P_EXP) \
|
|
||||||
((1 << 31 | 0 << 30 | 8 << 26 | 0 << 25 | 16 << 20 | 2 << 13) | \
|
|
||||||
(P_EXP) << 16 | (N) << 8 | \
|
|
||||||
(K - 1) << 4 | 0 << 3 | 0 << 2 | (M -1) << 0)
|
|
||||||
|
|
||||||
static const struct {
|
|
||||||
u32 pll1_cfg;
|
|
||||||
u16 freq_mhz;
|
|
||||||
} pll1_table[] = {
|
|
||||||
/* PLL1 output = (24MHz * N * K) / (M * P) */
|
|
||||||
{ PLL1_CFG(16, 1, 1, 0), 384 },
|
|
||||||
{ PLL1_CFG(16, 2, 1, 0), 768 },
|
|
||||||
{ PLL1_CFG(20, 2, 1, 0), 960 },
|
|
||||||
{ PLL1_CFG(21, 2, 1, 0), 1008 },
|
|
||||||
{ PLL1_CFG(22, 2, 1, 0), 1056 },
|
|
||||||
{ PLL1_CFG(23, 2, 1, 0), 1104 },
|
|
||||||
{ PLL1_CFG(24, 2, 1, 0), 1152 },
|
|
||||||
{ PLL1_CFG(25, 2, 1, 0), 1200 },
|
|
||||||
{ PLL1_CFG(26, 2, 1, 0), 1248 },
|
|
||||||
{ PLL1_CFG(27, 2, 1, 0), 1296 },
|
|
||||||
{ PLL1_CFG(28, 2, 1, 0), 1344 },
|
|
||||||
{ PLL1_CFG(29, 2, 1, 0), 1392 },
|
|
||||||
{ PLL1_CFG(30, 2, 1, 0), 1440 },
|
|
||||||
{ PLL1_CFG(31, 2, 1, 0), 1488 },
|
|
||||||
{ PLL1_CFG(20, 4, 1, 0), 1944 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static void cpu_clk_src_switch(u32 clksel_bits)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
reg32 = read32(&ccm->cpu_ahb_apb0_cfg);
|
|
||||||
reg32 &= ~CPU_CLK_SRC_MASK;
|
|
||||||
reg32 |= clksel_bits & CPU_CLK_SRC_MASK;
|
|
||||||
write32(&ccm->cpu_ahb_apb0_cfg, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void change_sys_divisors(u8 axi, u8 ahb_exp, u8 apb0_exp)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
reg32 = read32(&ccm->cpu_ahb_apb0_cfg);
|
|
||||||
/* Not a typo: We want to keep only the CLK_SRC bits */
|
|
||||||
reg32 &= CPU_CLK_SRC_MASK;
|
|
||||||
reg32 |= ((axi - 1) << 0) & AXI_DIV_MASK;
|
|
||||||
reg32 |= (ahb_exp << 4) & AHB_DIV_MASK;
|
|
||||||
reg32 |= (apb0_exp << 8) & APB0_DIV_MASK;
|
|
||||||
write32(&ccm->cpu_ahb_apb0_cfg, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spin_delay(u32 loops)
|
|
||||||
{
|
|
||||||
volatile u32 x = loops;
|
|
||||||
while (x--);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Configure the CPU clock and PLL1
|
|
||||||
*
|
|
||||||
* To run at full speed, the CPU uses PLL1 as the clock source. AXI, AHB, and
|
|
||||||
* APB0 are derived from the CPU clock, and need to be kept within certain
|
|
||||||
* limits. This function configures PLL1 as close as possible to the desired
|
|
||||||
* frequency, based on a set of known working configurations for PLL1. It then
|
|
||||||
* calculates and applies the appropriate divisors for the AXI/AHB/APB0 clocks,
|
|
||||||
* before finally switching the CPU to run from the new clock.
|
|
||||||
* No further configuration of the CPU clock or divisors is needed. after
|
|
||||||
* calling this function.
|
|
||||||
*
|
|
||||||
* @param[in] cpu_clk_mhz Desired CPU clock, in MHz
|
|
||||||
*/
|
|
||||||
void a1x_set_cpu_clock(u16 cpu_clk_mhz)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
u8 axi, ahb, ahb_exp, apb0, apb0_exp;
|
|
||||||
u32 actual_mhz;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Rated clock for PLL1 is 2000 MHz, but there is no combination of
|
|
||||||
* parameters that yields that exact frequency. 1944 MHz is the highest.
|
|
||||||
*/
|
|
||||||
if (cpu_clk_mhz > 1944) {
|
|
||||||
printk(BIOS_CRIT, "BUG! maximum PLL1 clock is 1944 MHz,"
|
|
||||||
"but asked to clock CPU at %d MHz\n",
|
|
||||||
cpu_clk_mhz);
|
|
||||||
cpu_clk_mhz = 1944;
|
|
||||||
}
|
|
||||||
/* Find target frequency */
|
|
||||||
while (pll1_table[i].freq_mhz < cpu_clk_mhz)
|
|
||||||
i++;
|
|
||||||
|
|
||||||
actual_mhz = pll1_table[i].freq_mhz;
|
|
||||||
|
|
||||||
if (cpu_clk_mhz != actual_mhz) {
|
|
||||||
printk(BIOS_WARNING, "Parameters for %d MHz not available, "
|
|
||||||
"setting CPU clock at %d MHz\n",
|
|
||||||
cpu_clk_mhz, actual_mhz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate system clock divisors:
|
|
||||||
* The minimum clock divisor for APB0 is 2, which guarantees that AHB0
|
|
||||||
* will always be in spec, as long as AHB is in spec, although the max
|
|
||||||
* AHB0 clock we can get is 125 MHz
|
|
||||||
*/
|
|
||||||
axi = DIV_ROUND_UP(actual_mhz, 450); /* Max 450 MHz */
|
|
||||||
ahb = DIV_ROUND_UP(actual_mhz/axi, 250); /* Max 250 MHz */
|
|
||||||
apb0 = 2; /* Max 150 MHz */
|
|
||||||
|
|
||||||
ahb_exp = log2_ceil(ahb);
|
|
||||||
ahb = 1 << ahb_exp;
|
|
||||||
apb0_exp = 1;
|
|
||||||
|
|
||||||
printk(BIOS_INFO, "CPU: %d MHz, AXI %d Mhz, AHB: %d MHz APB0: %d MHz\n",
|
|
||||||
actual_mhz,
|
|
||||||
actual_mhz / axi,
|
|
||||||
actual_mhz / (axi * ahb),
|
|
||||||
actual_mhz / (axi * ahb * apb0));
|
|
||||||
|
|
||||||
/* Keep the CPU off PLL1 while we change PLL parameters */
|
|
||||||
cpu_clk_src_switch(CPU_CLK_SRC_OSC24M);
|
|
||||||
/*
|
|
||||||
* We can't use udelay() here. udelay() relies on timer 0, but timers
|
|
||||||
* have the habit of not ticking when the CPU is clocked from the main
|
|
||||||
* oscillator.
|
|
||||||
*/
|
|
||||||
spin_delay(8);
|
|
||||||
|
|
||||||
change_sys_divisors(axi, ahb_exp, apb0_exp);
|
|
||||||
|
|
||||||
/* Configure PLL1 at the desired frequency */
|
|
||||||
write32(&ccm->pll1_cfg, pll1_table[i].pll1_cfg);
|
|
||||||
spin_delay(8);
|
|
||||||
|
|
||||||
cpu_clk_src_switch(CPU_CLK_SRC_PLL1);
|
|
||||||
/* Here, we're running from PLL, so timers will tick */
|
|
||||||
udelay(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __BOOTBLOCK__ */
|
|
@@ -1,283 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007-2011 Allwinner Technology Co., Ltd.
|
|
||||||
* Tom Cubie <tangliang@allwinnertech.com>
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License. or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Definitions for clock control and gating on Allwinner CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPU_ALLWINNER_A10_CLOCK_H
|
|
||||||
#define CPU_ALLWINNER_A10_CLOCK_H
|
|
||||||
|
|
||||||
#include "memmap.h"
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
/* CPU_AHB_APB0 config values */
|
|
||||||
#define CPU_CLK_SRC_MASK (3 << 16)
|
|
||||||
#define CPU_CLK_SRC_OSC24M (1 << 16)
|
|
||||||
#define CPU_CLK_SRC_PLL1 (2 << 16)
|
|
||||||
#define APB0_DIV_MASK (3 << 8)
|
|
||||||
#define APB0_DIV_1 (0 << 8)
|
|
||||||
#define APB0_DIV_2 (1 << 8)
|
|
||||||
#define APB0_DIV_4 (2 << 8)
|
|
||||||
#define APB0_DIV_8 (3 << 8)
|
|
||||||
#define AHB_DIV_MASK (3 << 4)
|
|
||||||
#define AHB_DIV_1 (0 << 4)
|
|
||||||
#define AHB_DIV_2 (1 << 4)
|
|
||||||
#define AHB_DIV_4 (2 << 4)
|
|
||||||
#define AHB_DIV_8 (3 << 4)
|
|
||||||
#define AXI_DIV_MASK (3 << 0)
|
|
||||||
#define AXI_DIV_1 (0 << 0)
|
|
||||||
#define AXI_DIV_2 (1 << 0)
|
|
||||||
#define AXI_DIV_3 (2 << 0)
|
|
||||||
#define AXI_DIV_4 (3 << 0)
|
|
||||||
|
|
||||||
/* APB1_CLK_DIV values */
|
|
||||||
#define APB1_CLK_SRC_MASK (3 << 24)
|
|
||||||
#define APB1_CLK_SRC_OSC24M (0 << 24)
|
|
||||||
#define APB1_CLK_SRC_PLL6 (1 << 24)
|
|
||||||
#define APB1_CLK_SRC_32K (2 << 24)
|
|
||||||
#define APB1_RAT_N_MASK (3 << 16)
|
|
||||||
#define APB1_RAT_N(m) (((m) & 0x3) << 16)
|
|
||||||
#define APB1_RAT_M_MASK (0x1f << 0)
|
|
||||||
#define APB1_RAT_M(n) (((n) & 0x1f) << 0)
|
|
||||||
|
|
||||||
/* PLL5_CFG values */
|
|
||||||
#define PLL5_PLL_ENABLE (1 << 31)
|
|
||||||
#define PLL5_OUT_BYPASS_EN (1 << 30)
|
|
||||||
#define PLL5_DDR_CLK_OUT_EN (1 << 29)
|
|
||||||
#define PLL5_DIV_EXP_P_MASK (0x3 << 16)
|
|
||||||
#define PLL5_DIV_EXP_P(ep) ((ep << 16) & PLL5_DIV_EXP_P_MASK)
|
|
||||||
#define PLL5_DIV_P_1 (0x0 << 16)
|
|
||||||
#define PLL5_DIV_P_2 (0x1 << 16)
|
|
||||||
#define PLL5_DIV_P_4 (0x2 << 16)
|
|
||||||
#define PLL5_DIV_P_8 (0x3 << 16)
|
|
||||||
#define PLL5_FACTOR_N_MASK (0x1f << 8)
|
|
||||||
#define PLL5_FACTOR_N(n) ((n << 8) & PLL5_FACTOR_N_MASK)
|
|
||||||
#define PLL5_LDO_EN (1 << 7)
|
|
||||||
#define PLL5_FACTOR_K_MASK (0x3 << 4)
|
|
||||||
#define PLL5_FACTOR_K(k) ((((k) - 1) << 4) & PLL5_FACTOR_K_MASK)
|
|
||||||
#define PLL5_FACTOR_M1_MASK (0x3 << 2)
|
|
||||||
#define PLL5_FACTOR_M1(m1) (((m1) << 2) & PLL5_FACTOR_M1_MASK)
|
|
||||||
#define PLL5_FACTOR_M_MASK (0x3 << 0)
|
|
||||||
#define PLL5_FACTOR_M(m) ((((m) - 1) << 0) & PLL5_FACTOR_M_MASK)
|
|
||||||
|
|
||||||
/* DRAM_CLK values*/
|
|
||||||
#define DRAM_CTRL_DCLK_OUT (1 << 15)
|
|
||||||
|
|
||||||
/* SDx_CLK values */
|
|
||||||
#define SDx_CLK_GATE (1 << 31)
|
|
||||||
#define SDx_CLK_SRC_MASK (3 << 24)
|
|
||||||
#define SDx_CLK_SRC_OSC24M (0 << 24)
|
|
||||||
#define SDx_CLK_SRC_PLL6 (1 << 24)
|
|
||||||
#define SDx_CLK_SRC_PLL5 (2 << 24)
|
|
||||||
#define SDx_RAT_EXP_N_MASK (3 << 16)
|
|
||||||
#define SDx_RAT_EXP_N(n) (((n) << 16) & SDx_RAT_EXP_N_MASK)
|
|
||||||
#define SDx_RAT_M_MASK (0xf << 0)
|
|
||||||
#define SDx_RAT_M(m) ((((m) - 1) << 0) & SDx_RAT_M_MASK)
|
|
||||||
/**
|
|
||||||
* \brief Clock gating definitions
|
|
||||||
*
|
|
||||||
* The definitions are specified in the form:
|
|
||||||
* 31:5 register offset from A1X_CCM_BASE for the clock register
|
|
||||||
* 4:0 bit offset for the given peripheral
|
|
||||||
*
|
|
||||||
* The names have the form [periph_type][periph_number]
|
|
||||||
*
|
|
||||||
* These definitions are meant to be used with @ref a1x_periph_clock_enable and
|
|
||||||
* @ref a1x_periph_clock_disable
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum a1x_clken {
|
|
||||||
/* AXI module clock gating */
|
|
||||||
A1X_CLKEN_DRAM_AXI = (0x5C << 5),
|
|
||||||
/* AHB0 module clock gating */
|
|
||||||
A1X_CLKEN_USB0 = (0x60 << 5),
|
|
||||||
A1X_CLKEN_EHCI0,
|
|
||||||
RSVD_0x60_2,
|
|
||||||
A1X_CLKEN_EHCI1,
|
|
||||||
RSVD_0x60_4,
|
|
||||||
A1X_CLKEN_SS,
|
|
||||||
A1X_CLKEN_DMA,
|
|
||||||
A1X_CLKEN_BIST,
|
|
||||||
A1X_CLKEN_MMC0,
|
|
||||||
A1X_CLKEN_MMC1,
|
|
||||||
A1X_CLKEN_MMC2,
|
|
||||||
A1X_CLKEN_MMC3,
|
|
||||||
A1X_CLKEN_NC,
|
|
||||||
A1X_CLKEN_NAND,
|
|
||||||
A1X_CLKEN_SDRAM,
|
|
||||||
RSVD_0x60_15,
|
|
||||||
A1X_CLKEN_ACE,
|
|
||||||
A1X_CLKEN_EMAC,
|
|
||||||
A1X_CLKEN_TS,
|
|
||||||
RSVD_0x60_19,
|
|
||||||
A1X_CLKEN_SPI0,
|
|
||||||
A1X_CLKEN_SPI1,
|
|
||||||
A1X_CLKEN_SPI2,
|
|
||||||
A1X_CLKEN_SPI3,
|
|
||||||
A1X_CLKEN_PATA,
|
|
||||||
RSVD_0x60_25,
|
|
||||||
A1X_CLKEN_GPS,
|
|
||||||
/* AHB1 module clock gating */
|
|
||||||
A1X_CLKEN_DRAM_VE = (0x64 << 5),
|
|
||||||
A1X_CLKEN_TVD,
|
|
||||||
A1X_CLKEN_TVE0,
|
|
||||||
A1X_CLKEN_TVE1,
|
|
||||||
A1X_CLKEN_LCD0,
|
|
||||||
A1X_CLKEN_LCD1,
|
|
||||||
RSVD_0x64_6,
|
|
||||||
RSVD_0x64_7,
|
|
||||||
A1X_CLKEN_CSI0,
|
|
||||||
A1X_CLKEN_CSI1,
|
|
||||||
RSVD_0x64_10,
|
|
||||||
A1X_CLKEN_HDMI,
|
|
||||||
A1X_CLKEN_DE_BE0,
|
|
||||||
A1X_CLKEN_DE_BE1,
|
|
||||||
A1X_CLKEN_DE_FE0,
|
|
||||||
A1X_CLKEN_DE_FE1,
|
|
||||||
RSVD_0x64_16,
|
|
||||||
RSVD_0x64_17,
|
|
||||||
A1X_CLKEN_MP,
|
|
||||||
RSVD_0x64_19,
|
|
||||||
A1X_CLKEN_MALI400,
|
|
||||||
/* APB0 module clock gating */
|
|
||||||
A1X_CLKEN_CODEC = (0x68 << 5),
|
|
||||||
A1X_CLKEN_NC_APB,
|
|
||||||
A1X_CLKEN_AC97,
|
|
||||||
A1X_CLKEN_IIS,
|
|
||||||
RSVD_0x68_4,
|
|
||||||
A1X_CLKEN_PIO,
|
|
||||||
A1X_CLKEN_IR0,
|
|
||||||
A1X_CLKEN_IR1,
|
|
||||||
RSVD_0x68_8,
|
|
||||||
RSVD_0x68_9,
|
|
||||||
A1X_CLKEN_KEYPAD,
|
|
||||||
/* APB1 module clock gating */
|
|
||||||
A1X_CLKEN_TWI0 = (0x6C << 5),
|
|
||||||
A1X_CLKEN_TWI1,
|
|
||||||
A1X_CLKEN_TWI2,
|
|
||||||
RSVD_0x6C_3,
|
|
||||||
A1X_CLKEN_CAN,
|
|
||||||
A1X_CLKEN_SCR,
|
|
||||||
A1X_CLKEN_PS20,
|
|
||||||
A1X_CLKEN_PS21,
|
|
||||||
RSVD_0x6C_8,
|
|
||||||
RSVD_0x6C_9,
|
|
||||||
RSVD_0x6C_10,
|
|
||||||
RSVD_0x6C_11,
|
|
||||||
RSVD_0x6C_12,
|
|
||||||
RSVD_0x6C_13,
|
|
||||||
RSVD_0x6C_14,
|
|
||||||
RSVD_0x6C_15,
|
|
||||||
A1X_CLKEN_UART0,
|
|
||||||
A1X_CLKEN_UART1,
|
|
||||||
A1X_CLKEN_UART2,
|
|
||||||
A1X_CLKEN_UART3,
|
|
||||||
A1X_CLKEN_UART4,
|
|
||||||
A1X_CLKEN_UART5,
|
|
||||||
A1X_CLKEN_UART6,
|
|
||||||
A1X_CLKEN_UART7,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct a10_ccm {
|
|
||||||
u32 pll1_cfg; /* 0x00 pll1 control */
|
|
||||||
u32 pll1_tun; /* 0x04 pll1 tuning */
|
|
||||||
u32 pll2_cfg; /* 0x08 pll2 control */
|
|
||||||
u32 pll2_tun; /* 0x0c pll2 tuning */
|
|
||||||
u32 pll3_cfg; /* 0x10 pll3 control */
|
|
||||||
u8 res0[0x4];
|
|
||||||
u32 pll4_cfg; /* 0x18 pll4 control */
|
|
||||||
u8 res1[0x4];
|
|
||||||
u32 pll5_cfg; /* 0x20 pll5 control */
|
|
||||||
u32 pll5_tun; /* 0x24 pll5 tuning */
|
|
||||||
u32 pll6_cfg; /* 0x28 pll6 control */
|
|
||||||
u32 pll6_tun; /* 0x2c pll6 tuning */
|
|
||||||
u32 pll7_cfg; /* 0x30 pll7 control */
|
|
||||||
u32 pll1_tun2; /* 0x34 pll5 tuning2 */
|
|
||||||
u8 res2[0x4];
|
|
||||||
u32 pll5_tun2; /* 0x3c pll5 tuning2 */
|
|
||||||
u8 res3[0xc];
|
|
||||||
u32 pll_lock_dbg; /* 0x4c pll lock time debug */
|
|
||||||
u32 osc24m_cfg; /* 0x50 osc24m control */
|
|
||||||
u32 cpu_ahb_apb0_cfg; /* 0x54 CPU, ahb and apb0 divide ratio */
|
|
||||||
u32 apb1_clk_div_cfg; /* 0x58 apb1 clock dividor */
|
|
||||||
u32 axi_gate; /* 0x5c axi module clock gating */
|
|
||||||
u32 ahb_gate0; /* 0x60 ahb module clock gating 0 */
|
|
||||||
u32 ahb_gate1; /* 0x64 ahb module clock gating 1 */
|
|
||||||
u32 apb0_gate; /* 0x68 apb0 module clock gating */
|
|
||||||
u32 apb1_gate; /* 0x6c apb1 module clock gating */
|
|
||||||
u8 res4[0x10];
|
|
||||||
u32 nand_sclk_cfg; /* 0x80 nand sub clock control */
|
|
||||||
u32 ms_sclk_cfg; /* 0x84 memory stick sub clock control */
|
|
||||||
u32 sd0_clk_cfg; /* 0x88 sd0 clock control */
|
|
||||||
u32 sd1_clk_cfg; /* 0x8c sd1 clock control */
|
|
||||||
u32 sd2_clk_cfg; /* 0x90 sd2 clock control */
|
|
||||||
u32 sd3_clk_cfg; /* 0x94 sd3 clock control */
|
|
||||||
u32 ts_clk_cfg; /* 0x98 transport stream clock control */
|
|
||||||
u32 ss_clk_cfg; /* 0x9c */
|
|
||||||
u32 spi0_clk_cfg; /* 0xa0 */
|
|
||||||
u32 spi1_clk_cfg; /* 0xa4 */
|
|
||||||
u32 spi2_clk_cfg; /* 0xa8 */
|
|
||||||
u32 pata_clk_cfg; /* 0xac */
|
|
||||||
u32 ir0_clk_cfg; /* 0xb0 */
|
|
||||||
u32 ir1_clk_cfg; /* 0xb4 */
|
|
||||||
u32 iis_clk_cfg; /* 0xb8 */
|
|
||||||
u32 ac97_clk_cfg; /* 0xbc */
|
|
||||||
u32 spdif_clk_cfg; /* 0xc0 */
|
|
||||||
u32 keypad_clk_cfg; /* 0xc4 */
|
|
||||||
u32 sata_clk_cfg; /* 0xc8 */
|
|
||||||
u32 usb_clk_cfg; /* 0xcc */
|
|
||||||
u32 gps_clk_cfg; /* 0xd0 */
|
|
||||||
u32 spi3_clk_cfg; /* 0xd4 */
|
|
||||||
u8 res5[0x28];
|
|
||||||
u32 dram_clk_cfg; /* 0x100 */
|
|
||||||
u32 be0_clk_cfg; /* 0x104 */
|
|
||||||
u32 be1_clk_cfg; /* 0x108 */
|
|
||||||
u32 fe0_clk_cfg; /* 0x10c */
|
|
||||||
u32 fe1_clk_cfg; /* 0x110 */
|
|
||||||
u32 mp_clk_cfg; /* 0x114 */
|
|
||||||
u32 lcd0_ch0_clk_cfg; /* 0x118 */
|
|
||||||
u32 lcd1_ch0_clk_cfg; /* 0x11c */
|
|
||||||
u32 csi_isp_clk_cfg; /* 0x120 */
|
|
||||||
u8 res6[0x4];
|
|
||||||
u32 tvd_clk_reg; /* 0x128 */
|
|
||||||
u32 lcd0_ch1_clk_cfg; /* 0x12c */
|
|
||||||
u32 lcd1_ch1_clk_cfg; /* 0x130 */
|
|
||||||
u32 csi0_clk_cfg; /* 0x134 */
|
|
||||||
u32 csi1_clk_cfg; /* 0x138 */
|
|
||||||
u32 ve_clk_cfg; /* 0x13c */
|
|
||||||
u32 audio_codec_clk_cfg; /* 0x140 */
|
|
||||||
u32 avs_clk_cfg; /* 0x144 */
|
|
||||||
u32 ace_clk_cfg; /* 0x148 */
|
|
||||||
u32 lvds_clk_cfg; /* 0x14c */
|
|
||||||
u32 hdmi_clk_cfg; /* 0x150 */
|
|
||||||
u32 mali_clk_cfg; /* 0x154 */
|
|
||||||
u8 res7[0x4];
|
|
||||||
u32 mbus_clk_cfg; /* 0x15c */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
void a1x_periph_clock_enable(enum a1x_clken periph);
|
|
||||||
void a1x_periph_clock_disable(enum a1x_clken periph);
|
|
||||||
|
|
||||||
void a1x_pll5_configure(u8 mul_n, u8 mul_k, u8 div_m, u8 exp_div_p);
|
|
||||||
void a1x_pll5_enable_dram_clock_output(void);
|
|
||||||
void a1x_ungate_dram_clock_output(void);
|
|
||||||
void a1x_gate_dram_clock_output(void);
|
|
||||||
|
|
||||||
/* Not available in bootblock */
|
|
||||||
void a1x_set_cpu_clock(u16 cpu_clk_mhz);
|
|
||||||
|
|
||||||
#endif /* CPU_ALLWINNER_A10_CLOCK_H */
|
|
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Ramstage initialization for Allwinner CPUs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <device/device.h>
|
|
||||||
#include <symbols.h>
|
|
||||||
|
|
||||||
static void cpu_enable_resources(struct device *dev)
|
|
||||||
{
|
|
||||||
ram_resource(dev, 0, (uintptr_t)_dram/KiB,
|
|
||||||
CONFIG_DRAM_SIZE_MB << 10);
|
|
||||||
/* TODO: Declare CBFS cache as reserved? There's no guarantee we won't
|
|
||||||
* overwrite it. It seems to stay intact, being so high in RAM
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cpu_init(struct device *dev)
|
|
||||||
{
|
|
||||||
/* TODO: Check if anything else needs to be explicitly initialized */
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct device_operations cpu_ops = {
|
|
||||||
.read_resources = DEVICE_NOOP,
|
|
||||||
.set_resources = DEVICE_NOOP,
|
|
||||||
.enable_resources = cpu_enable_resources,
|
|
||||||
.init = cpu_init,
|
|
||||||
.scan_bus = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void a1x_cpu_enable_dev(struct device *dev)
|
|
||||||
{
|
|
||||||
dev->ops = &cpu_ops;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct chip_operations cpu_allwinner_a10_ops = {
|
|
||||||
CHIP_NAME("CPU Allwinner A10")
|
|
||||||
.enable_dev = a1x_cpu_enable_dev,
|
|
||||||
};
|
|
@@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007-2012 Allwinner Technology Co., Ltd.
|
|
||||||
* Berg Xing <bergxing@allwinnertech.com>
|
|
||||||
* Tom Cubie <tangliang@allwinnertech.com>
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License.or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Allwinner A10 platform dram register definition.
|
|
||||||
*
|
|
||||||
* Based on sun4i Linux kernel sources mach-sunxi/pm/standby/dram*.c
|
|
||||||
* and earlier U-Boot Allwiner A10 SPL work
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPU_ALLWINNER_A10_DRAMC_H
|
|
||||||
#define CPU_ALLWINNER_A10_DRAMC_H
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
#define DRAM_CCR_COMMAND_RATE_1T (0x1 << 5)
|
|
||||||
#define DRAM_CCR_DQS_GATE (0x1 << 14)
|
|
||||||
#define DRAM_CCR_DQS_DRIFT_COMP (0x1 << 17)
|
|
||||||
#define DRAM_CCR_ITM_OFF (0x1 << 28)
|
|
||||||
#define DRAM_CCR_DATA_TRAINING (0x1 << 30)
|
|
||||||
#define DRAM_CCR_INIT (0x1 << 31)
|
|
||||||
|
|
||||||
#define DRAM_MEMORY_TYPE_DDR1 1
|
|
||||||
#define DRAM_MEMORY_TYPE_DDR2 2
|
|
||||||
#define DRAM_MEMORY_TYPE_DDR3 3
|
|
||||||
#define DRAM_MEMORY_TYPE_LPDDR2 4
|
|
||||||
#define DRAM_MEMORY_TYPE_LPDDR 5
|
|
||||||
#define DRAM_DCR_TYPE (0x1 << 0)
|
|
||||||
#define DRAM_DCR_TYPE_DDR2 0x0
|
|
||||||
#define DRAM_DCR_TYPE_DDR3 0x1
|
|
||||||
#define DRAM_DCR_IO_WIDTH(n) (((n) & 0x3) << 1)
|
|
||||||
#define DRAM_DCR_IO_WIDTH_MASK DRAM_DCR_IO_WIDTH(0x3)
|
|
||||||
#define DRAM_DCR_IO_WIDTH_8BIT 0x0
|
|
||||||
#define DRAM_DCR_IO_WIDTH_16BIT 0x1
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY(n) (((n) & 0x7) << 3)
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY_MASK DRAM_DCR_CHIP_DENSITY(0x7)
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY_256M 0x0
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY_512M 0x1
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY_1024M 0x2
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY_2048M 0x3
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY_4096M 0x4
|
|
||||||
#define DRAM_DCR_CHIP_DENSITY_8192M 0x5
|
|
||||||
#define DRAM_DCR_BUS_WIDTH(n) (((n) & 0x7) << 6)
|
|
||||||
#define DRAM_DCR_BUS_WIDTH_MASK DRAM_DCR_BUS_WIDTH(0x7)
|
|
||||||
#define DRAM_DCR_BUS_WIDTH_32BIT 0x3
|
|
||||||
#define DRAM_DCR_BUS_WIDTH_16BIT 0x1
|
|
||||||
#define DRAM_DCR_BUS_WIDTH_8BIT 0x0
|
|
||||||
#define DRAM_DCR_NR_DLLCR_32BIT 5
|
|
||||||
#define DRAM_DCR_NR_DLLCR_16BIT 3
|
|
||||||
#define DRAM_DCR_NR_DLLCR_8BIT 2
|
|
||||||
#define DRAM_DCR_RANK_SEL(n) (((n) & 0x3) << 10)
|
|
||||||
#define DRAM_DCR_RANK_SEL_MASK DRAM_DCR_CMD_RANK(0x3)
|
|
||||||
#define DRAM_DCR_CMD_RANK_ALL (0x1 << 12)
|
|
||||||
#define DRAM_DCR_MODE(n) (((n) & 0x3) << 13)
|
|
||||||
#define DRAM_DCR_MODE_MASK DRAM_DCR_MODE(0x3)
|
|
||||||
#define DRAM_DCR_MODE_SEQ 0x0
|
|
||||||
#define DRAM_DCR_MODE_INTERLEAVE 0x1
|
|
||||||
|
|
||||||
#define DRAM_CSR_FAILED (0x1 << 20)
|
|
||||||
|
|
||||||
#define DRAM_MCR_MODE_NORM(n) (((n) & 0x3) << 0)
|
|
||||||
#define DRAM_MCR_MODE_NORM_MASK DRAM_MCR_MOD_NORM(0x3)
|
|
||||||
#define DRAM_MCR_MODE_DQ_OUT(n) (((n) & 0x3) << 2)
|
|
||||||
#define DRAM_MCR_MODE_DQ_OUT_MASK DRAM_MCR_MODE_DQ_OUT(0x3)
|
|
||||||
#define DRAM_MCR_MODE_ADDR_OUT(n) (((n) & 0x3) << 4)
|
|
||||||
#define DRAM_MCR_MODE_ADDR_OUT_MASK DRAM_MCR_MODE_ADDR_OUT(0x3)
|
|
||||||
#define DRAM_MCR_MODE_DQ_IN_OUT(n) (((n) & 0x3) << 6)
|
|
||||||
#define DRAM_MCR_MODE_DQ_IN_OUT_MASK DRAM_MCR_MODE_DQ_IN_OUT(0x3)
|
|
||||||
#define DRAM_MCR_MODE_DQ_TURNON_DELAY(n) (((n) & 0x7) << 8)
|
|
||||||
#define DRAM_MCR_MODE_DQ_TURNON_DELAY_MASK DRAM_MCR_MODE_DQ_TURNON_DELAY(0x7)
|
|
||||||
#define DRAM_MCR_MODE_ADDR_IN (0x1 << 11)
|
|
||||||
#define DRAM_MCR_RESET (0x1 << 12)
|
|
||||||
#define DRAM_MCR_MODE_EN(n) (((n) & 0x3) << 13)
|
|
||||||
#define DRAM_MCR_MODE_EN_MASK DRAM_MCR_MOD_EN(0x3)
|
|
||||||
#define DRAM_MCR_DCLK_OUT (0x1 << 16)
|
|
||||||
|
|
||||||
#define DRAM_DLLCR_NRESET (0x1 << 30)
|
|
||||||
#define DRAM_DLLCR_DISABLE (0x1 << 31)
|
|
||||||
|
|
||||||
#define DRAM_ZQCR0_IMP_DIV(n) (((n) & 0xff) << 20)
|
|
||||||
#define DRAM_ZQCR0_IMP_DIV_MASK DRAM_ZQCR0_IMP_DIV(0xff)
|
|
||||||
|
|
||||||
#define DRAM_IOCR_ODT_EN(n) ((((n) & 0x3) << 30) | ((n) & 0x3) << 0)
|
|
||||||
#define DRAM_IOCR_ODT_EN_MASK DRAM_IOCR_ODT_EN(0x3)
|
|
||||||
|
|
||||||
#define DRAM_MR_BURST_LENGTH(n) (((n) & 0x7) << 0)
|
|
||||||
#define DRAM_MR_BURST_LENGTH_MASK DRAM_MR_BURST_LENGTH(0x7)
|
|
||||||
#define DRAM_MR_CAS_LAT(n) (((n) & 0x7) << 4)
|
|
||||||
#define DRAM_MR_CAS_LAT_MASK DRAM_MR_CAS_LAT(0x7)
|
|
||||||
#define DRAM_MR_WRITE_RECOVERY(n) (((n) & 0x7) << 9)
|
|
||||||
#define DRAM_MR_WRITE_RECOVERY_MASK DRAM_MR_WRITE_RECOVERY(0x7)
|
|
||||||
#define DRAM_MR_POWER_DOWN (0x1 << 12)
|
|
||||||
|
|
||||||
#define DRAM_CSEL_MAGIC 0x16237495
|
|
||||||
|
|
||||||
struct a1x_dramc {
|
|
||||||
u32 ccr; /* 0x00 controller configuration register */
|
|
||||||
u32 dcr; /* 0x04 dram configuration register */
|
|
||||||
u32 iocr; /* 0x08 i/o configuration register */
|
|
||||||
u32 csr; /* 0x0c controller status register */
|
|
||||||
u32 drr; /* 0x10 dram refresh register */
|
|
||||||
u32 tpr0; /* 0x14 dram timing parameters register 0 */
|
|
||||||
u32 tpr1; /* 0x18 dram timing parameters register 1 */
|
|
||||||
u32 tpr2; /* 0x1c dram timing parameters register 2 */
|
|
||||||
u32 gdllcr; /* 0x20 global dll control register */
|
|
||||||
u8 res0[0x28];
|
|
||||||
u32 rslr0; /* 0x4c rank system latency register */
|
|
||||||
u32 rslr1; /* 0x50 rank system latency register */
|
|
||||||
u8 res1[0x8];
|
|
||||||
u32 rdgr0; /* 0x5c rank dqs gating register */
|
|
||||||
u32 rdgr1; /* 0x60 rank dqs gating register */
|
|
||||||
u8 res2[0x34];
|
|
||||||
u32 odtcr; /* 0x98 odt configuration register */
|
|
||||||
u32 dtr0; /* 0x9c data training register 0 */
|
|
||||||
u32 dtr1; /* 0xa0 data training register 1 */
|
|
||||||
u32 dtar; /* 0xa4 data training address register */
|
|
||||||
u32 zqcr0; /* 0xa8 zq control register 0 */
|
|
||||||
u32 zqcr1; /* 0xac zq control register 1 */
|
|
||||||
u32 zqsr; /* 0xb0 zq status register */
|
|
||||||
u32 idcr; /* 0xb4 initializaton delay configure reg */
|
|
||||||
u8 res3[0x138];
|
|
||||||
u32 mr; /* 0x1f0 mode register */
|
|
||||||
u32 emr; /* 0x1f4 extended mode register */
|
|
||||||
u32 emr2; /* 0x1f8 extended mode register */
|
|
||||||
u32 emr3; /* 0x1fc extended mode register */
|
|
||||||
u32 dllctr; /* 0x200 dll control register */
|
|
||||||
u32 dllcr[5]; /* 0x204 dll control register 0(byte 0) */
|
|
||||||
/* 0x208 dll control register 1(byte 1) */
|
|
||||||
/* 0x20c dll control register 2(byte 2) */
|
|
||||||
/* 0x210 dll control register 3(byte 3) */
|
|
||||||
/* 0x214 dll control register 4(byte 4) */
|
|
||||||
u32 dqtr0; /* 0x218 dq timing register */
|
|
||||||
u32 dqtr1; /* 0x21c dq timing register */
|
|
||||||
u32 dqtr2; /* 0x220 dq timing register */
|
|
||||||
u32 dqtr3; /* 0x224 dq timing register */
|
|
||||||
u32 dqstr; /* 0x228 dqs timing register */
|
|
||||||
u32 dqsbtr; /* 0x22c dqsb timing register */
|
|
||||||
u32 mcr; /* 0x230 mode configure register */
|
|
||||||
u8 res[0x8];
|
|
||||||
u32 ppwrsctl; /* 0x23c pad power save control */
|
|
||||||
u32 apr; /* 0x240 arbiter period register */
|
|
||||||
u32 pldtr; /* 0x244 priority level data threshold reg */
|
|
||||||
u8 res5[0x8];
|
|
||||||
u32 hpcr[32]; /* 0x250 host port configure register */
|
|
||||||
u8 res6[0x10];
|
|
||||||
u32 csel; /* 0x2e0 controller select register */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dram_para {
|
|
||||||
u32 clock;
|
|
||||||
u32 type;
|
|
||||||
u32 rank_num;
|
|
||||||
u32 density;
|
|
||||||
u32 io_width;
|
|
||||||
u32 bus_width;
|
|
||||||
u32 cas;
|
|
||||||
u32 zq;
|
|
||||||
u32 odt_en;
|
|
||||||
u32 size;
|
|
||||||
u32 tpr0;
|
|
||||||
u32 tpr1;
|
|
||||||
u32 tpr2;
|
|
||||||
u32 tpr3;
|
|
||||||
u32 tpr4;
|
|
||||||
u32 tpr5;
|
|
||||||
u32 emr1;
|
|
||||||
u32 emr2;
|
|
||||||
u32 emr3;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned long dramc_init(struct dram_para *para);
|
|
||||||
|
|
||||||
#endif /* CPU_ALLWINNER_A10_DRAMC_H */
|
|
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Basic GPIO helpers for Allwinner CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gpio.h"
|
|
||||||
|
|
||||||
#include <device/mmio.h>
|
|
||||||
|
|
||||||
static struct a10_gpio *const gpio = (void *)GPIO_BASE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set a single output pin
|
|
||||||
*
|
|
||||||
* @param[in] port GPIO port of the pin (GPA -> GPS)
|
|
||||||
* @param[in] pin the pin number in the given port (1 -> 31)
|
|
||||||
*/
|
|
||||||
void gpio_set(u8 port, u8 pin)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
if ((port > GPS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
reg32 = gpio_read(port);
|
|
||||||
reg32 |= (1 << pin);
|
|
||||||
gpio_write(port, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Clear a single output pin
|
|
||||||
*
|
|
||||||
* @param[in] port GPIO port of the pin (GPA -> GPS)
|
|
||||||
* @param[in] pin the pin number in the given port (1 -> 31)
|
|
||||||
*/
|
|
||||||
void gpio_clear(u8 port, u8 pin)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
if ((port > GPS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
reg32 = gpio_read(port);
|
|
||||||
reg32 &= ~(1 << pin);
|
|
||||||
gpio_write(port, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Get the status of a single input pin
|
|
||||||
*
|
|
||||||
* @param[in] port GPIO port of the pin (GPA -> GPS)
|
|
||||||
* @param[in] pin the pin number in the given port (1 -> 31)
|
|
||||||
* @return 1 if the pin is high, or 0 if the pin is low
|
|
||||||
*/
|
|
||||||
int gpio_get(u8 port, u8 pin)
|
|
||||||
{
|
|
||||||
if ((port > GPS))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return (gpio_read(port) & (1 << pin)) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Write to a GPIO port
|
|
||||||
*
|
|
||||||
* Write the state of all output pins in the GPIO port. This only affects pins
|
|
||||||
* configured as output pins.
|
|
||||||
*
|
|
||||||
* @param[in] port GPIO port of the pin (GPA -> GPS)
|
|
||||||
* @param[in] val 32-bit mask indicating which pins to set. For a set bit, the
|
|
||||||
* corresponding pin will be set. Otherwise, it will be cleared
|
|
||||||
*/
|
|
||||||
void gpio_write(u8 port, u32 val)
|
|
||||||
{
|
|
||||||
if ((port > GPS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
write32(&gpio->port[port].dat, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Write to a GPIO port
|
|
||||||
*
|
|
||||||
* Read the state of all input pins in the GPIO port.
|
|
||||||
*
|
|
||||||
* @param[in] port GPIO port of the pin (GPA -> GPS)
|
|
||||||
* @return 32-bit mask indicating which pins are high. For each set bit, the
|
|
||||||
* corresponding pin is high. The value of bits corresponding to pins
|
|
||||||
* which are not configured as inputs is undefined.
|
|
||||||
*/
|
|
||||||
u32 gpio_read(u8 port)
|
|
||||||
{
|
|
||||||
if ((port > GPS))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return read32(&gpio->port[port].dat);
|
|
||||||
}
|
|
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Definitions for GPIO and pin multiplexing on Allwinner CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __CPU_ALLWINNER_A10_PINMUX_H
|
|
||||||
#define __CPU_ALLWINNER_A10_PINMUX_H
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
#define GPIO_BASE 0x01C20800
|
|
||||||
|
|
||||||
#define GPA 0
|
|
||||||
#define GPB 1
|
|
||||||
#define GPC 2
|
|
||||||
#define GPD 3
|
|
||||||
#define GPE 4
|
|
||||||
#define GPF 5
|
|
||||||
#define GPG 6
|
|
||||||
#define GPH 7
|
|
||||||
#define GPI 8
|
|
||||||
#define GPS 9
|
|
||||||
|
|
||||||
/* GPIO pad functions valid for all pins */
|
|
||||||
#define GPIO_PIN_FUNC_INPUT 0
|
|
||||||
#define GPIO_PIN_FUNC_OUTPUT 1
|
|
||||||
|
|
||||||
struct a10_gpio_port {
|
|
||||||
u32 cfg[4];
|
|
||||||
u32 dat;
|
|
||||||
u32 drv[2];
|
|
||||||
u32 pul[2];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct a10_gpio {
|
|
||||||
struct a10_gpio_port port[10];
|
|
||||||
u8 reserved_0x168[0x98];
|
|
||||||
|
|
||||||
/* Offset 0x200 */
|
|
||||||
u32 int_cfg[4];
|
|
||||||
|
|
||||||
u32 int_ctl;
|
|
||||||
u32 int_sta;
|
|
||||||
u8 reserved_0x21C[4];
|
|
||||||
u32 int_deb;
|
|
||||||
|
|
||||||
u32 sdr_pad_drv;
|
|
||||||
u32 sdr_pad_pul;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* gpio.c */
|
|
||||||
void gpio_set(u8 port, u8 pin);
|
|
||||||
void gpio_clear(u8 port, u8 pin);
|
|
||||||
int gpio_get(u8 port, u8 pin);
|
|
||||||
void gpio_write(u8 port, u32 val);
|
|
||||||
u32 gpio_read(u8 port);
|
|
||||||
|
|
||||||
/* pinmux.c */
|
|
||||||
void gpio_set_pin_func(u8 port, u8 pin, u8 pad_func);
|
|
||||||
void gpio_set_multipin_func(u8 port, u32 pin_mask, u8 pad_func);
|
|
||||||
|
|
||||||
#endif /* __CPU_ALLWINNER_A10_PINMUX_H */
|
|
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007-2011 Allwinner Technology Co., Ltd.
|
|
||||||
* Tom Cubie <tangliang@allwinnertech.com>
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Memory map definitions for Allwinner A10 CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPU_ALLWINNER_A10_MEMMAP_H
|
|
||||||
#define CPU_ALLWINNER_A10_MEMMAP_H
|
|
||||||
|
|
||||||
#define A1X_SRAM_A1_BASE 0x00000000
|
|
||||||
#define A1X_SRAM_A1_SIZE (16 * 1024) /* 16 kiB */
|
|
||||||
|
|
||||||
#define A1X_SRAM_A2_BASE 0x00004000 /* 16 kiB */
|
|
||||||
#define A1X_SRAM_A3_BASE 0x00008000 /* 13 kiB */
|
|
||||||
#define A1X_SRAM_A4_BASE 0x0000b400 /* 3 kiB */
|
|
||||||
#define A1X_SRAM_D_BASE 0x01c00000
|
|
||||||
#define A1X_SRAM_B_BASE 0x01c00000 /* 64 kiB (secure) */
|
|
||||||
|
|
||||||
#define A1X_SRAMC_BASE 0x01c00000
|
|
||||||
#define A1X_DRAMC_BASE 0x01c01000
|
|
||||||
#define A1X_DMA_BASE 0x01c02000
|
|
||||||
#define A1X_NFC_BASE 0x01c03000
|
|
||||||
#define A1X_TS_BASE 0x01c04000
|
|
||||||
#define A1X_SPI0_BASE 0x01c05000
|
|
||||||
#define A1X_SPI1_BASE 0x01c06000
|
|
||||||
#define A1X_MS_BASE 0x01c07000
|
|
||||||
#define A1X_TVD_BASE 0x01c08000
|
|
||||||
#define A1X_CSI0_BASE 0x01c09000
|
|
||||||
#define A1X_TVE0_BASE 0x01c0a000
|
|
||||||
#define A1X_EMAC_BASE 0x01c0b000
|
|
||||||
#define A1X_LCD0_BASE 0x01c0C000
|
|
||||||
#define A1X_LCD1_BASE 0x01c0d000
|
|
||||||
#define A1X_VE_BASE 0x01c0e000
|
|
||||||
#define A1X_MMC0_BASE 0x01c0f000
|
|
||||||
#define A1X_MMC1_BASE 0x01c10000
|
|
||||||
#define A1X_MMC2_BASE 0x01c11000
|
|
||||||
#define A1X_MMC3_BASE 0x01c12000
|
|
||||||
#define A1X_USB0_BASE 0x01c13000
|
|
||||||
#define A1X_USB1_BASE 0x01c14000
|
|
||||||
#define A1X_SS_BASE 0x01c15000
|
|
||||||
#define A1X_HDMI_BASE 0x01c16000
|
|
||||||
#define A1X_SPI2_BASE 0x01c17000
|
|
||||||
#define A1X_SATA_BASE 0x01c18000
|
|
||||||
#define A1X_PATA_BASE 0x01c19000
|
|
||||||
#define A1X_ACE_BASE 0x01c1a000
|
|
||||||
#define A1X_TVE1_BASE 0x01c1b000
|
|
||||||
#define A1X_USB2_BASE 0x01c1c000
|
|
||||||
#define A1X_CSI1_BASE 0x01c1d000
|
|
||||||
#define A1X_TZASC_BASE 0x01c1e000
|
|
||||||
#define A1X_SPI3_BASE 0x01c1f000
|
|
||||||
|
|
||||||
#define A1X_CCM_BASE 0x01c20000
|
|
||||||
#define A1X_INTC_BASE 0x01c20400
|
|
||||||
#define A1X_PIO_BASE 0x01c20800
|
|
||||||
#define A1X_TIMER_BASE 0x01c20c00
|
|
||||||
#define A1X_SPDIF_BASE 0x01c21000
|
|
||||||
#define A1X_AC97_BASE 0x01c21400
|
|
||||||
#define A1X_IR0_BASE 0x01c21800
|
|
||||||
#define A1X_IR1_BASE 0x01c21c00
|
|
||||||
|
|
||||||
#define A1X_IIS_BASE 0x01c22400
|
|
||||||
#define A1X_LRADC_BASE 0x01c22800
|
|
||||||
#define A1X_AD_DA_BASE 0x01c22c00
|
|
||||||
#define A1X_KEYPAD_BASE 0x01c23000
|
|
||||||
#define A1X_TZPC_BASE 0x01c23400
|
|
||||||
#define A1X_SID_BASE 0x01c23800
|
|
||||||
#define A1X_SJTAG_BASE 0x01c23c00
|
|
||||||
|
|
||||||
#define A1X_TP_BASE 0x01c25000
|
|
||||||
#define A1X_PMU_BASE 0x01c25400
|
|
||||||
#define A1X_CPUCFG_BASE 0x01c25c00 /* sun7i only ? */
|
|
||||||
|
|
||||||
#define A1X_UART0_BASE 0x01c28000
|
|
||||||
#define A1X_UART1_BASE 0x01c28400
|
|
||||||
#define A1X_UART2_BASE 0x01c28800
|
|
||||||
#define A1X_UART3_BASE 0x01c28c00
|
|
||||||
#define A1X_UART4_BASE 0x01c29000
|
|
||||||
#define A1X_UART5_BASE 0x01c29400
|
|
||||||
#define A1X_UART6_BASE 0x01c29800
|
|
||||||
#define A1X_UART7_BASE 0x01c29c00
|
|
||||||
#define A1X_PS2_0_BASE 0x01c2a000
|
|
||||||
#define A1X_PS2_1_BASE 0x01c2a400
|
|
||||||
|
|
||||||
#define A1X_TWI0_BASE 0x01c2ac00
|
|
||||||
#define A1X_TWI1_BASE 0x01c2b000
|
|
||||||
#define A1X_TWI2_BASE 0x01c2b400
|
|
||||||
|
|
||||||
#define A1X_CAN_BASE 0x01c2bc00
|
|
||||||
|
|
||||||
#define A1X_SCR_BASE 0x01c2c400
|
|
||||||
|
|
||||||
#define A1X_GPS_BASE 0x01c30000
|
|
||||||
#define A1X_MALI400_BASE 0x01c40000
|
|
||||||
|
|
||||||
/* module sram */
|
|
||||||
#define A1X_SRAM_C_BASE 0x01d00000
|
|
||||||
|
|
||||||
#define A1X_DE_FE0_BASE 0x01e00000
|
|
||||||
#define A1X_DE_FE1_BASE 0x01e20000
|
|
||||||
#define A1X_DE_BE0_BASE 0x01e60000
|
|
||||||
#define A1X_DE_BE1_BASE 0x01e40000
|
|
||||||
#define A1X_MP_BASE 0x01e80000
|
|
||||||
#define A1X_AVG_BASE 0x01ea0000
|
|
||||||
|
|
||||||
/* CoreSight Debug Module */
|
|
||||||
#define A1X_CSDM_BASE 0x3f500000
|
|
||||||
|
|
||||||
#define A1X_DRAM_BASE 0x40000000 /* 2 GiB */
|
|
||||||
|
|
||||||
#define A1X_BROM_BASE 0xffff0000 /* 32 kiB */
|
|
||||||
|
|
||||||
#define A1X_CPU_CFG (A1X_TIMER_BASE + 0x13c)
|
|
||||||
|
|
||||||
#endif /* CPU_ALLWINNER_A10_MEMMAP_H */
|
|
@@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Helpers to multiplex and configure pins on Allwinner SoCs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gpio.h"
|
|
||||||
|
|
||||||
#include <device/mmio.h>
|
|
||||||
|
|
||||||
static struct a10_gpio *const gpio = (void *)GPIO_BASE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set the pad function of a single pin
|
|
||||||
*
|
|
||||||
* @param[in] port GPIO port of the pin (GPA -> GPS)
|
|
||||||
* @param[in] pin the pin number in the given port (1 -> 31)
|
|
||||||
* @param[in] pad_func The peripheral function to which to connect this pin
|
|
||||||
*/
|
|
||||||
void gpio_set_pin_func(u8 port, u8 pin, u8 pad_func)
|
|
||||||
{
|
|
||||||
u8 reg, bit;
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
if ((port > GPS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pin &= 0x1f;
|
|
||||||
reg = pin / 8;
|
|
||||||
bit = (pin % 8) * 4;
|
|
||||||
|
|
||||||
reg32 = read32(&gpio->port[port].cfg[reg]);
|
|
||||||
reg32 &= ~(0xf << bit);
|
|
||||||
reg32 |= (pad_func & 0xf) << bit;
|
|
||||||
write32(&gpio->port[port].cfg[reg], reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set the pad function of a group of pins
|
|
||||||
*
|
|
||||||
* Multiplex a group of pins to the same pad function. This is useful for
|
|
||||||
* peripherals that use the same function number for several pins. This function
|
|
||||||
* allows those pins to be set with a single call.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* gpio_set_multipin_func(GPB, (1 << 23) | (1 << 22), 2);
|
|
||||||
*
|
|
||||||
* @param[in] port GPIO port of the pin (GPA -> GPS)
|
|
||||||
* @param[in] pin_mask 32-bit mask indicating which pins to re-multiplex. For
|
|
||||||
* each set bit, the corresponding pin will be multiplexed.
|
|
||||||
* @param[in] pad_func The peripheral function to which to connect the pins
|
|
||||||
*/
|
|
||||||
void gpio_set_multipin_func(u8 port, u32 pin_mask, u8 pad_func)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
u8 reg, bit;
|
|
||||||
u32 reg32, mask_offset;
|
|
||||||
|
|
||||||
if ((port > GPS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (reg = 0; reg < 4; reg++) {
|
|
||||||
mask_offset = 8 * reg;
|
|
||||||
/* Don't run the inner loop if we're not touching any pins */
|
|
||||||
if (!(pin_mask & (0xff << mask_offset)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
reg32 = read32(&gpio->port[port].cfg[reg]);
|
|
||||||
for (j = 0; j < 8; j++) {
|
|
||||||
if (!(pin_mask & (1 << (j + mask_offset))))
|
|
||||||
continue;
|
|
||||||
bit = j * 4;
|
|
||||||
reg32 &= ~(0xf << bit);
|
|
||||||
reg32 |= (pad_func & 0xf) << bit;
|
|
||||||
}
|
|
||||||
write32(&gpio->port[port].cfg[reg], reg32);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* How we use DRAM on Allwinner CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <symbols.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Put CBMEM at top of RAM
|
|
||||||
*/
|
|
||||||
static inline void *a1x_get_cbmem_top(void)
|
|
||||||
{
|
|
||||||
return _dram + (CONFIG_DRAM_SIZE_MB << 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* By CBFS cache, we mean a cached copy, in RAM, of the entire CBFS region.
|
|
||||||
*/
|
|
||||||
static inline void *a1x_get_cbfs_cache_top(void)
|
|
||||||
{
|
|
||||||
/* Arbitrary 16 MiB gap for cbmem tables and bouncebuffer */
|
|
||||||
return a1x_get_cbmem_top() - (16 << 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *a1x_get_cbfs_cache_base(void)
|
|
||||||
{
|
|
||||||
return a1x_get_cbfs_cache_top() - CONFIG_ROM_SIZE;
|
|
||||||
}
|
|
@@ -1,478 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
|
|
||||||
* Copyright (C) 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
|
|
||||||
* Copyright (C) 2007-2012 Allwinner Technology Co., Ltd.
|
|
||||||
* Berg Xing <bergxing@allwinnertech.com>
|
|
||||||
* Tom Cubie <tangliang@allwinnertech.com>
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Allwinner A10 DRAM controller initialization
|
|
||||||
*
|
|
||||||
* Based on sun4i Linux kernel sources mach-sunxi/pm/standby/dram*.c
|
|
||||||
* and earlier U-Boot Allwiner A10 SPL work
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clock.h"
|
|
||||||
#include "dramc.h"
|
|
||||||
#include "memmap.h"
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
#include <device/mmio.h>
|
|
||||||
#include <delay.h>
|
|
||||||
|
|
||||||
static struct a1x_dramc *const dram = (void *)A1X_DRAMC_BASE;
|
|
||||||
|
|
||||||
static void mctl_ddr3_reset(void)
|
|
||||||
{
|
|
||||||
if (a1x_get_cpu_chip_revision() != A1X_CHIP_REV_A) {
|
|
||||||
setbits_le32(&dram->mcr, DRAM_MCR_RESET);
|
|
||||||
udelay(2);
|
|
||||||
clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
|
|
||||||
} else {
|
|
||||||
clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
|
|
||||||
udelay(2);
|
|
||||||
setbits_le32(&dram->mcr, DRAM_MCR_RESET);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mctl_set_drive(void)
|
|
||||||
{
|
|
||||||
clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3),
|
|
||||||
DRAM_MCR_MODE_EN(0x3) | 0xffc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mctl_itm_disable(void)
|
|
||||||
{
|
|
||||||
clrsetbits_le32(&dram->ccr, DRAM_CCR_INIT, DRAM_CCR_ITM_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mctl_itm_enable(void)
|
|
||||||
{
|
|
||||||
clrbits_le32(&dram->ccr, DRAM_CCR_ITM_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mctl_enable_dll0(u32 phase)
|
|
||||||
{
|
|
||||||
clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
|
|
||||||
((phase >> 16) & 0x3f) << 6);
|
|
||||||
clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE);
|
|
||||||
udelay(2);
|
|
||||||
|
|
||||||
clrbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET | DRAM_DLLCR_DISABLE);
|
|
||||||
udelay(22);
|
|
||||||
|
|
||||||
clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_DISABLE, DRAM_DLLCR_NRESET);
|
|
||||||
udelay(22);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: This differs from pm/standby in that it checks the bus width
|
|
||||||
*/
|
|
||||||
static void mctl_enable_dllx(u32 phase)
|
|
||||||
{
|
|
||||||
u32 i, n, bus_width;
|
|
||||||
|
|
||||||
bus_width = read32(&dram->dcr);
|
|
||||||
|
|
||||||
if ((bus_width & DRAM_DCR_BUS_WIDTH_MASK) ==
|
|
||||||
DRAM_DCR_BUS_WIDTH(DRAM_DCR_BUS_WIDTH_32BIT))
|
|
||||||
n = DRAM_DCR_NR_DLLCR_32BIT;
|
|
||||||
else
|
|
||||||
n = DRAM_DCR_NR_DLLCR_16BIT;
|
|
||||||
|
|
||||||
for (i = 1; i < n; i++) {
|
|
||||||
clrsetbits_le32(&dram->dllcr[i], 0x4 << 14,
|
|
||||||
(phase & 0xf) << 14);
|
|
||||||
clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET,
|
|
||||||
DRAM_DLLCR_DISABLE);
|
|
||||||
phase >>= 4;
|
|
||||||
}
|
|
||||||
udelay(2);
|
|
||||||
|
|
||||||
for (i = 1; i < n; i++)
|
|
||||||
clrbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET |
|
|
||||||
DRAM_DLLCR_DISABLE);
|
|
||||||
udelay(22);
|
|
||||||
|
|
||||||
for (i = 1; i < n; i++)
|
|
||||||
clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_DISABLE,
|
|
||||||
DRAM_DLLCR_NRESET);
|
|
||||||
udelay(22);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 hpcr_value[32] = {
|
|
||||||
0x0301, 0x0301, 0x0301, 0x0301,
|
|
||||||
0x0301, 0x0301, 0, 0,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
0x1031, 0x1031, 0x0735, 0x1035,
|
|
||||||
0x1035, 0x0731, 0x1031, 0x0735,
|
|
||||||
0x1035, 0x1031, 0x0731, 0x1035,
|
|
||||||
0x1031, 0x0301, 0x0301, 0x0731
|
|
||||||
};
|
|
||||||
|
|
||||||
static void mctl_configure_hostport(void)
|
|
||||||
{
|
|
||||||
u32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < 32; i++)
|
|
||||||
write32(&dram->hpcr[i], hpcr_value[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mctl_setup_dram_clock(u32 clk)
|
|
||||||
{
|
|
||||||
/* setup DRAM PLL */
|
|
||||||
a1x_pll5_configure(clk / 24, 2, 2, 1);
|
|
||||||
|
|
||||||
/* FIXME: This bit is not documented for A10, and altering it doesn't
|
|
||||||
* seem to change anything.
|
|
||||||
*
|
|
||||||
* #define CCM_PLL5_CTRL_VCO_GAIN (0x1 << 19)
|
|
||||||
* reg_val = read32(&ccm->pll5_cfg);
|
|
||||||
* reg_val &= ~CCM_PLL5_CTRL_VCO_GAIN; // PLL VCO Gain off
|
|
||||||
* write32(reg_val, &ccm->pll5_cfg);
|
|
||||||
*/
|
|
||||||
udelay(5500);
|
|
||||||
|
|
||||||
a1x_pll5_enable_dram_clock_output();
|
|
||||||
|
|
||||||
/* reset GPS */
|
|
||||||
/* FIXME: These bits are also undocumented, and seem to have no effect
|
|
||||||
* on A10.
|
|
||||||
*
|
|
||||||
* #define CCM_GPS_CTRL_RESET (0x1 << 0)
|
|
||||||
* #define CCM_GPS_CTRL_GATE (0x1 << 1)
|
|
||||||
* clrbits_le32(&ccm->gps_clk_cfg, CCM_GPS_CTRL_RESET | CCM_GPS_CTRL_GATE);
|
|
||||||
*/
|
|
||||||
a1x_periph_clock_enable(A1X_CLKEN_GPS);
|
|
||||||
udelay(1);
|
|
||||||
a1x_periph_clock_disable(A1X_CLKEN_GPS);
|
|
||||||
|
|
||||||
/* setup MBUS clock */
|
|
||||||
/* FIXME: The MBUS does not seem to be present or do anything on A10. It
|
|
||||||
* is documented in the A13 user manual, but changing settings on A10
|
|
||||||
* has no effect.
|
|
||||||
*
|
|
||||||
* #define CCM_MBUS_CTRL_M(n) (((n) & 0xf) << 0)
|
|
||||||
* #define CCM_MBUS_CTRL_M_MASK CCM_MBUS_CTRL_M(0xf)
|
|
||||||
* #define CCM_MBUS_CTRL_M_X(n) ((n) - 1)
|
|
||||||
* #define CCM_MBUS_CTRL_N(n) (((n) & 0xf) << 16)
|
|
||||||
* #define CCM_MBUS_CTRL_N_MASK CCM_MBUS_CTRL_N(0xf)
|
|
||||||
* #define CCM_MBUS_CTRL_N_X(n) (((n) >> 3) ? 3 : (((n) >> 2) ? 2 : (((n) >> 1) ? 1 : 0)))
|
|
||||||
* #define CCM_MBUS_CTRL_CLK_SRC(n) (((n) & 0x3) << 24)
|
|
||||||
* #define CCM_MBUS_CTRL_CLK_SRC_MASK CCM_MBUS_CTRL_CLK_SRC(0x3)
|
|
||||||
* #define CCM_MBUS_CTRL_CLK_SRC_HOSC 0x0
|
|
||||||
* #define CCM_MBUS_CTRL_CLK_SRC_PLL6 0x1
|
|
||||||
* #define CCM_MBUS_CTRL_CLK_SRC_PLL5 0x2
|
|
||||||
* #define CCM_MBUS_CTRL_GATE (0x1 << 31)
|
|
||||||
* reg_val = CCM_MBUS_CTRL_GATE |
|
|
||||||
* CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) |
|
|
||||||
* CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
|
|
||||||
* CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
|
|
||||||
* write32(reg_val, &ccm->mbus_clk_cfg);
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* open DRAMC AHB & DLL register clock
|
|
||||||
* close it first
|
|
||||||
*/
|
|
||||||
a1x_periph_clock_disable(A1X_CLKEN_SDRAM);
|
|
||||||
|
|
||||||
udelay(22);
|
|
||||||
|
|
||||||
/* then open it */
|
|
||||||
a1x_periph_clock_enable(A1X_CLKEN_SDRAM);
|
|
||||||
udelay(22);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dramc_scan_readpipe(void)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
/* data training trigger */
|
|
||||||
setbits_le32(&dram->ccr, DRAM_CCR_DATA_TRAINING);
|
|
||||||
|
|
||||||
/* check whether data training process has completed */
|
|
||||||
while (read32(&dram->ccr) & DRAM_CCR_DATA_TRAINING);
|
|
||||||
|
|
||||||
/* check data training result */
|
|
||||||
reg32 = read32(&dram->csr);
|
|
||||||
if (reg32 & DRAM_CSR_FAILED)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dramc_scan_dll_para(void)
|
|
||||||
{
|
|
||||||
const u32 dqs_dly[7] = { 0x3, 0x2, 0x1, 0x0, 0xe, 0xd, 0xc };
|
|
||||||
const u32 clk_dly[15] = { 0x07, 0x06, 0x05, 0x04, 0x03,
|
|
||||||
0x02, 0x01, 0x00, 0x08, 0x10,
|
|
||||||
0x18, 0x20, 0x28, 0x30, 0x38
|
|
||||||
};
|
|
||||||
u32 clk_dqs_count[15];
|
|
||||||
u32 dqs_i, clk_i, cr_i;
|
|
||||||
u32 max_val, min_val;
|
|
||||||
u32 dqs_index, clk_index;
|
|
||||||
|
|
||||||
/* Find DQS_DLY Pass Count for every CLK_DLY */
|
|
||||||
for (clk_i = 0; clk_i < 15; clk_i++) {
|
|
||||||
clk_dqs_count[clk_i] = 0;
|
|
||||||
clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
|
|
||||||
(clk_dly[clk_i] & 0x3f) << 6);
|
|
||||||
for (dqs_i = 0; dqs_i < 7; dqs_i++) {
|
|
||||||
for (cr_i = 1; cr_i < 5; cr_i++) {
|
|
||||||
clrsetbits_le32(&dram->dllcr[cr_i],
|
|
||||||
0x4f << 14,
|
|
||||||
(dqs_dly[dqs_i] & 0x4f) << 14);
|
|
||||||
}
|
|
||||||
udelay(2);
|
|
||||||
if (dramc_scan_readpipe() == 0)
|
|
||||||
clk_dqs_count[clk_i]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Test DQS_DLY Pass Count for every CLK_DLY from up to down */
|
|
||||||
for (dqs_i = 15; dqs_i > 0; dqs_i--) {
|
|
||||||
max_val = 15;
|
|
||||||
min_val = 15;
|
|
||||||
for (clk_i = 0; clk_i < 15; clk_i++) {
|
|
||||||
if (clk_dqs_count[clk_i] == dqs_i) {
|
|
||||||
max_val = clk_i;
|
|
||||||
if (min_val == 15)
|
|
||||||
min_val = clk_i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (max_val < 15)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if Find a CLK_DLY failed */
|
|
||||||
if (!dqs_i)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Find the middle index of CLK_DLY */
|
|
||||||
clk_index = (max_val + min_val) >> 1;
|
|
||||||
if ((max_val == (15 - 1)) && (min_val > 0))
|
|
||||||
/* if CLK_DLY[MCTL_CLK_DLY_COUNT] is very good, then the middle
|
|
||||||
* value can be more close to the max_val
|
|
||||||
*/
|
|
||||||
clk_index = (15 + clk_index) >> 1;
|
|
||||||
else if ((max_val < (15 - 1)) && (min_val == 0))
|
|
||||||
/* if CLK_DLY[0] is very good, then the middle value can be more
|
|
||||||
* close to the min_val
|
|
||||||
*/
|
|
||||||
clk_index >>= 1;
|
|
||||||
if (clk_dqs_count[clk_index] < dqs_i)
|
|
||||||
clk_index = min_val;
|
|
||||||
|
|
||||||
/* Find the middle index of DQS_DLY for the CLK_DLY got above, and Scan
|
|
||||||
* read pipe again
|
|
||||||
*/
|
|
||||||
clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
|
|
||||||
(clk_dly[clk_index] & 0x3f) << 6);
|
|
||||||
max_val = 7;
|
|
||||||
min_val = 7;
|
|
||||||
for (dqs_i = 0; dqs_i < 7; dqs_i++) {
|
|
||||||
clk_dqs_count[dqs_i] = 0;
|
|
||||||
for (cr_i = 1; cr_i < 5; cr_i++) {
|
|
||||||
clrsetbits_le32(&dram->dllcr[cr_i],
|
|
||||||
0x4f << 14,
|
|
||||||
(dqs_dly[dqs_i] & 0x4f) << 14);
|
|
||||||
}
|
|
||||||
udelay(2);
|
|
||||||
if (dramc_scan_readpipe() == 0) {
|
|
||||||
clk_dqs_count[dqs_i] = 1;
|
|
||||||
max_val = dqs_i;
|
|
||||||
if (min_val == 7)
|
|
||||||
min_val = dqs_i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max_val < 7) {
|
|
||||||
dqs_index = (max_val + min_val) >> 1;
|
|
||||||
if ((max_val == (7 - 1)) && (min_val > 0))
|
|
||||||
dqs_index = (7 + dqs_index) >> 1;
|
|
||||||
else if ((max_val < (7 - 1)) && (min_val == 0))
|
|
||||||
dqs_index >>= 1;
|
|
||||||
if (!clk_dqs_count[dqs_index])
|
|
||||||
dqs_index = min_val;
|
|
||||||
for (cr_i = 1; cr_i < 5; cr_i++) {
|
|
||||||
clrsetbits_le32(&dram->dllcr[cr_i],
|
|
||||||
0x4f << 14,
|
|
||||||
(dqs_dly[dqs_index] & 0x4f) << 14);
|
|
||||||
}
|
|
||||||
udelay(2);
|
|
||||||
return dramc_scan_readpipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
|
||||||
clrbits_le32(&dram->dllcr[0], 0x3f << 6);
|
|
||||||
for (cr_i = 1; cr_i < 5; cr_i++)
|
|
||||||
clrbits_le32(&dram->dllcr[cr_i], 0x4f << 14);
|
|
||||||
udelay(2);
|
|
||||||
|
|
||||||
return dramc_scan_readpipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dramc_set_autorefresh_cycle(u32 clk)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
u32 tmp_val;
|
|
||||||
u32 reg_dcr;
|
|
||||||
|
|
||||||
if (clk < 600) {
|
|
||||||
reg_dcr = read32(&dram->dcr);
|
|
||||||
if ((reg_dcr & DRAM_DCR_CHIP_DENSITY_MASK) <=
|
|
||||||
DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M))
|
|
||||||
reg32 = (131 * clk) >> 10;
|
|
||||||
else
|
|
||||||
reg32 = (336 * clk) >> 10;
|
|
||||||
|
|
||||||
tmp_val = (7987 * clk) >> 10;
|
|
||||||
tmp_val = tmp_val * 9 - 200;
|
|
||||||
reg32 |= tmp_val << 8;
|
|
||||||
reg32 |= 0x8 << 24;
|
|
||||||
write32(&dram->drr, reg32);
|
|
||||||
} else {
|
|
||||||
write32(&dram->drr, 0x0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long dramc_init(struct dram_para *para)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
int ret_val;
|
|
||||||
|
|
||||||
/* check input dram parameter structure */
|
|
||||||
if (!para)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* setup DRAM relative clock */
|
|
||||||
mctl_setup_dram_clock(para->clock);
|
|
||||||
|
|
||||||
/* reset external DRAM */
|
|
||||||
mctl_ddr3_reset();
|
|
||||||
|
|
||||||
mctl_set_drive();
|
|
||||||
|
|
||||||
/* dram clock off */
|
|
||||||
a1x_gate_dram_clock_output();
|
|
||||||
|
|
||||||
/* select dram controller 1 */
|
|
||||||
write32(&dram->csel, DRAM_CSEL_MAGIC);
|
|
||||||
|
|
||||||
mctl_itm_disable();
|
|
||||||
mctl_enable_dll0(para->tpr3);
|
|
||||||
|
|
||||||
/* configure external DRAM */
|
|
||||||
reg32 = 0x0;
|
|
||||||
if (para->type == DRAM_MEMORY_TYPE_DDR3)
|
|
||||||
reg32 |= DRAM_DCR_TYPE_DDR3;
|
|
||||||
reg32 |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);
|
|
||||||
|
|
||||||
if (para->density == 256)
|
|
||||||
reg32 |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_256M);
|
|
||||||
else if (para->density == 512)
|
|
||||||
reg32 |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_512M);
|
|
||||||
else if (para->density == 1024)
|
|
||||||
reg32 |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M);
|
|
||||||
else if (para->density == 2048)
|
|
||||||
reg32 |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_2048M);
|
|
||||||
else if (para->density == 4096)
|
|
||||||
reg32 |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_4096M);
|
|
||||||
else if (para->density == 8192)
|
|
||||||
reg32 |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_8192M);
|
|
||||||
else
|
|
||||||
reg32 |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_256M);
|
|
||||||
|
|
||||||
reg32 |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
|
|
||||||
reg32 |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
|
|
||||||
reg32 |= DRAM_DCR_CMD_RANK_ALL;
|
|
||||||
reg32 |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE);
|
|
||||||
write32(&dram->dcr, reg32);
|
|
||||||
|
|
||||||
/* dram clock on */
|
|
||||||
a1x_ungate_dram_clock_output();
|
|
||||||
|
|
||||||
udelay(1);
|
|
||||||
|
|
||||||
while (read32(&dram->ccr) & DRAM_CCR_INIT);
|
|
||||||
|
|
||||||
mctl_enable_dllx(para->tpr3);
|
|
||||||
|
|
||||||
/* set odt impendance divide ratio */
|
|
||||||
reg32 = ((para->zq) >> 8) & 0xfffff;
|
|
||||||
reg32 |= ((para->zq) & 0xff) << 20;
|
|
||||||
reg32 |= (para->zq) & 0xf0000000;
|
|
||||||
write32(&dram->zqcr0, reg32);
|
|
||||||
|
|
||||||
/* set I/O configure register */
|
|
||||||
reg32 = 0x00cc0000;
|
|
||||||
reg32 |= (para->odt_en) & 0x3;
|
|
||||||
reg32 |= ((para->odt_en) & 0x3) << 30;
|
|
||||||
write32(&dram->iocr, reg32);
|
|
||||||
|
|
||||||
/* set refresh period */
|
|
||||||
dramc_set_autorefresh_cycle(para->clock);
|
|
||||||
|
|
||||||
/* set timing parameters */
|
|
||||||
write32(&dram->tpr0, para->tpr0);
|
|
||||||
write32(&dram->tpr1, para->tpr1);
|
|
||||||
write32(&dram->tpr2, para->tpr2);
|
|
||||||
|
|
||||||
if (para->type == DRAM_MEMORY_TYPE_DDR3) {
|
|
||||||
reg32 = DRAM_MR_BURST_LENGTH(0x0);
|
|
||||||
reg32 |= DRAM_MR_CAS_LAT(para->cas - 4);
|
|
||||||
reg32 |= DRAM_MR_WRITE_RECOVERY(0x5);
|
|
||||||
} else if (para->type == DRAM_MEMORY_TYPE_DDR2) {
|
|
||||||
reg32 = DRAM_MR_BURST_LENGTH(0x2);
|
|
||||||
reg32 |= DRAM_MR_CAS_LAT(para->cas);
|
|
||||||
reg32 |= DRAM_MR_WRITE_RECOVERY(0x5);
|
|
||||||
}
|
|
||||||
write32(&dram->mr, reg32);
|
|
||||||
|
|
||||||
write32(&dram->emr, para->emr1);
|
|
||||||
write32(&dram->emr2, para->emr2);
|
|
||||||
write32(&dram->emr3, para->emr3);
|
|
||||||
|
|
||||||
/* set DQS window mode */
|
|
||||||
clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE);
|
|
||||||
|
|
||||||
/* reset external DRAM */
|
|
||||||
setbits_le32(&dram->ccr, DRAM_CCR_INIT);
|
|
||||||
while (read32(&dram->ccr) & DRAM_CCR_INIT);
|
|
||||||
|
|
||||||
/* scan read pipe value */
|
|
||||||
mctl_itm_enable();
|
|
||||||
if (para->tpr3 & (0x1 << 31)) {
|
|
||||||
ret_val = dramc_scan_dll_para();
|
|
||||||
if (ret_val == 0)
|
|
||||||
para->tpr3 =
|
|
||||||
(((read32(&dram->dllcr[0]) >> 6) & 0x3f) << 16) |
|
|
||||||
(((read32(&dram->dllcr[1]) >> 14) & 0xf) << 0) |
|
|
||||||
(((read32(&dram->dllcr[2]) >> 14) & 0xf) << 4) |
|
|
||||||
(((read32(&dram->dllcr[3]) >> 14) & 0xf) << 8) |
|
|
||||||
(((read32(&dram->dllcr[4]) >> 14) & 0xf) << 12);
|
|
||||||
} else {
|
|
||||||
ret_val = dramc_scan_readpipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret_val < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* configure all host port */
|
|
||||||
mctl_configure_hostport();
|
|
||||||
|
|
||||||
return para->size;
|
|
||||||
}
|
|
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Timer control and delays for Allwinner CPUs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <device/mmio.h>
|
|
||||||
#include <delay.h>
|
|
||||||
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
struct a1x_timer_module *const timer_module = (void *)A1X_TIMER_BASE;
|
|
||||||
struct a1x_timer *const tmr0 =
|
|
||||||
&((struct a1x_timer_module *)A1X_TIMER_BASE)->timer[0];
|
|
||||||
|
|
||||||
static inline u32 read_timer(void)
|
|
||||||
{
|
|
||||||
return read32(&tmr0->val);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_timer(void)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
/* Load the timer rollover value */
|
|
||||||
write32(&tmr0->interval, 0xffffffff);
|
|
||||||
/* Configure the timer to run from 24MHz oscillator, no prescaler */
|
|
||||||
reg32 = TIMER_CTRL_PRESC_DIV_EXP(0);
|
|
||||||
reg32 |= TIMER_CTRL_CLK_SRC_OSC24M;
|
|
||||||
reg32 |= TIMER_CTRL_RELOAD;
|
|
||||||
reg32 |= TIMER_CTRL_TMR_EN;
|
|
||||||
write32(&tmr0->ctrl, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
void udelay(unsigned usec)
|
|
||||||
{
|
|
||||||
u32 curr_tick, last_tick;
|
|
||||||
s32 ticks_left;
|
|
||||||
|
|
||||||
last_tick = read_timer();
|
|
||||||
/* 24 timer ticks per microsecond (24 MHz, divided by 1) */
|
|
||||||
ticks_left = usec * 24;
|
|
||||||
|
|
||||||
/* FIXME: Should we consider timer rollover?
|
|
||||||
* From when we start the timer, we have almost three minutes before it
|
|
||||||
* rolls over, so we should be long into having booted our payload.
|
|
||||||
*/
|
|
||||||
while (ticks_left > 0) {
|
|
||||||
curr_tick = read_timer();
|
|
||||||
/* Timer value decreases with each tick */
|
|
||||||
ticks_left -= last_tick - curr_tick;
|
|
||||||
last_tick = curr_tick;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function has nothing to do with timers; however, the chip revision
|
|
||||||
* register is in the timer module, so keep this function here.
|
|
||||||
*/
|
|
||||||
u8 a1x_get_cpu_chip_revision(void)
|
|
||||||
{
|
|
||||||
write32(&timer_module->cpu_cfg, 0);
|
|
||||||
return (read32(&timer_module->cpu_cfg) >> 6) & 0x3;
|
|
||||||
}
|
|
@@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007-2011 Allwinner Technology Co., Ltd.
|
|
||||||
* Tom Cubie <tangliang@allwinnertech.com>
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Definitions for timer control on Allwinner CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPU_ALLWINNER_A10_TIMER_H
|
|
||||||
#define CPU_ALLWINNER_A10_TIMER_H
|
|
||||||
|
|
||||||
#include "memmap.h"
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
/* TMRx_CTRL values */
|
|
||||||
#define TIMER_CTRL_MODE_SINGLE (1 << 7)
|
|
||||||
#define TIMER_CTRL_PRESC_MASK (0x7 << 4)
|
|
||||||
#define TIMER_CTRL_PRESC_DIV_EXP(ep) ((ep << 4) & TIMER_CTRL_PRESC_MASK)
|
|
||||||
#define TIMER_CTRL_CLK_SRC_MASK (0x3 << 2)
|
|
||||||
#define TIMER_CTRL_CLK_SRC_LOSC (0x0 << 2)
|
|
||||||
#define TIMER_CTRL_CLK_SRC_OSC24M (0x1 << 2)
|
|
||||||
#define TIMER_CTRL_CLK_SRC_PLL6 (0x2 << 2)
|
|
||||||
#define TIMER_CTRL_RELOAD (1 << 1)
|
|
||||||
#define TIMER_CTRL_TMR_EN (1 << 0)
|
|
||||||
|
|
||||||
/* Chip revision definitions (found in CPU_CFG register) */
|
|
||||||
#define A1X_CHIP_REV_A 0x0
|
|
||||||
#define A1X_CHIP_REV_C1 0x1
|
|
||||||
#define A1X_CHIP_REV_C2 0x2
|
|
||||||
#define A1X_CHIP_REV_B 0x3
|
|
||||||
|
|
||||||
|
|
||||||
/* General purpose timer */
|
|
||||||
struct a1x_timer {
|
|
||||||
u32 ctrl;
|
|
||||||
u32 interval;
|
|
||||||
u32 val;
|
|
||||||
u8 res[4];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Audio video sync*/
|
|
||||||
struct a1x_avs {
|
|
||||||
u32 ctrl; /* 0x80 */
|
|
||||||
u32 cnt0; /* 0x84 */
|
|
||||||
u32 cnt1; /* 0x88 */
|
|
||||||
u32 div; /* 0x8c */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Watchdog */
|
|
||||||
struct a1x_wdog {
|
|
||||||
u32 ctrl; /* 0x90 */
|
|
||||||
u32 mode; /* 0x94 */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* 64 bit counter */
|
|
||||||
struct a1x_64cnt {
|
|
||||||
u32 ctrl; /* 0xa0 */
|
|
||||||
u32 lo; /* 0xa4 */
|
|
||||||
u32 hi; /* 0xa8 */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Rtc */
|
|
||||||
struct a1x_rtc {
|
|
||||||
u32 ctrl; /* 0x100 */
|
|
||||||
u32 yymmdd; /* 0x104 */
|
|
||||||
u32 hhmmss; /* 0x108 */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Alarm */
|
|
||||||
struct a1x_alarm {
|
|
||||||
u32 ddhhmmss; /* 0x10c */
|
|
||||||
u32 hhmmss; /* 0x110 */
|
|
||||||
u32 en; /* 0x114 */
|
|
||||||
u32 irq_en; /* 0x118 */
|
|
||||||
u32 irq_sta; /* 0x11c */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct a1x_timer_module {
|
|
||||||
u32 irq_en; /* 0x00 */
|
|
||||||
u32 irq_sta; /* 0x04 */
|
|
||||||
u8 res1[8];
|
|
||||||
struct a1x_timer timer[6]; /* We have 6 timers */
|
|
||||||
u8 res2[16];
|
|
||||||
struct a1x_avs avs;
|
|
||||||
struct a1x_wdog wdog;
|
|
||||||
u8 res3[8];
|
|
||||||
struct a1x_64cnt cnt64;
|
|
||||||
u8 res4[0x58];
|
|
||||||
struct a1x_rtc rtc;
|
|
||||||
struct a1x_alarm alarm;
|
|
||||||
u32 gp_data[4];
|
|
||||||
u8 res5[8];
|
|
||||||
u32 cpu_cfg;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
u8 a1x_get_cpu_chip_revision(void);
|
|
||||||
|
|
||||||
#endif /* CPU_ALLWINNER_A10_TIMER_H */
|
|
@@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Setup helpers for Two Wire Interface (TWI) (I2C) Allwinner CPUs
|
|
||||||
*
|
|
||||||
* Only functionality for I2C master is provided.
|
|
||||||
* Largely based on the uboot-sunxi code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <device/mmio.h>
|
|
||||||
#include <delay.h>
|
|
||||||
#include <device/i2c_simple.h>
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
#include "memmap.h"
|
|
||||||
#include "twi.h"
|
|
||||||
|
|
||||||
#define TWI_BASE(n) (A1X_TWI0_BASE + 0x400 * (n))
|
|
||||||
|
|
||||||
#define TWI_TIMEOUT (50 * 1000)
|
|
||||||
|
|
||||||
static u8 is_busy(struct a1x_twi *twi)
|
|
||||||
{
|
|
||||||
return (read32(&twi->stat) != TWI_STAT_IDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cb_err wait_until_idle(struct a1x_twi *twi)
|
|
||||||
{
|
|
||||||
u32 i = TWI_TIMEOUT;
|
|
||||||
while (i-- && is_busy((twi)))
|
|
||||||
udelay(1);
|
|
||||||
return i ? CB_SUCCESS : CB_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: This function is basic, and unintelligent */
|
|
||||||
static void configure_clock(struct a1x_twi *twi, u32 speed_hz)
|
|
||||||
{
|
|
||||||
/* FIXME: We assume clock is 24MHz, which may not be the case */
|
|
||||||
u32 apb_clk = 24000000, m, n;
|
|
||||||
|
|
||||||
/* Pre-divide the clock by 8 */
|
|
||||||
n = 3;
|
|
||||||
m = (apb_clk >> n) / speed_hz;
|
|
||||||
write32(&twi->clk, TWI_CLK_M(m) | TWI_CLK_N(n));
|
|
||||||
}
|
|
||||||
|
|
||||||
void a1x_twi_init(u8 bus, u32 speed_hz)
|
|
||||||
{
|
|
||||||
u32 i = TWI_TIMEOUT;
|
|
||||||
struct a1x_twi *twi = (void *)TWI_BASE(bus);
|
|
||||||
|
|
||||||
configure_clock(twi, speed_hz);
|
|
||||||
|
|
||||||
/* Enable the I2C bus */
|
|
||||||
write32(&twi->ctl, TWI_CTL_BUS_EN);
|
|
||||||
/* Issue soft reset */
|
|
||||||
write32(&twi->reset, 1);
|
|
||||||
|
|
||||||
while (i-- && read32(&twi->reset))
|
|
||||||
udelay(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_interrupt_flag(struct a1x_twi *twi)
|
|
||||||
{
|
|
||||||
write32(&twi->ctl, read32(&twi->ctl) & ~TWI_CTL_INT_FLAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_send_data(struct a1x_twi *twi, u8 data)
|
|
||||||
{
|
|
||||||
write32(&twi->data, data);
|
|
||||||
clear_interrupt_flag(twi);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum twi_status wait_for_status(struct a1x_twi *twi)
|
|
||||||
{
|
|
||||||
u32 i = TWI_TIMEOUT;
|
|
||||||
/* Wait until interrupt is asserted again */
|
|
||||||
while (i-- && !(read32(&twi->ctl) & TWI_CTL_INT_FLAG))
|
|
||||||
udelay(1);
|
|
||||||
/* A timeout here most likely indicates a bus error */
|
|
||||||
return i ? read32(&twi->stat) : TWI_STAT_BUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_send_start(struct a1x_twi *twi)
|
|
||||||
{
|
|
||||||
u32 reg32, i;
|
|
||||||
|
|
||||||
/* Send START condition */
|
|
||||||
reg32 = read32(&twi->ctl);
|
|
||||||
reg32 &= ~TWI_CTL_INT_FLAG;
|
|
||||||
reg32 |= TWI_CTL_M_START;
|
|
||||||
write32(&twi->ctl, reg32);
|
|
||||||
|
|
||||||
/* M_START is automatically cleared after condition is transmitted */
|
|
||||||
i = TWI_TIMEOUT;
|
|
||||||
while (i-- && (read32(&twi->ctl) & TWI_CTL_M_START))
|
|
||||||
udelay(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_send_stop(struct a1x_twi *twi)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
/* Send STOP condition */
|
|
||||||
reg32 = read32(&twi->ctl);
|
|
||||||
reg32 &= ~TWI_CTL_INT_FLAG;
|
|
||||||
reg32 |= TWI_CTL_M_STOP;
|
|
||||||
write32(&twi->ctl, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int i2c_read(struct a1x_twi *twi, uint8_t chip,
|
|
||||||
uint8_t *buf, size_t len)
|
|
||||||
{
|
|
||||||
unsigned count = len;
|
|
||||||
enum twi_status expected_status;
|
|
||||||
|
|
||||||
/* Send restart for read */
|
|
||||||
i2c_send_start(twi);
|
|
||||||
if (wait_for_status(twi) != TWI_STAT_TX_RSTART)
|
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
/* Send chip address */
|
|
||||||
i2c_send_data(twi, chip << 1 | 1);
|
|
||||||
if (wait_for_status(twi) != TWI_STAT_TX_AR_ACK)
|
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
/* Start ACK-ing received data */
|
|
||||||
setbits_le32(&twi->ctl, TWI_CTL_A_ACK);
|
|
||||||
expected_status = TWI_STAT_RXD_ACK;
|
|
||||||
|
|
||||||
/* Read data */
|
|
||||||
while (count > 0) {
|
|
||||||
if (count == 1) {
|
|
||||||
/* Do not ACK the last byte */
|
|
||||||
clrbits_le32(&twi->ctl, TWI_CTL_A_ACK);
|
|
||||||
expected_status = TWI_STAT_RXD_NAK;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_interrupt_flag(twi);
|
|
||||||
|
|
||||||
if (wait_for_status(twi) != expected_status)
|
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
*buf++ = read32(&twi->data);
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int i2c_write(struct a1x_twi *twi, uint8_t chip,
|
|
||||||
const uint8_t *buf, size_t len)
|
|
||||||
{
|
|
||||||
size_t count = len;
|
|
||||||
|
|
||||||
i2c_send_start(twi);
|
|
||||||
if (wait_for_status(twi) != TWI_STAT_TX_START)
|
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
/* Send chip address */
|
|
||||||
i2c_send_data(twi, chip << 1);
|
|
||||||
if (wait_for_status(twi) != TWI_STAT_TX_AW_ACK)
|
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
/* Send data */
|
|
||||||
while (count > 0) {
|
|
||||||
i2c_send_data(twi, *buf++);
|
|
||||||
if (wait_for_status(twi) != TWI_STAT_TXD_ACK)
|
|
||||||
return CB_ERR;
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int platform_i2c_transfer(unsigned bus, struct i2c_msg *segments, int count)
|
|
||||||
{
|
|
||||||
int i, ret = CB_SUCCESS;
|
|
||||||
struct i2c_msg *seg = segments;
|
|
||||||
struct a1x_twi *twi = (void *)TWI_BASE(bus);
|
|
||||||
|
|
||||||
|
|
||||||
if (wait_until_idle(twi) != CB_SUCCESS)
|
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
seg = segments + i;
|
|
||||||
|
|
||||||
if (seg->flags & I2C_M_RD) {
|
|
||||||
ret = i2c_read(twi, seg->slave, seg->buf, seg->len);
|
|
||||||
if (ret < 0)
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ret = i2c_write(twi, seg->slave, seg->buf, seg->len);
|
|
||||||
if (ret < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't worry about the status. STOP is on a best-effort basis */
|
|
||||||
i2c_send_stop(twi);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Definitions Two Wire Interface (TWI) (I2C) Allwinner CPUs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPU_ALLWINNER_A10_TWI_H
|
|
||||||
#define CPU_ALLWINNER_A10_TWI_H
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
/* TWI_CTL values */
|
|
||||||
#define TWI_CTL_INT_EN (1 << 7)
|
|
||||||
#define TWI_CTL_BUS_EN (1 << 6)
|
|
||||||
#define TWI_CTL_M_START (1 << 5)
|
|
||||||
#define TWI_CTL_M_STOP (1 << 4)
|
|
||||||
#define TWI_CTL_INT_FLAG (1 << 3)
|
|
||||||
#define TWI_CTL_A_ACK (1 << 2)
|
|
||||||
|
|
||||||
/* TWI_STAT values */
|
|
||||||
enum twi_status {
|
|
||||||
TWI_STAT_BUS_ERROR = 0x00, /**< Bus error */
|
|
||||||
TWI_STAT_TX_START = 0x08, /**< START sent */
|
|
||||||
TWI_STAT_TX_RSTART = 0x10, /**< Repeated START sent */
|
|
||||||
TWI_STAT_TX_AW_ACK = 0x18, /**< Sent address+read, ACK */
|
|
||||||
TWI_STAT_TX_AW_NAK = 0x20, /**< Sent address+read, NAK */
|
|
||||||
TWI_STAT_TXD_ACK = 0x28, /**< Sent data, got ACK */
|
|
||||||
TWI_STAT_TXD_NAK = 0x30, /**< Sent data, no ACK */
|
|
||||||
TWI_STAT_LOST_ARB = 0x38, /**< Lost arbitration */
|
|
||||||
TWI_STAT_TX_AR_ACK = 0x40, /**< Sent address+write, ACK */
|
|
||||||
TWI_STAT_TX_AR_NAK = 0x48, /**< Sent address+write, NAK */
|
|
||||||
TWI_STAT_RXD_ACK = 0x50, /**< Got data, sent ACK */
|
|
||||||
TWI_STAT_RXD_NAK = 0x58, /**< Got data, no ACK */
|
|
||||||
TWI_STAT_IDLE = 0xf8, /**< Bus idle*/
|
|
||||||
};
|
|
||||||
|
|
||||||
/* TWI_CLK values */
|
|
||||||
#define TWI_CLK_M_MASK (0xf << 3)
|
|
||||||
#define TWI_CLK_M(m) (((m - 1) << 3) & TWI_CLK_M_MASK)
|
|
||||||
#define TWI_CLK_N_MASK (0x7 << 0)
|
|
||||||
#define TWI_CLK_N(n) ((n) & TWI_CLK_N_MASK)
|
|
||||||
|
|
||||||
struct a1x_twi {
|
|
||||||
u32 addr; /**< 0x00: Slave address */
|
|
||||||
u32 xaddr; /**< 0x04: Extended slave address */
|
|
||||||
u32 data; /**< 0x08: Data byte */
|
|
||||||
u32 ctl; /**< 0x0C: Control register */
|
|
||||||
u32 stat; /**< 0x10: Status register */
|
|
||||||
u32 clk; /**< 0x14: Clock control register */
|
|
||||||
u32 reset; /**< 0x18: Software reset */
|
|
||||||
u32 efr; /**< 0x1C: Enhanced Feature register */
|
|
||||||
u32 lcr; /**< 0x20: Line control register */
|
|
||||||
};
|
|
||||||
|
|
||||||
void a1x_twi_init(u8 bus, u32 speed_hz);
|
|
||||||
|
|
||||||
#endif /* CPU_ALLWINNER_A10_TWI_H */
|
|
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Uart setup helpers for Allwinner SoCs
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uart.h"
|
|
||||||
#include <device/mmio.h>
|
|
||||||
#include <console/uart.h>
|
|
||||||
#include <drivers/uart/uart8250reg.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Configure line control settings for UART
|
|
||||||
*/
|
|
||||||
static void a10_uart_configure(struct a10_uart *uart, u32 baud_rate, u8 data_bits,
|
|
||||||
enum uart_parity parity, u8 stop_bits)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
u16 div;
|
|
||||||
|
|
||||||
div = (u16) uart_baudrate_divisor(baud_rate,
|
|
||||||
uart_platform_refclk(), 16);
|
|
||||||
/* Enable access to Divisor Latch register */
|
|
||||||
write32(&uart->lcr, UART8250_LCR_DLAB);
|
|
||||||
/* Set baudrate */
|
|
||||||
write32(&uart->dlh, (div >> 8) & 0xff);
|
|
||||||
write32(&uart->dll, div & 0xff);
|
|
||||||
/* Set line control */
|
|
||||||
reg32 = (data_bits - 5) & UART8250_LCR_WLS_MSK;
|
|
||||||
switch (parity) {
|
|
||||||
case UART_PARITY_ODD:
|
|
||||||
reg32 |= UART8250_LCR_PEN;
|
|
||||||
break;
|
|
||||||
case UART_PARITY_EVEN:
|
|
||||||
reg32 |= UART8250_LCR_PEN;
|
|
||||||
reg32 |= UART8250_LCR_EPS;
|
|
||||||
break;
|
|
||||||
case UART_PARITY_NONE: /* Fall through */
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
write32(&uart->lcr, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void a10_uart_enable_fifos(struct a10_uart *uart)
|
|
||||||
{
|
|
||||||
write32(&uart->fcr, UART8250_FCR_FIFO_EN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tx_fifo_full(struct a10_uart *uart)
|
|
||||||
{
|
|
||||||
/* This may be a misnomer, or a typo in the datasheet. THRE indicates
|
|
||||||
* that the TX register is empty, not that the FIFO is not full, but
|
|
||||||
* this may be due to a datasheet typo. Keep the current name to signal
|
|
||||||
* intent. */
|
|
||||||
return !(read32(&uart->lsr) & UART8250_LSR_THRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rx_fifo_empty(struct a10_uart *uart)
|
|
||||||
{
|
|
||||||
return !(read32(&uart->lsr) & UART8250_LSR_DR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Read a single byte from the UART.
|
|
||||||
*
|
|
||||||
* Blocks until at least a byte is available.
|
|
||||||
*/
|
|
||||||
static u8 a10_uart_rx_blocking(struct a10_uart *uart)
|
|
||||||
{
|
|
||||||
while (rx_fifo_empty(uart));
|
|
||||||
|
|
||||||
return read32(&uart->rbr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Write a single byte to the UART.
|
|
||||||
*
|
|
||||||
* Blocks until there is space in the FIFO.
|
|
||||||
*/
|
|
||||||
static void a10_uart_tx_blocking(struct a10_uart *uart, u8 data)
|
|
||||||
{
|
|
||||||
while (tx_fifo_full(uart));
|
|
||||||
|
|
||||||
return write32(&uart->thr, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void uart_init(int idx)
|
|
||||||
{
|
|
||||||
struct a10_uart *uart_base = uart_platform_baseptr(idx);
|
|
||||||
|
|
||||||
/* Use default 8N1 encoding */
|
|
||||||
a10_uart_configure(uart_base, get_uart_baudrate(),
|
|
||||||
8, UART_PARITY_NONE, 1);
|
|
||||||
a10_uart_enable_fifos(uart_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char uart_rx_byte(int idx)
|
|
||||||
{
|
|
||||||
return a10_uart_rx_blocking(uart_platform_baseptr(idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
void uart_tx_byte(int idx, unsigned char data)
|
|
||||||
{
|
|
||||||
a10_uart_tx_blocking(uart_platform_baseptr(idx), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uart_tx_flush(int idx)
|
|
||||||
{
|
|
||||||
}
|
|
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Definitions for UART on Allwinner CPUs
|
|
||||||
*
|
|
||||||
* The UART on the A10 seems to be 8250-compatible, however, this has not been
|
|
||||||
* verified. Our 8250mem code is specific to x86, and does not yet work, so we
|
|
||||||
* have to re-implement it ARM-style for the time being. The register
|
|
||||||
* definitions are present in <uart7250.h>, and are not redefined here.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPU_ALLWINNER_A10_UART_H
|
|
||||||
#define CPU_ALLWINNER_A10_UART_H
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
struct a10_uart {
|
|
||||||
union {
|
|
||||||
/* operational mode */
|
|
||||||
u32 rbr; /* receiver buffer (read) */
|
|
||||||
u32 thr; /* transmit holding (write) */
|
|
||||||
/* config mode (DLAB set) */
|
|
||||||
u32 dll; /* divisor latches low */
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
/* operational mode */
|
|
||||||
u32 ier; /* interrupt enable */
|
|
||||||
/* config mode (DLAB set) */
|
|
||||||
u32 dlh; /* divisor latches high */
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
u32 iir; /* interrupt ID (read) */
|
|
||||||
u32 fcr; /* FIFO control (write) */
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 lcr; /* line control */
|
|
||||||
|
|
||||||
/* 0x10 */
|
|
||||||
u32 mcr; /* modem control */
|
|
||||||
u32 lsr; /* line status, read-only */
|
|
||||||
u32 msr; /* modem status */
|
|
||||||
u32 sch; /* scratch register */
|
|
||||||
|
|
||||||
u8 reserved_0x20[0x50];
|
|
||||||
|
|
||||||
/* 0x70 */
|
|
||||||
u8 reserved_0x70[0xc];
|
|
||||||
u32 usr; /* UART status register */
|
|
||||||
|
|
||||||
/* 0x80 */
|
|
||||||
u32 tfl; /* Transmit FIFO level */
|
|
||||||
u32 rfl; /* Receive FIFO level */
|
|
||||||
u8 reserved_0x88[0x18];
|
|
||||||
|
|
||||||
/* 0xa0 */
|
|
||||||
u8 reserved_0xa0[4];
|
|
||||||
u32 halt; /* Halt register */
|
|
||||||
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
enum uart_parity {
|
|
||||||
UART_PARITY_NONE,
|
|
||||||
UART_PARITY_EVEN,
|
|
||||||
UART_PARITY_ODD,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CPU_ALLWINNER_A10_UART_H */
|
|
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright 2013 Google Inc.
|
|
||||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* Glue to UART code to enable serial console
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
#include <console/uart.h>
|
|
||||||
#include <boot/coreboot_tables.h>
|
|
||||||
|
|
||||||
#include "memmap.h"
|
|
||||||
|
|
||||||
uintptr_t uart_platform_base(int idx)
|
|
||||||
{
|
|
||||||
/* UART blocks are mapped 0x400 bytes apart */
|
|
||||||
if (idx < 8)
|
|
||||||
return A1X_UART0_BASE + 0x400 * idx;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: We assume clock is 24MHz, which may not be the case. */
|
|
||||||
unsigned int uart_platform_refclk(void)
|
|
||||||
{
|
|
||||||
return 24000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __PRE_RAM__
|
|
||||||
void uart_fill_lb(void *data)
|
|
||||||
{
|
|
||||||
struct lb_serial serial;
|
|
||||||
serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
|
|
||||||
serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
|
|
||||||
serial.baud = get_uart_baudrate();
|
|
||||||
serial.regwidth = 1;
|
|
||||||
serial.input_hertz = uart_platform_refclk();
|
|
||||||
serial.uart_pci_addr = 0;
|
|
||||||
lb_add_serial(&serial, data);
|
|
||||||
|
|
||||||
lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
|
|
||||||
}
|
|
||||||
#endif
|
|
@@ -7,12 +7,8 @@ romstage-y += ../car/romstage.c
|
|||||||
postcar-y += tsc_freq.c
|
postcar-y += tsc_freq.c
|
||||||
|
|
||||||
ramstage-y += acpi.c
|
ramstage-y += acpi.c
|
||||||
ramstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
|
|
||||||
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
|
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
|
||||||
|
|
||||||
romstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
|
|
||||||
postcar-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
|
|
||||||
|
|
||||||
smm-y += finalize.c
|
smm-y += finalize.c
|
||||||
smm-y += tsc_freq.c
|
smm-y += tsc_freq.c
|
||||||
|
|
||||||
|
@@ -118,15 +118,9 @@
|
|||||||
/* Data is passed through bits 31:0 of the data register. */
|
/* Data is passed through bits 31:0 of the data register. */
|
||||||
#define BIOS_MAILBOX_DATA 0x5da0
|
#define BIOS_MAILBOX_DATA 0x5da0
|
||||||
|
|
||||||
/* Region of SMM space is reserved for multipurpose use. It falls below
|
|
||||||
* the IED region and above the SMM handler. */
|
|
||||||
#define RESERVED_SMM_SIZE CONFIG_SMM_RESERVED_SIZE
|
|
||||||
#define RESERVED_SMM_OFFSET \
|
|
||||||
(CONFIG_SMM_TSEG_SIZE - CONFIG_IED_REGION_SIZE - RESERVED_SMM_SIZE)
|
|
||||||
|
|
||||||
/* Sanity check config options. */
|
/* Sanity check config options. */
|
||||||
#if (CONFIG_SMM_TSEG_SIZE <= (CONFIG_IED_REGION_SIZE + RESERVED_SMM_SIZE))
|
#if (CONFIG_SMM_TSEG_SIZE <= (CONFIG_IED_REGION_SIZE + CONFIG_SMM_RESERVED_SIZE))
|
||||||
# error "CONFIG_SMM_TSEG_SIZE <= (CONFIG_IED_REGION_SIZE + RESERVED_SMM_SIZE)"
|
# error "CONFIG_SMM_TSEG_SIZE <= (CONFIG_IED_REGION_SIZE + CONFIG_SMM_RESERVED_SIZE)"
|
||||||
#endif
|
#endif
|
||||||
#if (CONFIG_SMM_TSEG_SIZE < 0x800000)
|
#if (CONFIG_SMM_TSEG_SIZE < 0x800000)
|
||||||
# error "CONFIG_SMM_TSEG_SIZE must at least be 8MiB"
|
# error "CONFIG_SMM_TSEG_SIZE must at least be 8MiB"
|
||||||
|
@@ -250,7 +250,7 @@ static void fill_in_relocation_params(struct device *dev,
|
|||||||
params->ied_size = tseg_size - params->smram_size;
|
params->ied_size = tseg_size - params->smram_size;
|
||||||
|
|
||||||
/* Adjust available SMM handler memory size. */
|
/* Adjust available SMM handler memory size. */
|
||||||
params->smram_size -= RESERVED_SMM_SIZE;
|
params->smram_size -= CONFIG_SMM_RESERVED_SIZE;
|
||||||
|
|
||||||
/* SMRR has 32-bits of valid address aligned to 4KiB. */
|
/* SMRR has 32-bits of valid address aligned to 4KiB. */
|
||||||
params->smrr_base.lo = (params->smram_base & rmask) | MTRR_TYPE_WRBACK;
|
params->smrr_base.lo = (params->smram_base & rmask) | MTRR_TYPE_WRBACK;
|
||||||
|
@@ -21,7 +21,6 @@ config CPU_SPECIFIC_OPTIONS
|
|||||||
select CPU_INTEL_COMMON
|
select CPU_INTEL_COMMON
|
||||||
select NO_FIXED_XIP_ROM_SIZE
|
select NO_FIXED_XIP_ROM_SIZE
|
||||||
select PARALLEL_MP
|
select PARALLEL_MP
|
||||||
select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
|
|
||||||
|
|
||||||
config BOOTBLOCK_CPU_INIT
|
config BOOTBLOCK_CPU_INIT
|
||||||
string
|
string
|
||||||
|
@@ -19,10 +19,6 @@ ramstage-y += acpi.c
|
|||||||
|
|
||||||
smm-y += finalize.c
|
smm-y += finalize.c
|
||||||
|
|
||||||
romstage-y += stage_cache.c
|
|
||||||
ramstage-y += stage_cache.c
|
|
||||||
postcar-y += stage_cache.c
|
|
||||||
|
|
||||||
cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-25-*)
|
cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-25-*)
|
||||||
|
|
||||||
cpu_incs-y += $(src)/cpu/intel/car/non-evict/cache_as_ram.S
|
cpu_incs-y += $(src)/cpu/intel/car/non-evict/cache_as_ram.S
|
||||||
|
@@ -80,16 +80,9 @@ void set_power_limits(u8 power_limit_1_time);
|
|||||||
int cpu_config_tdp_levels(void);
|
int cpu_config_tdp_levels(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Region of SMM space is reserved for multipurpose use. It falls below
|
|
||||||
* the IED region and above the SMM handler.
|
|
||||||
*/
|
|
||||||
#define RESERVED_SMM_SIZE CONFIG_SMM_RESERVED_SIZE
|
|
||||||
#define RESERVED_SMM_OFFSET (CONFIG_SMM_TSEG_SIZE - RESERVED_SMM_SIZE)
|
|
||||||
|
|
||||||
/* Sanity check config options. */
|
/* Sanity check config options. */
|
||||||
#if (CONFIG_SMM_TSEG_SIZE <= RESERVED_SMM_SIZE)
|
#if (CONFIG_SMM_TSEG_SIZE <= CONFIG_SMM_RESERVED_SIZE)
|
||||||
# error "CONFIG_SMM_TSEG_SIZE <= RESERVED_SMM_SIZE"
|
# error "CONFIG_SMM_TSEG_SIZE <= CONFIG_SMM_RESERVED_SIZE"
|
||||||
#endif
|
#endif
|
||||||
#if (CONFIG_SMM_TSEG_SIZE < 0x800000)
|
#if (CONFIG_SMM_TSEG_SIZE < 0x800000)
|
||||||
# error "CONFIG_SMM_TSEG_SIZE must at least be 8MiB"
|
# error "CONFIG_SMM_TSEG_SIZE must at least be 8MiB"
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the coreboot project.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Google, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cbmem.h>
|
|
||||||
#include <stage_cache.h>
|
|
||||||
#include <cpu/intel/smm/gen1/smi.h>
|
|
||||||
#include "model_2065x.h"
|
|
||||||
|
|
||||||
void stage_cache_external_region(void **base, size_t *size)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
|
|
||||||
* The top of RAM is defined to be the TSEG base address.
|
|
||||||
*/
|
|
||||||
*size = RESERVED_SMM_SIZE;
|
|
||||||
*base = (void *)((uintptr_t)northbridge_get_tseg_base()
|
|
||||||
+ RESERVED_SMM_OFFSET);
|
|
||||||
}
|
|
@@ -19,7 +19,6 @@ config CPU_SPECIFIC_OPTIONS
|
|||||||
#select AP_IN_SIPI_WAIT
|
#select AP_IN_SIPI_WAIT
|
||||||
select TSC_SYNC_MFENCE
|
select TSC_SYNC_MFENCE
|
||||||
select CPU_INTEL_COMMON
|
select CPU_INTEL_COMMON
|
||||||
select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
|
|
||||||
select PARALLEL_MP
|
select PARALLEL_MP
|
||||||
select NO_FIXED_XIP_ROM_SIZE
|
select NO_FIXED_XIP_ROM_SIZE
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user