Merge remote-tracking branch 'upstream/master' into system76_cleanup

This commit is contained in:
Jeremy Soller
2019-08-09 09:52:58 -06:00
895 changed files with 13804 additions and 8561 deletions

2
3rdparty/blobs vendored

2
3rdparty/vboot vendored

14
AUTHORS Normal file
View 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

View File

@@ -148,7 +148,6 @@ mv build/coreboot.rom.new build/coreboot.rom
<li>Edit the src/soc/&lt;Vendor&gt;/&lt;Chip Family&gt;/memmap.c file <li>Edit the src/soc/&lt;Vendor&gt;/&lt;Chip Family&gt;/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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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.

View 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
```

View File

@@ -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)

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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)

View 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/

Binary file not shown.

View 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

View 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

View 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

View File

@@ -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:

View File

@@ -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

View File

@@ -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 $< $@

View File

@@ -0,0 +1,2 @@
CONFIG_BOARD_EMULATION_QEMU_RISCV_RV64=y
CONFIG_RISCV_OPENSBI=y

View File

@@ -0,0 +1,2 @@
CONFIG_VENDOR_UP=y
CONFIG_VBOOT=y

View File

@@ -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.

View File

@@ -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)" \

View File

@@ -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"

View File

@@ -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

View File

@@ -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) \

View File

@@ -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

View File

@@ -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)

View File

@@ -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])

View File

@@ -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 = {

View File

@@ -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++)

View File

@@ -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

View File

@@ -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);
/** @} */ /** @} */
/** /**

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
} }

View 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;
}

View File

@@ -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
View 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");
}

View File

@@ -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);

View File

@@ -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>

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);
/* /*

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}; };

View File

@@ -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;

View File

@@ -1 +0,0 @@
source src/cpu/allwinner/a10/Kconfig

View File

@@ -1 +0,0 @@
subdirs-$(CONFIG_CPU_ALLWINNER_A10) += a10

View File

@@ -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

View File

@@ -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, $^) $@

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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__ */

View File

@@ -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 */

View File

@@ -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,
};

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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)
{
}

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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);
}

View File

@@ -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