Compare commits

...

451 Commits

Author SHA1 Message Date
Sravan Balaji
e41716575c Fan Curve Adjustment to avoid CPU Throttling
- Modify fan curve to avoid CPU throttling
- Reduce fan curve cooldown time for oryp7
2024-10-06 17:08:07 -04:00
Tim Crawford
3d8204c3f4 Require Intel for PECI, add empty AMD power module
PECI is an Intel-only mechanism for getting CPU temp. AMD will use
SB-TSI to get temps.

Add empty power functions for AMD so the project will compile with AMD
selected.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-09-05 17:19:42 -06:00
Tim Crawford
2c6977bc6b Add config for host platform
Introduce a new config to determine the host platform and use it to
conditionally include power sequence logic.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-09-05 17:19:42 -06:00
Tim Crawford
ae63a9e3fb fan: Replace interpolation, smoothing with stepping
Fan noise is one of the top complaints reported. The existing
interpolation and smoothing logic has not sufficiently addressed the
issues with fans changing speeds too quickly in response to rapid
changes in thermals (particularly from PECI).

This behavior can be observed by with very basic tasks, such as:

- Powering on a system and logging into GNOME
- Starting a GUI application such as Firefox

Replace them with a fixed step update per event interval. Fans now have
a maximum amount they change change over time (3.9%/sec) as they move
towards a target duty.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-08-29 08:44:23 -06:00
Tim Crawford
88ad52491a Use CTR0 for max fan
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-08-29 08:44:23 -06:00
Tim Crawford
85cd3aa9ce Move fan-specific PWM logic to fan module
Better define the scope of the tachometer variables by moving them to
the fan module. `fan_update_duty` is renamed to `fan_event` to reflect
that it handles more than just updating the PWM duties.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-08-29 08:44:23 -06:00
Tim Crawford
710b4795fb Sync fans based on temp instead of duty
Fans may be different sizes, placed in asymmetrical positions, or have
different amounts of venting through the chassis. These characteristics
affect the ability for each fan, separately, to dissipate heat and
generate noise.

Replace syncing fans to the highest duty calculated for each fan, based
on separate thermal sensors, to using the highest reported temperature
across all sensors to calculate each fan's duty for that highest
temperature.

In other words: The old behavior synced fans based on the *output* value
(duty), while this new behavior syncs fans based on the *input* value
(temperature).

This allows tuning fans separately to better manage total system
thermals and mitigate noise.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-08-15 09:34:36 -06:00
Tim Crawford
2925376b6b bonw15-b: Add new Bonobo
The new Bonobo has the same pin layout as the original bonw15, but
uses the larger IT5570E-256 instead of keeping the IT5570E-128.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-08-07 11:36:53 -06:00
Tim Crawford
51d35cb272 Remove GPH7 on IT8587E
On IT8587E, pin 3 is VBAT and not a GPIO pin.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-29 18:41:30 -06:00
Tim Crawford
716efd4eb5 kbscan: Work around IT8587E hang
IT8587E is hanging when reading the keyboard matrix.

- Increasing the delay does not fix it
- Placing delays between KSO* writes does not fix it
- Code generated by SDCC looks valid to me

Rewriting it like this does fix it, although I don't know why.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-29 17:17:46 +02:00
Tim Crawford
984428b6a8 darp10: Add custom fan points
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-26 14:04:11 -06:00
Tim Crawford
0f7642defb Use a 16-bit system tick
The maximum interval when configured for a 1ms tick:

- 16-bit: ~65 seconds
- 32-bit: ~49.7 days

The value is used for scheduling and timeouts, and not to track the
uptime of the system, so the 32-bit value is excessive.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-25 11:38:35 -06:00
Tim Crawford
9e7f1952fa Add enum for PECI command codes
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-24 08:06:59 -06:00
Tim Crawford
face381354 Require boards to declare fan points
Thermal properties of each model differ and they should not rely on an
arbitrary, unoptimized set of fan points.

It is one thing to copy the points from the previous generation for a
model, as a lot of the time the chassis design is nearly identical, but
it should be always be explicit.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
a7bd81432e fan: Allow FAN2 without dGPU
Fully support fan points for the second fan on darp10.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
ffd0b7cbde fan: Do not make functions reentrant
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
e75a2f1e10 Improve handling of second fan
Replace hard-coded PWM channels with defines so the second fan on darp10
can be handled like the second fan on units with a dGPU.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
f8697a7ec4 Make fan names more generic
darp10 demonstrates that a board without a dGPU may still have a second
fan, so rename the CPU (PECI) fan to FAN1 and dGPU fan to FAN2.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
ceba69d7fa Refactor reading thermals, updating fan duty
Move the fan-related logic from the PECI and dGPU modules to the fan
module. The PECI and dGPU modules are now only responsible for reading
the thermal data, and the fan module handles calculating and updating
the fans duties based on that data.
2024-07-17 16:28:39 -06:00
Tim Crawford
e01536005a peci: Perform offset calculation in temp function
Have peci_get_temp() return the actual temp instead of the offset,
requiring the caller to make another calculation for the temp.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
8f88c0c7aa dgpu: Split out getting temp to a function
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
80cfa91b9f acpi: Report RPM values instead of raw tachometer values
Ref: IT5570E V0.3.2 datasheet; 7.12.3.2 Manual Fan Control Mode
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 16:28:39 -06:00
Tim Crawford
2a44e03a40 Update Rust toolchain config
Remove rust-src as it is not required. Use a minimal profile with
clippy and rustfmt installed, instead of the default profile, as
rust-docs is not needed.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-17 13:00:13 -06:00
Tim Crawford
70c8678a5f tool: Add error for write locked
Add a new error for the case of trying to flash when security is enabled
and it is still locked and update the related docs.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-15 11:49:32 -06:00
Tim Crawford
54d795480c ci: Show memory layout
I regularly use the `.mem` file to determine the impact changes have on
the RAM and flash usage. Print it as part of CI so I can easily see it
for all boards.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-12 08:17:26 -06:00
Tim Crawford
426dc99f10 tool: Update clap to 4.5
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-10 13:20:53 -06:00
Tim Crawford
1e02be1cbe Format with uncrustify
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-03 15:58:28 -06:00
Tim Crawford
d3894392d5 Replace clang-format with uncrustify
LLVM/clang is not used for any compilation due to it not supporting the
8-bit architectures we use (MCS-51, AVR). This means we are effectively
installing 250+ MiB of dependencies for a C formatting tool.

Replace it with uncrustify, which uses only ~600 KiB of space and has
more granular control of formatting (800+ options).

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-03 15:58:28 -06:00
Tim Crawford
6c3b34ee6e ci: Update runner to Ubuntu 24.04
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-03 15:58:28 -06:00
Tim Crawford
3d09a0b546 Conditionally compile dGPU support
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-07-03 13:47:40 -06:00
Jeremy Soller
5b0766a209 USe debounce bit and do not use interrupts for touchpad 2024-06-21 18:18:02 -06:00
Jeremy Soller
d88a175e23 Clear PS/2 touchpad status when waiting for write to finish 2024-06-21 18:18:02 -06:00
Tim Crawford
2c5c708569 oryp12: Fix USB-PD config
Fixes: 1e4667f1d3 ("Conditionally compile USB-PD support")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-06-17 17:12:38 -06:00
Tim Crawford
a67b0c98b8 lemp13-b: Remove GPB7
Fixes: f79f4d1157 ("Remove GPB7 on IT5570E")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-06-17 16:38:22 -06:00
Tim Crawford
f79f4d1157 Remove GPB7 on IT5570E
On IT5570E, pin A1 is VSTBY0 and not a GPIO pin.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-06-17 15:37:01 -06:00
Tim Crawford
1e4667f1d3 Conditionally compile USB-PD support
Boards may not have USB-PD. Remove the need for a "none" option by only
adding USB-PD sources when enabled.

The resulting binary for boards with USB-PD enabled (addw3, bonw15,
serw13) are identical. The binary for boards without USB-PD now have the
empty calls optimized out.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-06-17 14:52:34 -06:00
Tim Crawford
fc3bad29a2 pnp: Match EC2I programming guide
Use the sequence specified by the flowcharts in the ITE manuals.

Ref: IT5570E V0.3.2 datasheet; 7.15.5 EC2I Programming Guide
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-05-17 10:02:22 -06:00
Tim Crawford
8382c81b9d tool: Update Rust toolchain to nightly-2024-05-11
Update toolchain to match the version used in Redox.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-05-17 09:57:27 -06:00
Jeremy Soller
09c5a3b5f0 lemp13-b: use darp10-b keymap 2024-05-17 08:34:54 -06:00
Jeremy Soller
b4768ed2dd Add lemp13-b 2024-05-17 08:34:54 -06:00
Tim Crawford
88c77aa1d3 darp10-b: Add custom keymap
The darp10-b replaces the display toggle with mic mute like other newer
units.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-05-07 14:35:29 -06:00
Jeremy Soller
522284e5d5 Add darp10-b 2024-05-07 14:35:29 -06:00
Tim Crawford
e7ad77898b darp10: Add custom keymap
The customer units for darp10 will have custom keyboard with the alt
legend on Num / removed.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-05-07 14:35:29 -06:00
Tim Crawford
b744529960 [HACK] darp10: Set FAN2 duty to FAN1
This model has a second CPU fan connected to PWM3.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-05-07 14:35:29 -06:00
Tim Crawford
748ec13132 darp10: Add Darter Pro 10
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-05-07 14:35:29 -06:00
Tim Crawford
38d4666a90 oryp12: Use OZ26786 charger
Ref: Schematics sheet 58 ("AC In Charger")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-21 13:32:38 -06:00
Tim Crawford
637036ec02 oryp12: Enable security
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-19 17:22:49 -06:00
Tim Crawford
6a40a54932 oryp12: Add Oryx Pro 12
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-19 14:28:24 -06:00
Jeremy Soller
91b8c48773 Add lemp13 2024-03-19 13:22:24 -06:00
Jeremy Soller
90af96faf5 eSPI: debug all vwire indexes 2024-03-19 13:22:24 -06:00
Jeremy Soller
17aae5af71 Update ecspy 2024-03-19 13:22:24 -06:00
Tim Crawford
6aced2fd57 ci: Update actions/checkout to v4
Fixes the following warnings in Actions:

    Node.js 16 actions are deprecated. Please update the following
    actions to use Node.js 20: actions/checkout@v3.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-18 14:27:58 -06:00
Tim Crawford
16e4f93f2c Mark pointed-to data const where possible
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-18 14:27:36 -06:00
Tim Crawford
9fb08ffa46 Mark pointers as const
Resulting binaries are identical.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-18 14:27:36 -06:00
Tim Crawford
d60a8e4c8e scripts: Remove explicit rustup self update
Commit 17f8e37ed5 ("Convert toolchain file to TOML syntax") switched
from the bare toolchain file to the TOML-based one for better management
of the toolchain and components used.

Commit 1cb61e6918 ("deps.sh: Update rustup or inform user of env
vars") added an explicit `rustup self update` because there were still
cases, a year later, of people not having a rustup new enough to support
the TOML-based toolchain file.

Now 2 years after that, it should be safe to drop the explicit self
update. The TOML format has widespread adoption and rustup now self
updates by default. This should allow distro-provided rustup, which
disables the self update feature, to work if it is already installed in
place of the one downloaded from https://rustup.rs.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-18 14:20:31 -06:00
Jeremy Soller
8c52c313e1 addw4: improved fan curve 2024-03-11 08:54:13 -06:00
Tim Crawford
8af7fd5bad addw4: Enable security
Development is sufficiently far along that this can default to enabled.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-01 11:15:40 -07:00
Tim Crawford
2174b4593a addw4: Enable KBLED support
Fixes: fff6208f98 ("Conditionally compile KBLED support")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-03-01 09:44:34 -07:00
Tim Crawford
fff6208f98 Conditionally compile KBLED support
Remove the need for a "none" option by only adding KBLED sources when
enabled.

The resulting binaries with KBLED enabled (all of them) are identical.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-02-28 13:20:23 -07:00
Tim Crawford
ecac574671 addw4: Add Adder WS 4
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-02-28 11:40:32 -07:00
Tim Crawford
acf67d4413 tool: Assume ROM size is total flash size
Remove the hard-coded assumption that the EC is always 128K, as ITE
chips can also be 256K (which Clevo has started using since addw4).
Instead assume the ROM is correctly sized, which we do since
0d83819a21 ("Pad binary file to total flash size") and proprietary
firmware has always done.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-02-28 11:40:32 -07:00
Tim Crawford
183778c32f make: Fix printing error if BOARD unset
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-02-28 11:40:32 -07:00
Tim Crawford
82b9e19746 time: Replace hard-coded values with macro
This is more descriptive than the comment and allows for changing
values, such as using a chip with a different clock frequency.

The resulting binary is identical.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-02-26 09:06:05 -07:00
Tim Crawford
449bafd130 main: Remove empty switch case
SDCC 4.4.0 now fails to compile if there are empty switch cases.

    src/board/system76/common/main.c:105: error 110: conditional flow changed by optimizer: so said EVELYN the modified DOG

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-02-24 21:03:21 -07:00
Tim Crawford
ef4eeae2df ite: Add support for 256K flash
The upcoming addw4 will use the IT5570E-256, which requires removing the
assumption that every ITE chip is 128K. Introduce new configs so boards
may select which flash size they use.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-01-25 13:26:43 -07:00
Tim Crawford
4b86176659 main: Replace MOD with bitwise AND
This prevents `moduint` from being called for the superloop.

A bitwise AND is used instead of using the equivalent `% 4` as an
indication that modulo should not be used, as not using a power of 2
(which is optimized) will result in an expensive call to SDCC library
functions.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-01-05 15:04:28 -07:00
Tim Crawford
766fb738a0 kbscan: Remove unused array
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-01-04 15:05:40 -07:00
Tim Crawford
0ccb8079ae kbscan: Do not read matrix if lid is closed
Pull the lid check out to the loop to avoid accessing the matrix when we
know we do not need the data. It is left in kbscan (instead of simply
disabling reading) to clear the state of the matrix data.

The lid check for wake is removed as it will never be true.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-01-04 15:05:40 -07:00
Tim Crawford
0e1a748b16 kbscan: Disable reading columns at init
The functionality is split into a separate function to optimize the use
case for each.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-01-04 11:55:56 -07:00
Tim Crawford
11b1e724b5 docs: Add note about write lock for flashing
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2024-01-03 09:45:34 -07:00
Ian Douglas Scott
47b070418a ectool: Use clap derive syntax
Co-authored-by: Tim Crawford <tcrawford@system76.com>
2023-12-08 16:04:37 -07:00
Tim Crawford
cbad8e09be smfi: Remove always true conditional
SDCC 4.3.3 (terribly) reports this as an error:

    src/board/system76/common/smfi.c:244: error 110: conditional flow changed by optimizer: so said EVELYN the modified DOG

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-19 08:02:41 -06:00
Tim Crawford
713e1d9681 Add void to function declarations with no args
SDCC 4.3.3 complains about the declaration not matching the prototype:

    error 283: function declarator with no prototype

Add `void` to the AVR functions as well, even though no warning is
issued by GCC.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-19 08:02:41 -06:00
Tim Crawford
01be30f107 Only support building a single board at a time
As a follow up to c461e20df3 ("make: Remove version from build output
path"), only support building a single version of a single board by
default. The build directory can still be specified by passing `BUILD`.

Fixes running the `clean` target when `BUILD` is a custom value or
`BOARD` isn't set.

Fixes: b03c960b4f ("make: Reduce build output")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-12 12:49:43 -06:00
Tim Crawford
946415f3a7 peci: Add timeouts to infinitely blocking waits
Add timeouts to the legacy PECI implementation to prevent the EC locking
up when PECI stops working, such as during S0ix opportunistic suspend.

This is not the optimal solution, as PECI should not be available at all
to cause the lock up in the first place, but it at least prevents the
issue.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-12 09:09:20 -06:00
Tim Crawford
a3fb9e1c77 avr: Fix compiling with GCC 13
Apply the CFLAGS workaround for GCC 13.

The issue is fixed in GCC 14, so only 12 and 13 are affected.

Ref: 84fe76cad4 ("avr: Fix compiling with GCC 12")
Ref: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-06 13:58:27 -06:00
Tim Crawford
166e03972b tool: Derive Eq, PartialEq on enums
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-05 14:32:15 -06:00
Tim Crawford
4fa389e1bd tool: Fix clippy warnings
Fix:

- clippy::unnecessary_cast
- clippy::needless_borrow

Allow:

- clippy::uninlined_format_args
- clippy::get_first

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-05 14:32:15 -06:00
Tim Crawford
782f18a3f6 tool: Update toolchain, edition, deps
- Update toolchain to nightly-2023-09-07
- Update edition to 2021
- Update deps

`OpenHidDeviceError` is deprecated, and is removed in newer versions.
Replace it with `HidApiErrorEmpty`, because there are no descriptions
for what anything means so I just picked one that didn't require fields.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-05 14:32:15 -06:00
Tim Crawford
c461e20df3 make: Remove version from build output path
Support building only a single version for a model. This removes the
need to determine the git commit hash and date in order to access build
artifacts.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-10-03 09:40:42 -06:00
Matt Parnell
bb1ce2273b fix sdcc 4.3.0 #14184 build error - error 283: function declarator with no prototype 2023-09-20 09:36:34 -06:00
Tim Crawford
181d4c5d59 kbscan: Increase debounce time from 5ms to 10ms
Some users are reporting that a debounce time of 5ms is not enough to
prevent keys from registering twice. Split the difference between the
old and the new debounce times and set it to 10ms.

Ref: https://github.com/system76/firmware-open/issues/471
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-09-07 17:14:44 -06:00
Jeremy Soller
1097fd999a Do not force charging if end threshold is not set 2023-08-17 17:55:04 -06:00
Tim Crawford
34dd9ccbac battery: Disable charger if full or not on AC
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-08-17 17:55:04 -06:00
Jeremy Soller
894b82d4fb Set default battery start threshold to 90% 2023-08-17 17:55:04 -06:00
Tim Crawford
dc482dd11a Add basic support for IT5571E
The IT5571E is nearly identical to the IT5570E.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-08-15 08:24:02 -06:00
Winston Hoy
13dd6a1038 Update debugging.md 2023-08-02 09:14:35 -06:00
Winston Hoy
c0bfb257db Update debugging.md 2023-08-02 09:14:35 -06:00
Winston Hoy
8d844cf966 add console_internal debugging instructions 2023-08-02 09:14:35 -06:00
Tim Crawford
01907011bb Add a FnLock key
Implement a FnLock toggle that behaves as follows:

- Disabled: F1-F12 are normal
- Enabled: F1-F12 are the alternate function

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-08-01 14:39:59 -06:00
Tim Crawford
b63e2092ce peci: Check PECI available based on eSPI usage
If eSPI is used, use Virtual Wires to determine if PECI is available.

Fixes incorrectly reporting PECI as available on systems using S0ix, as
the CPU would be in C10 but `PLTRST#` would not be asserted.

Requires enabling `HOST_C10` reporting in FSP-S.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-08-01 14:24:21 -06:00
Tim Crawford
ebc5168cb0 Remove the use of symlinks
Replace symlinks with directories with `board.mk`, using relative paths
to include the files rather than duplicate them.

This allows making board-specific changes without affecting other
boards, such as when firmware security had to be enabled on galp6 when
it was enabled on galp7 (2d5cbadf71).

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-31 09:06:23 -06:00
Tim Crawford
9b7c6704c3 docs: Build with mdBook
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-31 09:05:53 -06:00
Tim Crawford
bd291871f4 Rename doc/ to docs/
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-31 09:05:53 -06:00
Tim Crawford
9302a30a2d pmc: Add interrupt control and enable registers
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-31 09:04:52 -06:00
Tim Crawford
459e5a3614 ec/ite: Add WUC functions to handle interrupts
Add functions to enable, disable, and clear an interrupt.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-31 09:04:20 -06:00
Tim Crawford
120ed1e2c5 ec/ite: Add INTC functions to handle interrupts
Add functions to enable, disable, and clear an interrupt.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-31 09:04:20 -06:00
Tim Crawford
d4ecd8a79a kbscan: Remove comparing matrix to keymap
Remove checking against the real keys declared in the keymap. It appears
to have no effect on behavior.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-28 20:07:24 -06:00
Tim Crawford
0f2ff7e540 kbscan: Switch from GPIO mode to KBS (Normal) mode
Use the default mode for reading the keyboard scan matrix when being
used as a keyboard. There should be no perceived change in behavior, but
should make the code easier to understand.

Note: `KSO[17:16]` are configured by `GPCRC` on boards that use them.
They are now set to alternate function to use in KBS mode rather than
GPIO mode, with the pull-up enabled to prevent them from floating when
configured as open-drain.

As part of this change, we now only read the hardware matrix state once
upfront, instead of on every iteration through the loop applying the
logic.

Tested by verifying that typing still works on darp9.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-28 20:07:24 -06:00
Tim Crawford
546458e368 kbscan: Return early if debouncing
A single timer is used for debouncing all keys, so there is no reason to
perform any operations if the matrix is being debounced. Just return
early and remove some of the convoluted logic.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-25 13:03:25 -06:00
Tim Crawford
8a1adc2bdc Enable power switch WDT on IT5570E boards
Enable PWRSW WDT 2 and use the default timeout of 10 seconds.

Allows forcing an EC reset in case it gets into an invalid state.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-22 06:35:42 -06:00
Tim Crawford
45520646aa power: Reset KBC on CPU reset
Ensure the keyboard controller is not left locked/disabled.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-22 06:32:07 -06:00
Tim Crawford
de546fa761 kbc: Add reset function
This function can be called after EC init to put the KBC into a known
working state.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-22 06:32:07 -06:00
Tim Crawford
0d83819a21 Pad binary file to total flash size
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-19 06:13:17 -06:00
Tim Crawford
64e5b8308d lemp: Remove pull-down from CPU fan sense
Matches the GPIO for all other boards.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-17 18:06:35 -06:00
Tim Crawford
1ebc0bc6c2 galp6: Set CPU/VGA fan sense to TACH functionality
Set D6 and D7 to ALT to use as tachometers inputs from the fans.

Matches config for all other boards.

Ref: IT5570E V0.3.2 datasheet; 7.5.4 Alternate Function Selection
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-17 18:06:35 -06:00
Tim Crawford
e093952dd2 kbscan: Reduce debounce time from 15ms to 5ms
Allows increased typing speed while avoiding repeating keys due to
contact bounce and keys being rejected by ghost key detection.

This is the default value for QMK.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-17 13:38:15 -06:00
Tim Crawford
1fded3f7bf Use %cs format when getting the commit date
From the man page:

    %cs
        committer date, short format (YYYY-MM-DD)

This is identical to what we use, without having to specify a custom
date format for it.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-07 23:20:51 -06:00
Tim Crawford
4458d5dbe2 bonw15: Set battery Rsense to 5
PRS3 is 0.005 Ohms.

However, I am unsure about this change because PRS1 and PRS2 are also
both 0.005 Ohms, but are in *parallel*.

Ref: bonw15 schematics, Charger (Sheet 70)
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-06 12:31:03 -06:00
Tim Crawford
42a19b3d6b oryp11,serw13: Set adapter Rsense to 10 milliohms
PRS1 is 5, but it is in series with PRS3, which is also 5. PRS1 by
itself is only connected to ACP/ACN.

Ref: oryp11 schematics, AC In Charger (Sheet 59)
Ref: serw13 schematics, AC_In, Charger (Sheet 70)
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-07-06 12:31:03 -06:00
Tim Crawford
dd555b9012 peci: Clear status on completion
The PECI-over-eSPI implementation, like the legacy implementation, must
acknowledge when the transaction is done by clearing the bit in the
register.

Fixes a hang during shutdown on oryp11 after unplugging a TBT display.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-21 12:44:12 -06:00
Tim Crawford
c7288a5a60 darp9,oryp11: Update keyboard
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-16 14:49:54 -06:00
Tim Crawford
8e6d938f90 Add new keyboards
Replace micmute and darp9 layouts with new keyboards.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-16 14:40:43 -06:00
Yethal
347bbf0d9a reuse make target for board list 2023-06-15 13:45:12 -06:00
Yethal
faede6264a Generate matrix from directory 2023-06-15 13:45:12 -06:00
13r0ck
fe6faa21fc Add reset command to ectool 2023-06-14 13:50:20 -06:00
Tim Crawford
485f390077 darp9: Set CC_EN high
Fixes using the non-TBT USB-C port.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-08 12:18:53 -06:00
Jeremy Soller
9b111bafc6 Fix K_MIC_MUTE keycode 2023-06-07 17:24:06 -06:00
Tim Crawford
c09960cbc6 Replace Call Mute with random key for micmute
Replace the Windows specific key with an arbitrary keycode to remap to
micmute on Linux.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
2dd33ffec5 Add "Call Mute" combo key for darp9
The proprietary firmware for the darp9 adds the mic mute hotkey using
the new "Call Mute" hotkey from Windows 11 22H2, which is mapped to
`Super+Alt+K` [1]. Match the behavior in open firmware.

[1]: https://support.microsoft.com/en-us/windows/keyboard-shortcuts-in-windows-dcc61a57-8ff0-cffe-9796-cb9706c75eec#WindowsVersion=Windows_11

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
399415fdf6 Add custom keymap for darp9
Despite the darp9 supporting an RGB backlit keyboard, the keyboard
option was removed and it ships with a white-only LED backlit keyboard
instead. The keypad `/` still has the cycle symbol printed on it, so
replace the color cycling function with the keyboard brightness
function used by other white-only LED keyboards (the 14" TKL ones).

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
9ac513128a kbled: Add a "step" function for BKL hotkey
Replace the get+set logic with a step function to change the backlight
level for `K_KBD_BKL`.

Keyboards using a DAC have a different set of levels due to the
brightness difference between the keyboards.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
4c9d3197b8 kbled: Make white_dac work like others
Make `white_dac` functions work based on the DAC power level like the
other I2C and PWM mechanisms, instead of preset values from an array.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
bfbbfe43e6 acpi: Update keyboard backlight functions
Existing FDAT values remain unchanged in their functionality.
New functionality is added to fill unused FDAT values.

FDAT values correspond to the following functionality:

- 0: Set brightness
- 1: Get brightness
- 2: Get backlight type (new)
- 3: Set color
- 4: Get color (new)
- 5: <unused>
- 6: Set brightness (duplicate)

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
598aef8c4a kbled: Check if using white or RGB keyboard
Use RGBKB-DET# to determine the type of keyboard connected.

If a white keyboard is attached, always set the color to white, and
always return white for the color.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
c71a58f7cf Add RGBKB-DET# GPIO
This GPIO can be used to detect if the connected keyboard is RGB.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Tim Crawford
e60873a82c darp9: Add Darter Pro 9
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-07 17:24:06 -06:00
Jeremy Soller
002823908a oryp9,oryp10: enable firmware security 2023-06-07 11:56:11 -06:00
Tim Crawford
498508f2f1 scripts: Disable showing signature when getting date
Fixes building when `log.showSignature` is enabled.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-06-04 13:48:35 -06:00
Jeremy Soller
f4ad9520a8 bonw15: invert USB power GPIO 2023-05-31 20:20:44 -06:00
Tim Crawford
82f091ef55 galp{6,7}: Reduce PL4 on AC to 65W
Reduce PL4 to the same value as other non-GPU units, even though the
galp7 has an H series CPU.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-05-25 10:27:42 -06:00
Tim Crawford
2d5cbadf71 galp6,galp7: Enable firmware security
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-05-18 08:56:37 -06:00
Tim Crawford
43dfbb055b Increase PL4 on battery to 45W for dGPU boards
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-05-17 10:43:26 -06:00
Tim Crawford
99dfbeaec3 power: Set PL4 based on AC state on all boards
Limit PL4 based on AC state for all units, not just those with dGPUs.
This will allow setting standard values in coreboot.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-05-17 10:43:26 -06:00
Tim Crawford
b967e7c921 Format code
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-05-15 10:25:44 -06:00
Jeremy Soller
f5c4eaba97 lemp12: hack to drain LDO_3V3 capacitors 2023-05-12 11:00:27 -06:00
Jeremy Soller
ca1996dd44 lemp12: Reset GPIO to match lemp11 2023-05-12 11:00:27 -06:00
Jeremy Soller
bc92291c26 lemp12: set PSYS current gain to 0.5uA/W 2023-05-12 11:00:27 -06:00
Jeremy Soller
e6b8eb4c42 charger/oz26786: support different PSYS current gains 2023-05-12 11:00:27 -06:00
Jeremy Soller
93c2784eb3 lemp12: adjust GPIOs some more 2023-05-12 11:00:27 -06:00
Jeremy Soller
f5c2548d04 lemp12: check and fix all GPIO config 2023-05-12 11:00:27 -06:00
Jeremy Soller
36e6059e90 lemp12: remove unused GPIOs 2023-05-12 11:00:27 -06:00
Jeremy Soller
3f4c65931a lemp12: enable firmware security 2023-05-12 11:00:27 -06:00
Jeremy Soller
55632aab7a lemp12: set PD_POWER_EN to output 2023-05-12 11:00:27 -06:00
Jeremy Soller
f80f40f006 Add lemp12 2023-05-12 11:00:27 -06:00
Tim Crawford
5d2f2fd5c0 galp7: Symlink to galp6
galp7 is a CPU refresh of galp6 and contains no EC changes.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-05-09 14:43:40 -06:00
Jeremy Soller
930f16b230 addw3, oryp11, serw13: Set VBATT_BOOST# to input 2023-04-03 13:06:16 -06:00
Jeremy Soller
d38ef1413f Fix style 2023-04-03 13:06:16 -06:00
Jeremy Soller
916c9f8c5f Fixup bonw15 gpios 2023-04-03 13:06:16 -06:00
Jeremy Soller
5d11cc14f8 bonw15: Change keyboard model to 15in_102 2023-04-03 13:06:16 -06:00
Jeremy Soller
a03ce8d1c3 Set bonw15 smart charger 2023-04-03 13:06:16 -06:00
Jeremy Soller
da9648dddb Add bonw15 2023-04-03 13:06:16 -06:00
Tim Crawford
d0596100bd serw13: Hook up USB-PD
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Jeremy Soller
cd0321bfbb Ensure smart charger uses new input current limits when detected 2023-04-03 13:06:16 -06:00
Jeremy Soller
658f24a8a8 Hack and slash until it is done 2023-04-03 13:06:16 -06:00
Jeremy Soller
7a5c111786 Set CPU power limit based on input current 2023-04-03 13:06:16 -06:00
Jeremy Soller
c5229fafab Set input current based on USB-PD charger data 2023-04-03 13:06:16 -06:00
Jeremy Soller
a5ea9f4f05 Expose input current setting 2023-04-03 13:06:16 -06:00
Jeremy Soller
49aee51343 Fix gaze17-3050 input current 2023-04-03 13:06:16 -06:00
Jeremy Soller
edcfac1050 Make INPUT_CURRENT a macro taking arguments 2023-04-03 13:06:16 -06:00
Jeremy Soller
5b55048ef3 WIP: USB-PD current detection 2023-04-03 13:06:16 -06:00
Jeremy Soller
a1f4bb55bb oryp11: Adjust fan curve 2023-04-03 13:06:16 -06:00
Jeremy Soller
cd53d28d2e oryp11: Increase DC power limit to 55W 2023-04-03 13:06:16 -06:00
Jeremy Soller
5adacc4241 serw13: Increase DC power limit to 55W 2023-04-03 13:06:16 -06:00
Jeremy Soller
4745b109d8 addw3: Increase DC power limit to 55W 2023-04-03 13:06:16 -06:00
Jeremy Soller
c76919b189 Add PD_EN to oryp11 to ensure it powers off 2023-04-03 13:06:16 -06:00
Tim Crawford
3eaa5e6e06 Only use PECI over eSPI on oryp11
Make all boards except oryp11 use the legacy PECI implementation. The
oryp11 removed the legacy pin (H_PECI) and must use PECI over eSPI.

All boards that use eSPI should switch to using PECI over eSPI once the
implementation is working correctly.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
c1c082d2cc power: Set PL4 after CPU reset
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
568fae6aba power: Remove last AC check from power_set_limit
Unconditionally set the power limit based on the current AC state when
power_set_limit is called. The contional logic to run it only on ACIN#
state change is already done in power_event.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
a198289695 Remove power_set_limit from board_event
This is already handled by power_event.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
b1bd244d49 gaze18: Set PWM pin to ALT
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Jeremy Soller
546dd30b5e Fix cold reset by using VW_SUS_PWRDN_ACK again 2023-04-03 13:06:16 -06:00
Jeremy Soller
1dd25e0bf0 Remove unnecessary config USE_S0IX from all boards 2023-04-03 13:06:16 -06:00
Jeremy Soller
8228362c5d Do not try to use peci between VW_HOST_RST_WARN and VW_PLTRST_N 2023-04-03 13:06:16 -06:00
Jeremy Soller
584e397b07 addw3, gaze18, oryp11, serw13: enable CONFIG_SECURITY 2023-04-03 13:06:16 -06:00
Jeremy Soller
86f281b410 Add ME_WE gpio for all boards 2023-04-03 13:06:16 -06:00
Jeremy Soller
4a1e0a5aa8 Add optional EC security state and documentation 2023-04-03 13:06:16 -06:00
Tim Crawford
4567f99015 peci: Clear status after command completion
Per the flow charts for PECI programming guide, clear the status
register after the command has completed.

Ref: IT5570E V0.3.2 datasheet
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
3dde812dba peci: Check FINISH for completed transaction
Per the IT5570E datasheet, FINISH should be used to check if a
transaction completed, not HOBY.

> For the polling mode, software continues reading the Host Status
> Register to check whether the transaction is completed or not (the
> Finish bit in the Host Status Register will be set when the
> transaction is completed).

Ref: IT5570E V0.3.2 datasheet
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
dd97946056 peci: Check for hardware error
Check if any hardware error bits are set instead of checking for only
command completion.

Move logging of WrPkgConfig() errors from power to peci.

Ref: IT5570E V0.3.2 datasheet
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
373dc36676 kbc: Enable Transaction Done interrupt
Step 2 for data transmission (both RX and TX) is to enable the
Transaction Done interrupt.

Ref: IT5570 V0.3.2, 7.9.3.1 Hardware Mode Selected
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
22487f737d gaze18: Set CC_EN high
Fixes using the TBT port (rear USB-C).

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Jeremy Soller
0348800411 addw3: Enable USB-C power 2023-04-03 13:06:16 -06:00
Jeremy Soller
f73160fad5 oryp11: Enable thunderbolt power 2023-04-03 13:06:16 -06:00
Jeremy Soller
4aeb3669a0 Fix formatting 2023-04-03 13:06:16 -06:00
Jeremy Soller
7587a6412d oryp11: set EC_AMP_EN high 2023-04-03 13:06:16 -06:00
Jeremy Soller
ba5438a79a Update power state prior to using PECI 2023-04-03 13:06:16 -06:00
Jeremy Soller
55df52a013 Remove unnecessary code from espi_event 2023-04-03 13:06:16 -06:00
Jeremy Soller
cb8e0971c6 PECI ESPI timeout of 10ms 2023-04-03 13:06:16 -06:00
Jeremy Soller
34ef03b19a Fix ESPI vw_get and vw_set 2023-04-03 13:06:16 -06:00
Jeremy Soller
33eaef2dd0 Reorder power plane detection 2023-04-03 13:06:16 -06:00
Jeremy Soller
0d438a3314 Make sure power_state is S0 before attempting PECI 2023-04-03 13:06:16 -06:00
Jeremy Soller
962d55309a Gate peci_available on ESPI availability 2023-04-03 13:06:16 -06:00
Jeremy Soller
fc1fda0725 Use EC_RSMRST# for S5 detection on eSPI systems as well 2023-04-03 13:06:16 -06:00
Jeremy Soller
35d3c4f161 Fix style 2023-04-03 13:06:16 -06:00
Jeremy Soller
6b80721138 oryp11: set prochot the right way 2023-04-03 13:06:16 -06:00
Jeremy Soller
a0c81f6304 Improvements for determining CPU state using virtual wires 2023-04-03 13:06:16 -06:00
Jeremy Soller
4e11f6220b Fix comparisons of vw_get values 2023-04-03 13:06:16 -06:00
Jeremy Soller
cea89a78d8 Use ESPI VW signals wherever possible 2023-04-03 13:06:16 -06:00
Jeremy Soller
a5a677ee63 oryp11: fix some GPIO configuration 2023-04-03 13:06:16 -06:00
Jeremy Soller
8c52a51af1 addw3: fix some GPIO configuration 2023-04-03 13:06:16 -06:00
Jeremy Soller
cda67e6d1e Fix stalls in getting PECI information over eSPI 2023-04-03 13:06:16 -06:00
Jeremy Soller
9abd9d853a common: peci: WIP peci_get_temp over espi 2023-04-03 13:06:16 -06:00
Jeremy Soller
83f40c643f ite: Add more eSPI registers 2023-04-03 13:06:16 -06:00
Jeremy Soller
95a654aaff common: peci: Remove extra shift in peci_get_temp 2023-04-03 13:06:16 -06:00
Jeremy Soller
53f22a6658 common: Break out PECI GetTemp logic, prepare for PECI over ESPI 2023-04-03 13:06:16 -06:00
Jeremy Soller
c8df652723 Rename gaze18-3050 to gaze18 2023-04-03 13:06:16 -06:00
Jeremy Soller
9c59871986 Rename gaze18-40x0 to addw3 2023-04-03 13:06:16 -06:00
Jeremy Soller
cd3e5ac329 Rename addp3 to oryp11 2023-04-03 13:06:16 -06:00
Jeremy Soller
d68a42180b Rename oryp11 to serw13 2023-04-03 13:06:16 -06:00
Jeremy Soller
55f961406c addp3: Use virtual wire for calculating power state 2023-04-03 13:06:16 -06:00
Jeremy Soller
db10c198b3 addp3: Add new board 2023-04-03 13:06:16 -06:00
Tim Crawford
c7bc078cbd gaze18-3050: Fix GPIOs for power sequence
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
60f9cfc8d6 gaze18-3050: Add new board
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
e4542d2aa5 oryp11: Adjust fan points
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Tim Crawford
e4d7196b5c oryp11: Increase AC power limit to 280W
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Jeremy Soller
d723e2e13d gaze18-40x0: Fix prochot polarity 2023-04-03 13:06:16 -06:00
Jeremy Soller
ff7d7138b0 Support power limits above 256W 2023-04-03 13:06:16 -06:00
Jeremy Soller
8bd3b49273 gaze18-40x0: gpio fixes 2023-04-03 13:06:16 -06:00
Tim Crawford
213f79e2b6 oryp11: Add new board
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-04-03 13:06:16 -06:00
Jeremy Soller
bc111b7a4b gaze18-40x0: Let PCH handle panel 2023-04-03 13:06:16 -06:00
Jeremy Soller
ef6ea32c37 Add gaze18-40x0 2023-04-03 13:06:16 -06:00
Tim Crawford
1046dd7aec Update Rust toolchain to 2023-01-21
Update the toolchain and deps, and use the sparse registry access.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-02-18 06:28:21 -07:00
Tim Crawford
96b2d78c2e Remove PMC hack for S0ix
Whatever the issue was appears to be fixed after rebasing coreboot on
the 4.19 release. lemp11 has successfully reached S0ix with SLP_S0#
asserted when booted on battery power for 100 cycles.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-02-18 06:27:17 -07:00
Tim Crawford
ddb19e8738 ec/ite: Add Wake-Up Control registers
Groups 1, 3, and 4 require explicitly enabling the wake-up function
before unmasking them in INTC.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-02-07 10:47:24 -07:00
Tim Crawford
084aefd506 ec/ite: Add Interrupt Controller registers
- IT8587E has groups 0-18
- IT5570E has groups 0-21
- IT81202E has groups 0-23

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-02-07 10:47:24 -07:00
Tim Crawford
59c386ec12 Move gpio_debug from board to EC code
The gpio_debug() functionality depends on the ITE registers and not
anything board-specific.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-23 14:26:30 -07:00
Tim Crawford
f687000a4f ci: Install deps before running lints
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 13:52:14 -07:00
Tim Crawford
7205f1a49e Add shellcheck lint
Run shellcheck [1] on the bash files.

[1]: https://www.shellcheck.net/

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 13:52:14 -07:00
Tim Crawford
623d3ce8ab make: Add new targets
- fmt: Apply clang-format
- list-boards: list of available build targets
- help: Short description of make targets

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 13:52:14 -07:00
Tim Crawford
58f9ed4051 Run lints at pre-commit
Install a hook to run lints at pre-commit to force issues to be fixed
during development.

This introduces a 5-10 second delay when committing due to how slow
clang-format is.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 13:52:14 -07:00
Tim Crawford
1aadc68257 scripts: Rewrite lint scripts
Rewrite lint scripts to report what they do and if they pass. In the
case they fail list the files that caused the failure, except for
clang-format, which will be slow to run of every file individually
(should just run `make fmt` anyway). Also add a script to run all the
lints in order with a single command.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 13:52:14 -07:00
Tim Crawford
b03c960b4f make: Reduce build output
Default to silent builds, only outputting the file being generated. This
gives output similar to Linux/coreboot output when building. `VERBOSE=1`
can be passed to show the actual commands.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 12:18:31 -07:00
Tim Crawford
2056d4d5e0 make: Disable built-in rules and variables
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 12:18:31 -07:00
Tim Crawford
9a52042f95 Generate and use compiler dep rules
SDCC supports the `-MMD` option. Use it instead of having every file
depend on *all* the headers. Reduces incremental build time after
modifying headers as it will now only rebuild the actual dependents and
not the entire project.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-18 12:18:31 -07:00
Tim Crawford
84fe76cad4 avr: Fix compiling with GCC 12
Compiling the Arduino targets with GCC 12 fails with the following:

    error: array subscript 0 is outside array bounds of 'volatile uint8_t[0]' {aka 'volatile unsigned char[]'} [-Werror=array-bounds]

Apply the workaround from the bug discussion to fix it.

Ref: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-13 12:10:49 -07:00
Tim Crawford
28882975e3 make: Ensure git hash is 7 characters
Specify abbrev so the version string is the same across systems with
different values for core.abbrev.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-13 12:01:49 -07:00
Tim Crawford
f46360fb45 make: Ensure main object file is first
Per the SDCC manual, the object that declares main must be passed first
to the linker. The resulting binary is identical, and this has not
caused a problem yet, so I'm unsure how "required" this is.

Ref: Section 3.2.3 Projects with Multiple Source Files
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-13 12:01:49 -07:00
Tim Crawford
7ebec4f7b1 make: Enable compiling asm files
Allow specifying asm files the same way C files are added:

    board-common-y += foo.asm

The file must use an `.asm` extension. The toolchain file filters the
sources to compile them into objects correctly, as the C compiler
doesn't handle asm files itself.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-13 12:01:49 -07:00
Tim Crawford
e032c5f0f2 Update .clang-format and apply
Update .clang-format for LLVM 14.0, available on Ubuntu 22.04.

There is still plenty that clang-format sucks at or does wrong, so
either add some more blocks to disable it, or just put up with it.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-10 12:02:21 -07:00
Tim Crawford
c3267fc4ad ci: Update to Ubuntu 22.04
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-10 12:02:21 -07:00
Tim Crawford
d687df482a Conditionally compile eSPI support
A board may use either the LPC bus or the eSPI bus. Only include eSPI
support for boards that use it.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-06 12:47:54 -07:00
Tim Crawford
5e884cf413 scratch: Use relative path for source
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2023-01-06 12:47:54 -07:00
Tim Crawford
a8e37276e9 tool: Disable default features of redox-hwio
Fixes using as a dependency in no-std environments.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-12-20 13:41:02 -07:00
Tim Crawford
1019878e3c tool: Update dependencies
clap is only updated to 3.2 instead of 4.0 because I didn't want to deal
with all the changes.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-11-30 08:39:16 -07:00
Ian Douglas Scott
cd28de382d Add a K_NONE define
Seems like this define might as well be included. It means `layouts.py`
doesn't need to handle it specially.
2022-11-29 09:20:41 -07:00
Ian Douglas Scott
004c7acf6c Remove scripts/layouts.sh
Superseded by `keyboard-configurator/layouts.py`.
2022-11-29 09:20:41 -07:00
Tim Crawford
2a8befc195 Enable WLAN at power_on() instead of board_init()
If the board is on AC power when powered off the EC will not reset, and
WLAN power will not be enabled on next boot. Move enabling WLAN from
`board_init()` to `power_on()`.

Fixes: be4659a0cb ("Set wireless power at init and power off")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-11-18 19:11:01 -07:00
Tim Crawford
be4659a0cb Set wireless power at init and power off
Add a new wireless object for controlling WLAN power state. Change the
power sequence to enable WLAN at board init and disable it at power off.

Newer galp5 units sold to customers have an issue where they do not
fully power off. This is apparently somehow caused by `WLAN_PWR_EN`.

The unit received for development do not have this issue.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-11-18 07:32:18 -07:00
Tim Crawford
839abf7878 galp5: Remove BT_EN
BT is enabled PCH side by `PCH_BT_EN`. `BT_EN` is not connected.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-11-18 07:32:18 -07:00
Tim Crawford
861f1f2cc8 make: Add config for each ITE EC
EC_VARIANT is only used on AVR as a parameter to avrdude.

Replace its use on ITE with 2 choices:

- CONFIG_EC_ITE_IT8587E
- CONFIG_EC_ITE_IT5570E

Replace the EC defines with a matching define for the variable.
2022-11-17 14:19:39 -07:00
Tim Crawford
ac9631f948 make: Specify source files to include
Replace use of wildcard with list of source files to include. The `-y`
suffix is added, but has no significance since conditional compilation
has not been added yet.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-11-17 14:19:39 -07:00
Tim Crawford
ce66685c70 make: Move arch.mk to toolchain.mk
The arch.mk file contains variables/rules to build, so rename it. Leave
an empty arch.mk so it can still be used in a follow-up commit.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-11-17 14:19:39 -07:00
Jeremy Soller
c5b737f505 ESPI systems should always power off if in S5 state 2022-11-17 13:54:43 -07:00
Tim Crawford
edbb5b594a HACK: pmc: Apply hack for S0ix to all ADL boards
For some reason, *all* the ADL boards are now failing to enter S0ix.
Apply the PMC hack to the remaining boards.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-11-08 09:44:14 -07:00
13r0ck
be5d34dc0d Add other launch keyboards 2022-11-01 16:22:11 -06:00
Tim Crawford
d36fb62cd7 Replace makebin with objcopy
Replace custom SDCC tool with the more standard binutils tool.

scratch.rom and flash.rom are different (no unnecessary padding), but
resulting ec.rom is the same.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-10-28 15:01:45 -06:00
Tim Crawford
69f97fe149 Merge common EC directories
Split the EC define into base and variant. Merge the 3 ATmega chips as
atmega, and the 2 ITE chips as ite.

Tested that the generated files are identical.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-10-27 09:42:45 -06:00
Tim Crawford
01885609e8 HACK: pmc: Add hack to force S0ix entry on lemp11
lemp11 sometimes fails to reach C10 and gets stuck in C0 during s2idle.
For some reason, sending a PMC SCI allows the CPU to go to C10.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-10-17 18:36:35 -06:00
Tim Crawford
f8d1123934 pwm: Reload counters when they reach 0
Add IT5570E register that controls when the down counters are updated.
Set them to update when they reach 0, instead of immediately when DCRi
is written.

Fixes keyboard color changing when changing brightness levels if not
using 0xFF for an RGB value.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-10-14 08:38:34 -06:00
Tim Crawford
76019bdb61 Fix charger values, again (#303)
* common: Add macros for min, max, clamp

Simple macros, with no type checking.

Signed-off-by: Tim Crawford <tcrawford@system76.com>

* charger: Limit charger values to max valid value

Use the maximum valid value instead of discarding bits.

Fixes: 6295f60172 ("Fix smart charger values")

Signed-off-by: Tim Crawford <tcrawford@system76.com>

* charger/bq24780s: Fix charge current mask

bq24780s uses bit 12 for 4096 a current weight.

Fixes: 6295f60172 ("Fix smart charger values")

Signed-off-by: Tim Crawford <tcrawford@system76.com>

* oryp: Reduce charge current to 2A

Signed-off-by: Tim Crawford <tcrawford@system76.com>

* charger/bq24780s: Set RSENSE ratio option

Signed-off-by: Tim Crawford <tcrawford@system76.com>

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-10-06 13:02:15 -06:00
leviport
a32a3e3e95 Docs: update models that use 0.5mm pitch FPC cable (#302) 2022-09-15 11:42:12 -06:00
Tim Crawford
7f28764436 battery: Fix condition to start/stop charging
Change the condition, which is currently a level *at* which charging
will start/stop.

Per sysfs [1], these values are a level:

- *below* which charging will begin
- *above* which charging will stop

[1]: https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-09-02 11:22:56 -06:00
Tim Crawford
5cf57d69b9 gaze17: Define SLP_S0# to CPU_C10_GATE#
gaze17 does not connect SLP_S0# to the EC, so continue using
CPU_C10_GATE# for S0ix detection.

Fixes: 4b888ae9a501 ("board/system76/common: use SLP_S0# pin for modern standby detection")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-08-30 08:47:30 -06:00
Michał Kopeć
cc3effb6a4 board/system76/common: use SLP_S0# pin for modern standby detection
Previously, CPU_C10_GATE# was used for detecting entry into s0ix /
Modern Standby.

Intel documentation says that SLP_S0# should be used for s0ix detection
instead, and CPU_C10_GATE# is intended for VCCSTG power gating, so
switch the pin to improve s0ix detection reliability.

Fixes https://github.com/system76/firmware-open/issues/199

References:

- Intel docs #575570 rev 0.5, #607872 rev 2.2
- Chromium EC: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/power/intel_x86.c#41

Signed-off-by: Michał Kopeć <michal.kopec@3mdeb.com>
2022-08-30 08:47:30 -06:00
Tim Crawford
49abf83c08 Add config for using S0ix
S0ix does not require eSPI, and eSPI does not mandate S0ix.

Enable S0ix for:

- darp7 (TGL-U)
- darp8 (ADL-P)
- galp5 (TGL-U)
- galp6 (ADL-P)
- lemp10 (TGL-U)
- lemp11 (ADL-U)

It is also currently enabled on ADL-H due to a bug with S3:

- gaze17-3050
- gaze17-3060-b
- oryp9

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-08-30 08:47:30 -06:00
Tim Crawford
b78631e316 oryp10: Symlink to oryp9
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-08-26 11:38:49 -06:00
Tim Crawford
a8213311b1 galp6: Do not provide power while off
The previous commit incorrectly enabled power while off. Model PD_EN
after VA_EC_EN, which it replaced on galp6 for TCP0.

Fixes: a6a6c5fba4 ("galp6: Fix TCP0 power")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-08-03 11:11:28 -06:00
Tim Crawford
a6a6c5fba4 galp6: Fix TCP0 power
galp6 uses `PD_EN` instead of `VA_EC_EN` for enabling power to TCP0.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-08-02 16:02:06 -06:00
Tim Crawford
cd86c1e7d7 galp6: Fix USB power
The schematics incorrectly show the pin as `USB_PWR_EN#`. There is a
comment on the port side clarifying that it is actually active high.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-08-02 16:02:06 -06:00
Tim Crawford
371f6d3047 galp6: Add Galago Pro 6
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-08-01 19:26:36 -06:00
Tim Crawford
6295f60172 Fix smart charger values
Fix all smart charger values by having boards provide the RSENSE values
and perform the register calculations in the code.

The galp3-c, galp5, gaze16, and gaze17 do not seem to have the same
behavior as the rest of the boards, and further investigation is needed.
In the mean time, reduce their charge current values to preserve current
behavior.

Ref: OZ26786-DS v1.0
Ref: bq24780S Rev. C datasheet
Signed-off-by: Tim Crawford <tcrawford@system76.com
2022-08-01 19:26:36 -06:00
Tim Crawford
20d40f3477 gaze17-3050: Adjust fan points
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-07-26 09:27:44 -06:00
Tim Crawford
22fa2769ad gaze17-3050: Update configs
- Add to CI
- Correct smart charger values
- Enable WLAN power
- Enable USB power
- Disable mute

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-07-26 09:27:44 -06:00
Tim Crawford
7ab91e9f1d oryp9: Sync fans
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-07-20 14:20:31 -06:00
Tim Crawford
5ef477ab5b ci: Add darp8 and lemp11
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-07-12 15:31:35 -06:00
Tim Crawford
e8d91e5c2d oryp9: Add Oryx Pro 9
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-07-12 15:31:35 -06:00
Tim Crawford
60dfb62f90 lemp11: Add Lemur Pro 11
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-06-28 13:22:30 -06:00
Tim Crawford
7b9b91187a darp8: Add Darter Pro 8
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-06-22 09:17:21 -06:00
Tim Crawford
158ec124fe Add Pause key
In proprietary firmware and QMK, the Break key by itself is always just
Pause. They produce the same scan code, but Ctrl must be held for the OS
to recognize it as Break.

Behavior tested with xev.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-05-23 13:08:31 -06:00
Jeremy Soller
375d11f4ed Add gaze17 2022-05-16 11:16:33 -07:00
Jeremy Soller
a70ea4558c Fix battery TRACE macro 2022-04-27 07:13:48 -06:00
Tim Crawford
5780bb5e83 Update Rust toolchain to 2022-03-18
Match the toolchain used by Redox.

Update dependencies and submodules to fix building.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-04-04 18:59:20 -06:00
Tim Crawford
700f9e3756 ci: Add clang-format check
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-03-22 12:52:47 -06:00
Tim Crawford
b70a09e205 Disable clang-format for sensitive blocks
Things like macro blocks should not be auto-formatted.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-03-22 12:52:47 -06:00
Tim Crawford
04df6ae311 Add .clang-format
Most options are configured to keep most of the current style.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-03-22 12:52:47 -06:00
Tim Crawford
f21cc6d602 battery: Group battery info in a struct
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-03-18 12:47:59 -06:00
Tim Crawford
ee8ba5b72e fan: Replace 'static const' with defines
SDCC is not able to optimize statics [1]. Replace their use with defines
so significantly better code is generated.

[1]: https://sourceforge.net/p/sdcc/feature-requests/414/

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-03-18 12:47:20 -06:00
Jeremy Soller
84f9aad7d8 Add force console mode to arduino firmware 2022-02-14 18:55:14 -07:00
Jeremy Soller
cb341cfb2b Add power_init function 2022-02-14 18:55:14 -07:00
Jeremy Soller
474b1c2191 Remove unused power states, rename power on/off functions 2022-02-14 18:55:14 -07:00
Jeremy Soller
2262097c2b Add missing newline 2022-02-14 18:55:14 -07:00
Jeremy Soller
4bab1cc00d Ensure that system powers off S5 plane if it fails to power on S5 plane 2022-02-14 18:55:14 -07:00
Jeremy Soller
c31ef33101 Remove DEEP_SX, no boards use it 2022-02-14 18:55:14 -07:00
Tim Crawford
1cb61e6918 deps.sh: Update rustup or inform user of env vars
Ensure rustup is up-to-date to avoid users having a version that is too
old to support the TOML format.

If rustup was just installed, tell the user to source the new env vars
to use the correct version of the toolchain.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-01-18 08:09:56 -07:00
Tim Crawford
ca58502137 readme: Add datasheet info
The IT81202E, despite using a different core, contains sufficiently
equivalent documentation to IT8587E and IT5570E for most tasks except
interrupt management. Provide it as a reference since we cannot share
the datasheets for the models we use.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-01-07 18:36:10 -07:00
Jeremy Soller
7d75235081 Fix ectool path in power.sh 2021-12-02 10:35:56 -07:00
Ian Douglas Scott
ab0c55fae2 ectool 0.3.8 2021-11-19 13:32:00 -08:00
Ian Douglas Scott
85595a8d4c tool: Add a system76_ec command to disable input events
For testing Launch keyboards.

Could easily support in EC firmware as well if we had a use for that,
but not adding that for now.
2021-11-18 13:08:05 -08:00
Jeremy Soller
d9ce247a15 ectool: update lock file 2021-11-17 18:27:11 -07:00
Jeremy Soller
e8ce6d9096 Add libhidapi-dev to deps 2021-11-17 18:26:26 -07:00
Jeremy Soller
95632b4503 ectool: use linux-shared-hidraw feature for hidapi 2021-11-17 18:26:26 -07:00
Tim Crawford
55a617f2e0 gaze16-3060-b: Symlink new variant to gaze16-3060 2021-11-01 11:01:34 -06:00
Tim Crawford
987a5b4b70 Update submodules
Submodules have been updated to work with newer toolchains and fix build
warnings.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-10-26 11:35:48 -06:00
Tim Crawford
43e5cf4ba3 Fix or silence clippy warnings on nightly
Fix:
- dead_code
- clippy::if_then_panic
- clippy::manual_memcpy
- clippy::needless_borrow

Silence:
- clippy::missing_safety_doc
- clippy::needless_range_loop
- clippy::single_match

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-10-26 11:35:48 -06:00
Tim Crawford
975377af42 Update Rust toolchain to 2021-06-15
Update toolchain to match the version used in Redox.

Update dependencies to fix build.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-10-26 11:35:48 -06:00
Jeremy Soller
9fa83ad359 gaze16-3050, gaze16-3060: set PCH_DPWROK_EC low on EC boot to ensure PCH is off 2021-09-30 12:29:24 -06:00
Jeremy Soller
d3ee037879 Add gaze16 to CI 2021-09-20 10:58:11 -06:00
Jeremy Soller
9046f1e527 Add oryp8 2021-09-20 10:50:53 -06:00
Ian Douglas Scott
15c5f936b5 Read cycle count from battery and expose for ACPI 2021-09-15 07:49:50 -06:00
Jeremy Soller
646a6436a7 Attempt to fix power_peci_limit issues
- Return false when power_peci_limit fails
- Allow power_peci_limit to be retried indefinitely from power_set_limit
2021-09-08 13:39:54 -06:00
Tim Crawford
f55e493001 Remove overflow check for unsigned diffs
Calculating diffs with *unsigned* integers will always produce the
correct result, as long as the diff is less than the type max.

For example, suppose we read 254 and 2 for an 8 bit value:

    2 - 254 = 4

Using this property, simplify diffs on time_get() comparisons.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-16 09:52:08 -06:00
Tim Crawford
e00686a661 docs: Only 5570 and 8587 are valid EC IDs
ecflash has no verification for the EC it detects. It will attempt to
read and erase whatever it finds, where it will hang. Document what it
*should* read and an example of what it *shouldn't* read.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-03 08:12:50 -06:00
Tim Crawford
73c6bd986d main: Use unsigned modulo
Explicitly affix the literal with `U` so SDCC will directly call
`moduint()` instead of `modsint()`.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
d99ea41259 power: Use u8/u16 for loop index
Use u8/u16 instead of i16 as the value will never be negative and the
bounds are known at compile time.

Use a decrementing loop as SDCC generates more efficient code.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
37fa06ebc8 parallel: Use u16 for data length
The length will never be negative. Change it from i16 to u16 so
SDCC will generate more efficient code.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
5599c02e83 keymap: Use u8 for array access
The index will never be negative and will never exceed 255. Change them
from i16 to u8 so SDCC will generate more efficient code.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
458cb000f3 kbscan: Use u8 for array access
The index will never be negative and will never exceed 255. Change them
from i16 to u8 so SDCC will generate more efficient code.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
571316a4ea kbled: Use u8 for array access
The index will never be negative and will never exceed 255. Change them
from i16 to u8 so SDCC will generate more efficient code.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
f27d6350f2 kbc: Use u16 for timeout
The timeout will never be negative.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
2a3830fb57 i2c: Use u16 for data length
The length will never be negative.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
784202383e fan: Use u8 for array access
The index will never be negative and will never exceed 255. Change them
from i16 to u8 so SDCC will generate more efficient code.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 14:37:08 -06:00
Tim Crawford
99af8a35f5 Use explicitly sized types from stdint
Replace bare int types with stdint types. This was done with:

    grep -rwl 'int' src/ | xargs sed -i 's/\<int\>/int16_t/g'
    grep -rwl 'unsigned long' src/ | xargs sed -i 's/\<unsigned long\>/uint32_t/g'
    grep -rwl 'unsigned char' src/ | xargs sed -i 's/\<unsigned char\>/uint8_t/g'

Then reverted for *main(), putchar(), and getchar().

The Arduino declarations for parallel_main() were also corrected to
match their definitions.

SDCC does *not* generate the same code in all instances, due to `int`
being treated different than `short int`.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-08-02 07:46:44 -06:00
Tim Crawford
38b2a628f9 gaze16-3050: Correct charger input current
Per the charger for the 3050 variants:

    DC OUTPUT (输出/輸出): 19.5V⎓7.7A 150W

The 3060 charger does list 9.23A.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-31 06:15:05 -06:00
Jeremy Soller
ff53939a56 Add gaze16 2021-07-20 10:49:08 -06:00
Jeremy Soller
2720bb9037 Use PME virtual wire for suspend/resume 2021-07-20 10:49:08 -06:00
Jeremy Soller
90057df94f Change repetitive prints from DEBUG to TRACE 2021-07-20 10:49:08 -06:00
Jeremy Soller
913b0dfc44 Expose pnp_read and pnp_write 2021-07-20 10:49:08 -06:00
Jeremy Soller
e25af93f2e Update ecsim 2021-07-20 10:49:08 -06:00
Tim Crawford
9aab239f0a keyboard: Set scroll lock in default layouts
Not added to 14in_83 as it is not printed on the key.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-19 18:20:49 -06:00
Tim Crawford
701adb2f27 keymap: Define scroll lock
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-19 18:20:49 -06:00
Jeremy Soller
146f2d2b4a Implement scancode buffer 2021-07-19 14:52:07 -06:00
Tim Crawford
e86e18d4b1 delay: Use u8, decrementing loop
Use u8 instead of i16 as a delay can never be negative and should never
block for a long period of time.

Use a decrementing loop as SDCC generates more efficient code.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-19 06:48:16 -06:00
Tim Crawford
f9e4e25b05 ec/it*: Merge remaining ITE EC files
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-16 13:34:56 -06:00
Tim Crawford
cd8e76420d Add EC define that is usable in macros
The `__EC__` define is not usable in macros for conditional compilation.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-16 13:34:56 -06:00
Tim Crawford
851221da61 ec/it*: Merge all identical ITE EC files
Most of the code is the same between IT8587E and IT5570E.

Identical files were detected with:

    diff -rs src/ec/it8587e/ src/ec/it5570e/ | egrep '^Files .+ and .+ are identical$'

Then manually moved from one variant and deleted from the other.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-16 13:34:56 -06:00
Tim Crawford
c7fafe0103 board.c: Remove unused includes/globals
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 08:02:55 -06:00
Tim Crawford
92c8f8f3d1 lemp9: Remove duplicate setting of XLP_OUT
XLP_OUT is already set in power_event().

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 08:02:55 -06:00
Tim Crawford
1fc832ca94 Enable POST codes in EC init instead of per-board
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 07:37:40 -06:00
Tim Crawford
d1db553e8c system76/*: Call EC function to read POST codes
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 07:37:40 -06:00
Tim Crawford
f8d81a1e1b ec/it5570e: Add function to read POST codes
Logic for reading port 0x80/0x81 is common to the IT5570E.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 07:37:40 -06:00
Tim Crawford
43651cf2c2 ec/it*: Remove vendor string from signature
Per the specs, a 16-byte signature is stored at 0x40. All proprietary EC
ROMs store a space-padded 16-byte vendor string at 0x50, but it isn't
required.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 07:36:27 -06:00
Tim Crawford
a8229d9e62 Move power limit functions to common board code
Logic for changing power limit is the same for all boards with GPUs. It
is still called from board_event() instead of in power_event() to
maintain the current behavior of checking every main cycle.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 07:35:52 -06:00
Tim Crawford
3f446e5c6e Move eSPI files to board common code
The eSPI logic is the same for all TGL boards using it. None of it is
moved to IT5570E due to the call to power_cpu_reset().

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-07-09 07:34:51 -06:00
Winston Hoy
8ea0403850 Smooth fan speed changes (#190)
* SMOOTH_FANS, SMOOTH_FANS_UP, SMOOTH_FANS_DOWN build flags to smooth fan speed changes.
Defaults 40, set SMOOTH_FANS=0 to disable and keep sharp fan speed changes

* fix for ACPI CPU temperature

* allow for a floor to be set for fan smoothing and specifically configure oryp6/7 to start smoothing at 25% to mitigate fan buzzing below 25%

* update default config values for fans

* update all devices to use defaults for heatup, cooldown, update galp5 fan curves

* Decrease default cooldown time from 20 to 10

Co-authored-by: Jacob Kauffmann <jacob@system76.com>
2021-06-14 14:22:29 -06:00
Tim Crawford
b7368e8202 docs: Add overview of development environment
Give an overview of the different tools required for development and
what they're used for.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-06-10 09:41:16 -06:00
Tim Crawford
5a7fd2d7b3 docs: Rewrite the keyboard layout doc
Use of shorter sentences should reduce cognitive load. Example shell
commands should improve understanding of the description.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-06-08 11:23:44 -06:00
Tim Crawford
dab3a24fcb docs: flashing: Emphasize potential loss of data
Internal flashing can result in corrupted or lost OS data. Make this
more explicit for internal flashing, and make it a point for external
flashing.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-06-08 11:23:44 -06:00
Tim Crawford
d36cf981fe readme: Expand "dependencies" to "quickstart"
Give the process from 0 to built. Due to the implications of doing
something wrong (unbootable machine), flashing is kept separate.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-06-08 11:23:44 -06:00
Jeremy Soller
ca09e86987 Update documentation 2021-06-04 16:22:10 -06:00
Jeremy Soller
df469a9eea Reduce copying of keyboard layouts 2021-06-04 16:22:10 -06:00
Jeremy Soller
4742fd9742 Fix adding src/board/system76/common headers to INCLUDE 2021-06-04 16:22:10 -06:00
Tim Crawford
689cea4e9c readme: Add section for legal info
- General copyright notice
- License info for firmware and tools
- Note about ITE datasheets being unavailable

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-06-04 07:04:21 -06:00
Tim Crawford
6c5257ff3e readme: Add note about releases
Explain why there are no tagged releases, and why the commit hash on
official releases does not match commits from this repo.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-06-04 07:04:21 -06:00
Tim Crawford
51d6319f5b readme: Update note about PATH
Use hard line breaks to keep the line under 80 columns. Break it into 2
sentences: one explaining the issue, and the other explaining the fix.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-06-04 07:04:21 -06:00
Tim Crawford
b3b2a312b7 Define GPCRn values in EC header 2021-06-03 09:48:55 -06:00
Tim Crawford
3fe0e2f4e4 Add hidapi deps
ectool uses hidapi, which requires cc and pkg-config to be available.

This fixes building ectool on a minimal install system.
2021-05-25 09:15:02 -06:00
Jeremy Soller
1b539e1206 Make touchpad access non-blocking 2021-05-24 19:02:47 -06:00
Tim Crawford
532219c3f8 Allow battery thresholds to be set in config.mk
The start/end thresholds are user-configurable values. This will allow
us to override these with profile values if desired.
2021-05-14 15:55:26 -06:00
Tim Crawford
76e02c9514 Set battery charging thresholds in common.mk
Battery threshold control is entirely software-defined and does not
depend on any board-specific behavior.
2021-05-14 15:55:26 -06:00
Tim Crawford
285d622fbc kbc: Reduce timeout from 10ms to 1ms
Fix ACPI timeout and delay on S3 resume when holding a key.

A timeout greater than 1ms results in the excessive delay (~10s) still
occurring on an oryp5 (IT8587).
2021-05-14 15:06:50 -06:00
Tim Crawford
aa880033e3 Add missing xxd dep 2021-05-14 12:48:34 -06:00
Tim Crawford
316376c271 Add deps for Arch Linux 2021-05-14 12:48:34 -06:00
Tim Crawford
8bdcf243ec Add lint to ensure spaces are used for indentation 2021-05-07 12:44:48 -06:00
Tim Crawford
4963e04a83 Reindent files using spaces 2021-05-07 12:44:48 -06:00
Tim Crawford
720af4b2b0 Use BIT macro
Mostly done with the cocci script. macro.h was then added manually.
2021-05-07 11:24:25 -06:00
Tim Crawford
9a3ecba010 scripts: Add coccinelle file to use BIT macro 2021-05-07 11:24:25 -06:00
Lars Alexander Blumberg
7888f214bb Update dependency and keyboard config instructions
People who are just reading the keyboard customization instructions might overread the dependencies installations sections.
Additionally, installing rustup for the first time requires sourcing cargo's env vars in case the firmware is flashed in the same shell session after installing rustup.
2021-05-03 16:25:19 -06:00
Winston Hoy
606ba01b48 default to fan syncing but support disabling fan syncing with SYNC_FANS=0 build flag 2021-05-01 06:33:40 -06:00
Winston Hoy
f0c42f5839 Sync dGPU and PECI fans (at highest requested duty) 2021-05-01 06:33:40 -06:00
Tim Crawford
73b4e42726 Update ecspy
Attempting to use ecspy results in it failing to build redox_hwio.
Update the submodule to a version that uses a newer version of the dep.
2021-04-14 15:43:34 -06:00
Ian Douglas Scott
1ea21aedbe deps.sh: Run apt-get update
Hopefully this will fix the CI tests. This is a common enough issue on
CI that Travis mentions it in their documentation:
https://docs.travis-ci.com/user/common-build-problems/#linux-apt-fails-to-install-package-with-404-error
2021-04-13 11:04:51 -06:00
Ian Douglas Scott
55523d4083 ectool 0.3.6 2021-04-13 11:04:51 -06:00
Ian Douglas Scott
84d5c6b79d tool: Make Access require Send and 'static
This allows the Configurator to send a `Ec<Box<dyn Access>>` through a
channel to a background thread. This could be done differently, but
presumably there's no reason to have an `Access` implementation this
doesn't apply to.
2021-04-13 11:04:51 -06:00
Jeremy Soller
16778e4a41 Report all keys as released when lid is closed 2021-04-02 13:38:28 -06:00
Jeremy Soller
a04d353096 Fix fan_max keeping fan on when in S0iX 2021-04-02 13:38:28 -06:00
Jeremy Soller
2401fcc50d oryp6, oryp7: Fix buzzing at lowest fan speed 2021-03-16 18:51:55 -06:00
Jeremy Soller
61428bd198 ectool 0.3.5 2021-03-16 10:33:46 -06:00
Jeremy Soller
0017450cbb Add LED_SAVE command 2021-03-16 10:33:46 -06:00
Tim Crawford
17f8e37ed5 Convert toolchain file to TOML syntax
rustup 1.23.0 (2020-11-27) introduced support for TOML syntax for the
toolchain file. Use this and specify required compoenents.

To ensure you are using a new enough rustup, run:

    rustup self update
2021-03-15 10:09:42 -06:00
Jeremy Soller
66a970fa51 oryp6, oryp7: Improved fan curve for video chat 2021-03-08 15:54:19 -07:00
Jeremy Soller
9ad6b54aed Fix requiring sudo to run power.sh 2021-03-08 15:54:19 -07:00
Jeremy Soller
91d128f0a0 ectool 0.3.4 2021-03-04 13:52:25 -07:00
Jeremy Soller
aab45bfcc1 Add layer parameter for LED_GET_MODE and LED_SET_MODE commands 2021-03-04 13:52:25 -07:00
Ian Douglas Scott
301eef6f21 tool: Fix and CI test with redox_hwio 2021-03-04 13:51:19 -07:00
Ian Douglas Scott
59df32814b tool: Don't depend on clap when without default features 2021-03-04 13:51:19 -07:00
Ian Douglas Scott
aefad937bb ci: Test --no-default-features build of ectool 2021-03-04 13:51:19 -07:00
Ian Douglas Scott
325762d4d8 tool: Fix building without std feature 2021-03-04 13:51:19 -07:00
Jeremy Soller
8825b906bd ectool 0.3.3 2021-03-01 11:51:08 -07:00
Jeremy Soller
f30a9d84f7 Fix unused variable warning 2021-03-01 11:50:31 -07:00
Jeremy Soller
2ef4cd7bbd Add matrix command 2021-03-01 11:50:31 -07:00
Jeremy Soller
c931eb4eef Do not repeat K_FAN_TOGGLE 2021-02-26 15:51:47 -07:00
Jeremy Soller
67e143178d Always notify OS of SCI when pmc_sci is called 2021-02-26 15:51:47 -07:00
Ian Douglas Scott
4cd4df03e8 ectool 0.3.2 2021-02-26 12:18:02 -07:00
Ian Douglas Scott
b11bc64bba tool: API and CLI for LED matrix mode 2021-02-26 12:18:02 -07:00
Jeremy Soller
73a5d8b8a1 ectool 0.3.1: Implement read_debug for Box<dyn Access> 2021-02-23 09:45:55 -07:00
Tim Crawford
221da86e20 ci: Add job to build the tool 2021-02-23 09:29:16 -07:00
Tim Crawford
340ddd2e81 deps: Install libudev 2021-02-23 09:29:16 -07:00
Tim Crawford
ba99aec1b7 deps: Skip installing Rust if rustup is available
Saves time and prevents errors with trying to install rustup twice or
potentially overriding the user's default toolchain.
2021-02-22 16:26:14 -07:00
Tim Crawford
71534e736c ci: Add job to check for SPDX identifiers 2021-02-22 14:02:18 -07:00
Tim Crawford
3e154d7f00 Add missing SPDX identifiers 2021-02-22 14:02:18 -07:00
Tim Crawford
3e742b0da7 Add script to check for SPDX identifiers 2021-02-22 14:02:18 -07:00
Tim Crawford
9ef191edff tool: Update copyright year 2021-02-22 13:58:53 -07:00
Tim Crawford
44a0b887c4 tool: Replace ICU license text with MIT license
Cargo.toml declares MIT license, but the included LICENSE is the ICU
variant. Replace the text, as formatted on choosealicense [1].

[1]: https://choosealicense.com/licenses/mit/

Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-02-22 13:58:53 -07:00
Jeremy Soller
4ba943e3df oryp7 2021-02-22 10:05:52 -07:00
Tim Crawford
230d7f10b1 Add CI using GitHub Actions 2021-02-22 09:04:50 -07:00
Tim Crawford
55b6256ed6 Add script for installing dependencies 2021-02-22 09:04:50 -07:00
Tim Crawford
2ac214352b Move scripts from top-level to scripts/ 2021-02-22 09:04:50 -07:00
Ian Douglas Scott
71f0f1e181 ectool 0.3.0
Crates depending on both ectool and hidapi will have to disable hidapi's
default features (annoyingly) or it will fail to compile saying only one
backend should be enabled.
2021-02-22 08:08:49 -07:00
Ian Douglas Scott
e30779ab8d tool: Accesor method for HidDevice 2021-02-22 08:08:49 -07:00
Ian Douglas Scott
2768925ec6 tool: Support downcasting generic Ec
Removes the `impl Access for &mut dyn Access` I added earlier. But that
hasn't proven too useful.
2021-02-22 08:08:49 -07:00
Ian Douglas Scott
171257916c tool: CLI for color/brightness 2021-02-22 08:08:49 -07:00
Ian Douglas Scott
49b79f665b tool: Add --access argument to work with sim or hid 2021-02-22 08:08:49 -07:00
Ian Douglas Scott
7c5ba4e62c tool: Use clap for argument parsing 2021-02-22 08:08:49 -07:00
Ian Douglas Scott
504284bf72 tool: Move read_debug to trait so generic code can use it
Returns error for backends that don't support it.
2021-02-22 08:08:49 -07:00
Ian Douglas Scott
0c1584385c tool: Support for owned and unowned generic Ec 2021-02-22 08:08:49 -07:00
Ian Douglas Scott
f4458aebca tool: Use hidraw backend of hidapi
The default libusb backend just returns the string "hid_error is not
implemented yet" for all errors, while the hidraw backend at least gives
something correct if vague.

I'm not aware of any disadvantage other that not being (properly)
supported with really ancient kernels. It seems to work fine.
2021-02-22 08:08:49 -07:00
Tim Crawford
791b3224f9 docs: Explicitly mention to use a USB cable
Replace the vague step about grounding with one that says to connect a
USB cable and explain its purpose.
2021-02-18 08:37:53 -07:00
Jeremy Soller
18ec0eb694 Increase keyboard scanning delay to eliminate darp7 scanning issues 2021-02-05 09:52:24 -07:00
Jeremy Soller
3a9665a753 lemp10: Set DPWROK low on EC reset to ensure PCH reset 2021-02-04 09:14:38 -07:00
Jeremy Soller
12a9ac8d84 ectool 0.2.3 2021-01-15 08:34:31 -07:00
Jeremy Soller
304e7534c9 Add led value and color commands 2021-01-15 08:34:31 -07:00
Jeremy Soller
5bab59a526 Do not duplicate kbled support. Add kbled_max and kbled_get_color functions 2021-01-15 08:34:31 -07:00
Jeremy Soller
9309efb3e0 Use BIT macros 2021-01-05 12:17:16 -07:00
Jeremy Soller
47c1062e08 Add SPDX headers 2021-01-05 12:17:16 -07:00
Jeremy Soller
7f4a837bcf Add system76/darp7 2021-01-05 12:17:16 -07:00
Jeremy Soller
fbaea59b46 Add system76/galp5 2021-01-05 12:17:16 -07:00
Jeremy Soller
8f340d6164 Add system76/lemp10 2021-01-05 12:17:16 -07:00
Jeremy Soller
b156d18bc2 system76/common: Add OZ26786 charger 2021-01-05 12:17:16 -07:00
Jeremy Soller
fb6355f907 system76/common: Move touchpad handling to kbc_event 2021-01-05 12:17:16 -07:00
Jeremy Soller
31a908556b system76/common/kbc: Refactor to remove delays and improve readability 2021-01-05 12:17:16 -07:00
Jeremy Soller
5559d4e2f6 system76/common: Switch to pmc_swi for wake events 2021-01-05 12:17:16 -07:00
Jeremy Soller
3f41cd6ab3 system76/common/pmc: Refactor to improve readability and support ESPI 2021-01-05 12:17:16 -07:00
Jeremy Soller
99a0d6861f system76/common/power: Fix spurious power button enable 2021-01-05 12:17:16 -07:00
Jeremy Soller
c7827e4a7c system76/common/power: Support for ESPI 2021-01-05 12:17:16 -07:00
Jeremy Soller
c3fa2a27a7 system76/common/peci.c: Do not use PECI when in C10 state and using ESPI 2021-01-05 12:17:16 -07:00
Jeremy Soller
0595ba2b16 system76/common: Adjust KBC interrupts when using ESPI 2021-01-05 12:17:16 -07:00
Jeremy Soller
6da7a48e16 system76/common: Make acpi_read and acpi_write TRACE instead of DEBUG 2021-01-05 12:17:16 -07:00
Jeremy Soller
515c7495c1 ec/it5570/gpio.h: Add GCR21 register 2021-01-05 12:17:16 -07:00
Jeremy Soller
e4e7f89a67 system76/common: Add battery abstraction 2021-01-05 12:17:16 -07:00
Jeremy Soller
4de18eba93 common/macro.h: Add BIT macro 2021-01-05 12:17:16 -07:00
Jeremy Soller
b0c196d4b9 ec/it*: Add ESPI definitions 2021-01-05 12:17:16 -07:00
Jeremy Soller
87e16205d6 ec/it*/kbc.c: kbc_wait delay is now in microseconds 2021-01-05 12:17:16 -07:00
Jeremy Soller
932dbe8e71 mega2560/parallel.c: return immediately when perif cycle not ready 2021-01-05 12:17:16 -07:00
Jeremy Soller
f0c129c9f1 power.sh: Only show battery information if battery exists 2021-01-05 12:17:16 -07:00
Jeremy Soller
c40dd06da6 Update ecsim and ecspy 2021-01-05 12:17:16 -07:00
Ian Douglas Scott
42f1b4863f Add AccessLpcSim for communicating with ecsim
Probably the duplicated logic in `access/lpc/*` should be factored out
in some way, but it's a bit awkward to do so without defining a trait
that would be part of the public API...
2020-12-08 13:46:35 -07:00
Ian Douglas Scott
802bf417cc tool: Use From<T> for slightly neater error handling 2020-12-08 13:46:35 -07:00
Brosseau Valentin
43d31ca0c3 Add Custom Valentin French ISO Layout definition
Move some keys, and make the French ISO Layout working with the System76 EC.

This layout is working with the Venus PW55. (Clevo L140CU based model)
2020-12-08 13:44:45 -07:00
Tim Crawford
5c4f9b6c8b Sort object files
ROMs produced of Pop!_OS 20.10 and Fedora 33 with SDCC 4.0.0 cause
uecflash to crash after verifying the block write, leaving the  system
unbootable until all power is removed to force an EC reset.

Sorting object files appears to resolve this issue, creates a smaller
binary (~200 bytes from 20.04), and gives up more reproducible builds.
2020-12-08 13:43:40 -07:00
David Lattimore
2a56a82164 Add instructions for using released firmware version.
This should hopefully help people avoid issues like #132
2020-12-06 08:03:07 -07:00
420 changed files with 19851 additions and 5649 deletions

View File

@@ -13,8 +13,8 @@ trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.mk]
[{Makefile,*.mk}]
indent_style = tab
[Makefile]
indent_style = tab
[*.yml]
indent_size = 2

67
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
name: CI
on:
push:
branches: [master]
pull_request:
jobs:
lint:
runs-on: ubuntu-24.04
outputs:
boards: ${{ steps.board-matrix.outputs.boards }}
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: ./scripts/deps.sh
- name: Check SPDX tags
run: ./scripts/lint/01-spdx-tags.sh
- name: Check formatting
run: ./scripts/lint/02-uncrustify.sh
- name: Check shell scripts
run: ./scripts/lint/03-shellcheck.sh
- name: Generate board matrix
id: board-matrix
run: echo "boards=$(make list-boards | jq -sRc 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
tool:
strategy:
matrix:
include:
- features:
- features: --no-default-features --features="redox_hwio"
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: ./scripts/deps.sh
- name: Build tool
run: cargo build ${{ matrix.features }} --release --manifest-path tool/Cargo.toml
ec:
runs-on: ubuntu-24.04
needs: lint
strategy:
matrix:
boards: ${{ fromJson(needs.lint.outputs.boards) }}
# TODO: Conditionally build based on files changed?
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: ./scripts/deps.sh
- name: Build firmware
run: make BOARD=${{ matrix.boards }} VERBOSE=1
- name: Show memory layout
run: cat build/ec.mem
continue-on-error: true

156
.uncrustify.cfg Normal file
View File

@@ -0,0 +1,156 @@
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: NONE
# Uncrustify-0.78.1_f
# https://github.com/uncrustify/uncrustify/blob/uncrustify-0.78.1/documentation/htdocs/config.txt
newlines = lf
input_tab_size = 4
output_tab_size = 4
disable_processing_cmt = "uncrustify:off"
enable_processing_cmt = "uncrustify:on"
utf8_bom = remove
sp_arith_additive = force
sp_assign = force
sp_enum_brace = force
sp_enum_after_assign = force
sp_pp_concat = ignore
sp_bool = force
sp_compare = force
sp_inside_paren = remove
sp_paren_paren = remove
sp_cparen_oparen = remove
sp_paren_brace = force
sp_before_ptr_star = force
sp_between_ptr_star = remove
sp_between_ptr_ref = remove
sp_after_ptr_star = remove
sp_after_type = ignore # XXX: Fixes using macros in assignments
sp_before_sparen = force
sp_inside_sparen = remove
sp_inside_for = remove
sp_sparen_paren = remove
sp_sparen_brace = force
sp_do_brace_open = force
sp_brace_close_while = force
sp_before_semi_for = remove
sp_before_semi_for_empty = remove
sp_between_semi_for_empty = remove
sp_after_semi_for_empty = remove
sp_before_square = remove
sp_before_squares = remove
sp_inside_square = remove
sp_after_comma = add
sp_after_cast = remove
sp_inside_paren_cast = remove
sp_sizeof_paren = remove
sp_inside_braces = add
sp_inside_braces_empty = remove
sp_func_proto_paren = remove
sp_func_def_paren = remove
sp_inside_fparens = remove
sp_inside_fparen = remove
sp_inside_tparen = remove
sp_after_tparen_close = remove
sp_fparen_brace = force
sp_func_call_paren = remove
sp_return_paren = force
sp_attribute_paren = remove
sp_defined_paren = remove
sp_else_brace = force
sp_brace_else = force
sp_brace_typedef = force
sp_before_nl_cont = force
sp_cond_colon = force
sp_cond_question = force
sp_endif_cmt = force
sp_before_tr_cmt = add
sp_num_before_tr_cmt = 1
indent_columns = 4
indent_with_tabs = 0
indent_macro_brace = false
indent_ignore_label = true
indent_paren_close = 2
indent_align_assign = false
indent_align_paren = false
indent_compound_literal_return = false
nl_collapse_empty_body = true
nl_collapse_empty_body_functions = true
nl_start_of_file = remove
nl_end_of_file = force
nl_end_of_file_min = 1
nl_assign_brace = remove
nl_fcall_brace = remove
nl_enum_brace = remove
nl_struct_brace = remove
nl_union_brace = remove
nl_if_brace = remove
nl_brace_else = remove
nl_else_brace = remove
nl_else_if = remove
nl_for_brace = remove
nl_while_brace = remove
nl_do_brace = remove
nl_brace_while = remove
nl_switch_brace = remove
nl_after_case = true
nl_enum_own_lines = force
nl_func_type_name = remove
nl_func_proto_type_name = remove
nl_func_paren = remove
nl_func_def_paren = remove
nl_func_call_paren = remove
nl_fdef_brace = remove
nl_return_expr = remove
nl_after_semicolon = true
nl_brace_struct_var = remove
nl_ds_struct_enum_close_brace = true
nl_split_if_one_liner = true
nl_split_for_one_liner = true
nl_split_while_one_liner = true
nl_max = 2
eat_blanks_after_open_brace = true
eat_blanks_before_close_brace = true
code_width = 100
ls_for_split_full = true
ls_func_split_full = true
align_on_tabstop = true
align_var_def_star_style = 1
align_var_def_amp_style = 1
align_typedef_star_style = 1
align_typedef_amp_style = 1
align_func_proto_star_style = 1
align_func_proto_amp_style = 1
align_pp_define_together = true
cmt_width = 100
cmt_convert_tab_to_spaces = true
cmt_trailing_single_line_c_to_cpp = true
mod_paren_on_return = remove
mod_remove_extra_semicolon = true
mod_remove_duplicate_include = true
mod_sort_incl_import_prioritize_filename = true
mod_move_case_break = true
mod_move_case_return = true
mod_remove_empty_return = true
mod_enum_last_comma = add
pp_multiline_define_body_indent = 4
pp_indent_case = false
pp_indent_func_def = false
pp_indent_extern = false
#set QUALIFIER __at # XXX: Allow it to be treated as a function call
set QUALIFIER __code
set QUALIFIER __critical
set QUALIFIER __data
set QUALIFIER __idata
set QUALIFIER __pdata
set QUALIFIER __reentrant
set QUALIFIER __xdata
set TYPE __bit
set TYPE __sbit
set TYPE __sfr
set TYPE __sfr16
set TYPE __sfr32
set FUNC_CALL __asm__

View File

@@ -2,60 +2,102 @@
-include config.mk
# Disable built-in rules and variables
MAKEFLAGS += -rR
# Default to silent builds
ifneq ($(VERBOSE),1)
MAKEFLAGS += -s
endif
# Set build directory
BUILD = build
# Parameter for current board
ifeq ($(BOARD),)
all:
@echo "Please set BOARD to one of the following:"
@cd src/board && for board in */*/board.mk; do \
echo " $$(dirname "$$board")"; \
done
@exit 1
$(error BOARD must be specified)
else
# Calculate version
DATE=$(shell git show --format="%cd" --date="format:%Y-%m-%d" --no-patch)
REV=$(shell git describe --always --dirty)
DATE=$(shell git show --format="%cs" --no-patch --no-show-signature)
REV=$(shell git describe --abbrev=7 --always --dirty)
VERSION?=$(DATE)_$(REV)
# Set build directory
BUILD=build/$(BOARD)/$(VERSION)
# Default target - build the board's EC firmware
all: $(BUILD)/ec.rom
$(info Built '$(VERSION)' for '$(BOARD)')
$(info Built $(VERSION) for $(BOARD))
# Include common source
COMMON_DIR=src/common
SRC=$(wildcard $(COMMON_DIR)/*.c)
INCLUDE=$(wildcard $(COMMON_DIR)/include/common/*.h) $(COMMON_DIR)/common.mk
INCLUDE += $(COMMON_DIR)/common.mk
CFLAGS=-I$(COMMON_DIR)/include -D__FIRMWARE_VERSION__=$(VERSION)
include $(COMMON_DIR)/common.mk
SRC += $(foreach src, $(common-y), $(COMMON_DIR)/$(src))
# Include the board's source
BOARD_DIR=src/board/$(BOARD)
SRC+=$(wildcard $(BOARD_DIR)/*.c)
INCLUDE+=$(wildcard $(BOARD_DIR)/include/board/*.h) $(BOARD_DIR)/board.mk
INCLUDE += $(BOARD_DIR)/board.mk
CFLAGS+=-I$(BOARD_DIR)/include -D__BOARD__=$(BOARD)
include $(BOARD_DIR)/board.mk
SRC += $(foreach src, $(board-y), $(BOARD_DIR)/$(src))
SRC += $(foreach src, $(board-common-y), $(SYSTEM76_COMMON_DIR)/$(src))
SRC += $(foreach src, $(keyboard-y), $(KEYBOARD_DIR)/$(src))
# The board will define the embedded controller
# Include the embedded controller's source
EC_DIR=src/ec/$(EC)
SRC+=$(wildcard $(EC_DIR)/*.c)
INCLUDE+=$(wildcard $(EC_DIR)/include/ec/*.h) $(EC_DIR)/ec.mk
CFLAGS+=-I$(EC_DIR)/include -D__EC__=$(EC)
INCLUDE += $(EC_DIR)/ec.mk
CFLAGS+=-I$(EC_DIR)/include
include $(EC_DIR)/ec.mk
SRC += $(foreach src, $(ec-y), $(EC_DIR)/$(src))
# The EC will define the architecture
# Include the architecture's source
ARCH_DIR=src/arch/$(ARCH)
SRC+=$(wildcard $(ARCH_DIR)/*.c)
INCLUDE+=$(wildcard $(ARCH_DIR)/include/arch/*.h) $(ARCH_DIR)/arch.mk
INCLUDE += $(ARCH_DIR)/arch.mk
CFLAGS+=-I$(ARCH_DIR)/include -D__ARCH__=$(ARCH)
include $(ARCH_DIR)/arch.mk
SRC += $(foreach src, $(arch-y), $(ARCH_DIR)/$(src))
include $(ARCH_DIR)/toolchain.mk
# The architecture defines build targets, no more is required
endif
# Target to remove build artifacts
.PHONY: docs
docs:
mdbook build docs/
.PHONY: clean
clean:
rm -rf build
rm -rf $(BUILD)
.PHONY: fmt
fmt:
uncrustify -c .uncrustify.cfg -q --no-backup $(shell git ls-files '*.c' '*.h')
.PHONY: lint
lint:
./scripts/lint/lint.sh
.PHONY: list-boards
list-boards:
@cd src/board && for board in */*/board.mk; do \
echo "$$(dirname "$$board")"; \
done
# This target is run during setup, and is not shown in the help text.
.PHONY: git-config
git-config:
$(eval HOOKS = "$(shell git rev-parse --git-dir)/hooks")
ln -sfrv scripts/hooks/pre-commit.sh "$(HOOKS)/pre-commit"
.PHONY: help
help:
@echo "System76 EC build targets"
@echo " [all] BOARD=<B> Build the specified board"
@echo " list-boards List available target boards"
@echo " clean Remove build artifacts"
@echo " fmt Format the source code"
@echo " lint Run lint checks"
@echo " help Print this message"

View File

@@ -5,23 +5,67 @@ laptops.
## Documentation
- [Supported embedded controllers](./doc/controllers.md)
- [Flashing firmware](./doc/flashing.md)
- [Debugging](./doc/debugging.md)
- [Creating a custom keyboard layout](./doc/keyboard-layout-customization.md)
- [Adding a new board](./doc/adding-a-new-board.md)
- [Supported embedded controllers](./docs/controllers.md)
- [Flashing firmware](./docs/flashing.md)
- [Debugging](./docs/debugging.md)
- [Creating a custom keyboard layout](./docs/keyboard-layout-customization.md)
- [Development environment](./docs/dev-env.md)
- [Adding a new board](./docs/adding-a-new-board.md)
## Dependencies
## Quickstart
The complete set of dependencies can be installed using the `deps.sh` script
from the [Open Firmware](https://github.com/system76/firmware-open) repo.
Install dependencies using the provided script.
Dependencies specific to EC development can be installed with:
```sh
./scripts/deps.sh
```
If rustup was installed as part of this, then the correct `cargo` will not be
available in the running session. Start a new shell session or source the env
file to update `PATH`.
```sh
source $HOME/.cargo/env
```
Then build the firmware for your laptop model.
```sh
make BOARD=system76/<model>
```
See [Flashing](./docs/flashing.md) for how to use the new firmware image.
## Releases
The EC firmware itself does not have tagged releases. Any commit of this repo
may be used as a part of a [System76 Open Firmware][firmware-open] release.
In official releases the EC shares the same version as the BIOS firmware. Run
the follow command from firmware-open to determine the corresponding EC commit
for a release.
```
sudo apt install \
avr-libc \
avrdude \
gcc-avr \
sdcc
git ls-tree <release_hash> ec
```
[firmware-open]: https://github.com/system76/firmware-open
## Legal
System76 EC is copyright System76 and contributors.
System76 EC firmware is made available under the terms of the GNU General
Public License, version 3. See [LICENSE](./LICENSE) for details.
- firmware: GPL-3.0-only
- ecflash: LGPL-2.1-or-later
- ecsim: MIT
- ectool: MIT
Datasheets for the ITE embedded controllers used in System76 laptops cannot be
shared outside of company. (However, the IT81202E datasheet is [publicly
available][it81202e]. While it uses a different core, a significant portion of
the register information is the same as IT85878E/IT5570E.)
[it81202e]: https://www.ite.com.tw/en/product/view?mid=149

View File

@@ -1,33 +0,0 @@
# Flashing firmware
## Internal programmer
Use this method for flashing a system already running System76 EC.
This will trigger a watchdog reset causing the system to immediately power off.
Save and close all applications before flashing.
```
make BOARD=<vendor>/<model> flash_internal
```
## External programmer
Use this method for first-time flashing or flashing a bricked controller.
[A Mega 2560 is required for flashing.](./mega2560.md)
**The system must not have any power!**
1. Turn off the computer
2. Unplug the AC adapter
3. Remove the bottom panel
4. Disconnect the battery
5. Ground the laptop to the programmer
6. Disconnect the keyboard from its port
7. Attach the programmer to the keyboard port
8. Flash the firmware
```
make BOARD=<vendor>/<model> flash_external
```

View File

@@ -1,46 +0,0 @@
# Keyboard layout customization
## Dependencies
* Dependencies are listed in the README file for the EC project.
## Adding your layout
* In `src/board/system76/{your-model}/keymap/`, copy `default.c` and rename it.
There are two examples to reference in the `lemp9` directory: `jeremy.c` and
`levi.c`.
* In `src/common/include/common/keymap.h` you will find a list of the key
definitions.
* You will notice two sets of keys in these layout files. The top one is the
standard mapping. The bottom one is the Fn layer, meaning it is active when
the Fn key is being held. If you look at the Fn layer in the `levi.c` layout,
you will see that there are arrow keys at WASD, media and volume keys on the
bottom row, etc.
* Hint: To avoid losing your place change one key at a time, referencing the key
code you are deleting to keep yourself positioned correctly in the list of
keycodes.
## Configure your EC to build with your layout
* Create a file in the project's root directory called `config.mk` and add your
board and keyboard layout to it. For example, if you want to build lemp9
firmware with Jeremy's layout (which is at
`ec/src/board/system76/lemp9/keymap/jeremy.c`):
```
BOARD?=system76/lemp9
KEYMAP?=jeremy
```
## Test build your EC
* From the `ec` directory, run `make` to make sure it builds correctly.
## Flash your EC
* If the test build went well, you should be ready to flash your EC:
- Close all running applications.
- Unplug everything from your laptop except the charger.
- Flash with `make flash_internal`
- When it says, "Waiting 5 seconds for all keys to be released", it is
important to not touch the keyboard or trackpad until it finishes writing
the new EC and turns itself off.
- Once it shuts down, you can power it back on, and your keymap will be
active.
- If you changed your layout in such a way that you can't easily type, just
plug in a USB keyboard and re-flash to the default layout until you can
fix. The USB keyboard's layout will be unaffected.

10
docs/SUMMARY.md Normal file
View File

@@ -0,0 +1,10 @@
# Summary
- [Index](./index.md)
- [Development environment](./dev-env.md)
- [Adding a new board](./adding-a-new-board.md)
- [Supported controllers](./controllers.md)
- [Debugging](./debugging.md)
- [Flashing](./flashing.md)
- [Custom keyboard layouts](./keyboard-layout-customization.md)
- [Mega2560](./mega2560.md)

View File

@@ -2,7 +2,9 @@
## Charger parameters
- `CHARGER_CHARGE_CURRENT`: Currently the same for all boards (1536).
- `CHARGER_ADAPTER_RSENSE`: The adapter RSENSE value in milliohms.
- `CHARGER_BATTERY_RSENSE`: The battery RSENSE value in milliohms.
- `CHARGER_CHARGE_CURRENT`: The desired charge current in milliamps.
- `CHARGER_CHARGE_VOLTAGE`: On the battery, look for 充电限制电压 (charge limit
voltage). Convert this from volts to millivolts.
- `CHARGER_INPUT_CURRENT`: On the charger, look for DC output. Convert the
@@ -10,23 +12,28 @@
#### Example
The gaze15 battery has
The gaze15 battery has:
```
充电限制电压: 16.8Vdc
```
and its charger has
Its charger has:
```
DC OUTPUT (输出/輸出): 19.5V⎓9.23A 180W
```
This gives
The schematics show it uses a 0.005 ohm sense resistor for both the adapter and
the battery.
This gives:
```
CFLAGS+=\
-DCHARGER_CHARGE_CURRENT=1536 \
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=5 \
-DCHARGER_CHARGE_CURRENT=3072 \
-DCHARGER_CHARGE_VOLTAGE=16800 \
-DCHARGER_INPUT_CURRENT=9230
```

20
docs/book.toml Normal file
View File

@@ -0,0 +1,20 @@
# SPDX-License-Identifier: GPL-3.0-only
[book]
title = "System76 EC"
description = "System76 EC documentation"
language = "en"
src = "."
[build]
build-dir = "../build/docs"
create-missing = false
[output.html]
default-theme = "rust"
preferred-dark-theme = "coal"
no-section-label = true
git-repository-url = "https://github.com/system76/ec"
[output.html.print]
enable = false

View File

@@ -5,7 +5,25 @@ Terms used:
- *host*: The system that will have all devices connected to it and
will receive the EC logs
## Parallel port
## Debugging with target device
1. Install dependencies
```bash
./scripts/deps.sh
```
1. Start the console
```bash
make BOARD=system76/<model> console_internal
```
1. If you're not seeing seeing expected output, check the
[`LEVEL` cflag][level_cflag]. This is an EC compile time configuration and
changing will require a build and flash of the EC.
[level_cflag]: https://github.com/system76/ec/blob/01907011bb63/src/board/system76/common/common.mk#L31-L39
## Debugging with external device
### Parallel port
This method replaces the keyboard with a device used for debug logging.
An alternate method of interacting with the target is needed; e.g., an
@@ -20,7 +38,7 @@ Requirements:
For details on configuring the Mega 2560 and breakout board, see
[mega2560](./mega2560.md).
### Setup
#### Setup
1. Enable parallel port debugging in the EC firmware
- Uncomment `PARALLEL_DEBUG` in `src/board/system76/common/common.mk`
@@ -46,12 +64,12 @@ To return the Mega 2560 to host mode, reset the device.
If logs are corrupted, try power cycling the Mega or reseating the cable.
## I2C connection
### I2C connection
**Failure to follow steps in order, or performing steps on an
unsupported board, may result in damaged board components.**
### Wiring the target
#### Wiring the target
The I2C connection is made through the battery pins. Find the pins marked
`SMC_BAT` (clock) and `SMD_BAT` (data) in the service manual.
@@ -69,8 +87,10 @@ galp4 | 4 | 5
gaze14 | 4 | 3
gaze15 | 4 | 3
lemp9 | 6 | 5
lemp10 | 6 | 5
oryp5 | 4 | 5
oryp6 | 6 | 5
oryp7 | 6 | 5
1. Power off system
2. Unplug AC adapter
@@ -84,7 +104,7 @@ oryp6 | 6 | 5
9. Reconnect battery
10. Replace bottom panel
### Setup
#### Setup
Requirements:
- Target wired for EC debugging

53
docs/dev-env.md Normal file
View File

@@ -0,0 +1,53 @@
# Development environment
## OS
Linux is the only supported environment. Development is possible on a variety
of distros. It is recommended to use the latest Pop!\_OS or Ubuntu release.
The build server uses Ubuntu 20.04.
## IDE/Editor
Any editor that has support for [EditorConfig] may be used.
No specific IDE or editor is required or recommended.
## Toolset
EC development depends on using distro-provided packages for the most of the
toolset.
A complete list of dependencies can be seen in `scripts/deps.sh`.
### Cargo
rustup manages the [Rust] toolchain, which includes cargo. Cargo is required
for building the tools. It is the only part of the development toolset that is
not installed through distro packages.
### GNU Make
[GNU Make] is used to automate the build process. It also provides targets for
using ecflash (for flashing) and ectool (for console).
### SDCC
[SDCC] is the only practical open source toolset on Linux for targeting the
8051 architecture (among others). It contains a collection of tools comparable
to what you would expect from GCC for other development targets.
SDCC contains language extensions to support the 8051 architecture. Refer to
the [SDCC manual] for more information.
Version 4.0.0 or newer should be used.
**Note**: Fedora installs SDCC binaries to a non-standard location. Ensure that
`PATH` includes `/usr/libexec/sdcc`.
[EditorConfig]: https://editorconfig.org/
[GNU Make]: https://www.gnu.org/software/make/
[Rust]: https://www.rust-lang.org/
[SDCC manual]: http://sdcc.sourceforge.net/doc/sdccman.pdf
[SDCC]: http://sdcc.sourceforge.net/

76
docs/flashing.md Normal file
View File

@@ -0,0 +1,76 @@
# Flashing firmware
## UEFI application
The `flash.sh` script from the top-level firmware-open project will use
firmware-update, the UEFI application which is used for normal system updates.
This will flash both the SBIOS and the EC after building the firmware. To
flash just the EC, delete the built `firmware.rom` before running `flash.sh`.
## Internal programmer
Use this method for flashing a system already running System76 EC.
This method will only work if the running firmware is not locked. Firmware is
write locked if it was built with `CONFIG_SECURITY=y`. The firmware can be
unlocked using ectool for a single boot:
```
./scripts/ectool.sh security unlock
```
This method will trigger a watchdog reset causing the system to **immediately
power off**. OS data may be lost or corrupted as a result. Save and close all
applications before flashing.
```
make BOARD=<vendor>/<model> flash_internal
```
## External programmer
Use this method for:
- flashing from proprietary firmware to System76 EC firmware
- flashing without risking loss of OS data
- flashing a bricked controller
This requires:
- [A configured Mega 2560](./mega2560.md): For programming the EC itself
- A USB cable: For creating a common ground and providing power
- USB-C is recommended, but USB-A will work as well
- A second computer: For building and flashing the firmware
**The system must not have any power!**
1. Turn off the laptop
2. Unplug the AC adapter
3. Remove the bottom panel
4. Disconnect the battery
5. Disconnect the keyboard from its port
6. Replace the bottom panel and flip the laptop back over
7. Connect the USB cable from the laptop to the host machine
8. Connect the Mega 2560 to the host machine
9. Attach the programmer to the keyboard port
10. Flash the firmware
```
make BOARD=<vendor>/<model> flash_external
```
One of the first things it does is read the EC ID and version. If working, the
ID will be the EC model the machine uses.
```
ID: 5570 VER: 2
ID: 8587 VER: 6
```
Any other values means that the Mega 2560 is misconfigured or the FPC is not
seated correctly. E.g., this is wrong:
```
ID: FF7F VER: 127
```

View File

@@ -0,0 +1,118 @@
# Keyboard layout customization
System76 EC firmware suppports using custom keyboard layouts. For example,
having the physical "Caps Lock" key function as "Escape" when pressed.
This only applies to the internal keyboard. External keyboards are not
affected.
Advanced functionality, such as macros or QMK's Mod-Tap, are not supported.
You must be able to build and flash firmware. See the [README](../README.md)
if you have not built the firmware before.
## Firmware version
To ensure compatibility with other system components (e.g. your current BIOS
version), it's recommended to flash the same firmware version as you're
currently using.
Determine the BIOS version using dmidecode. The BIOS version is formatted as
`<date>_<revision>`.
```sh
sudo dmidecode -t bios | grep Version
```
From the [firmware-open](https://github.com/system76/firmware-open) repo,
determine the EC commit used for the BIOS version.
```sh
git ls-tree <bios_rev> ec
```
Checkout that commit in the EC repo and update the submodules.
```sh
git checkout <ec_rev>
git submodule update --recursive
```
## Adding a layout file
Determine the keyboard used for your model.
```sh
grep KEYBOARD src/board/system76/<model>/board.mk
```
Copy the default layout file for the keyboard to a separate file in the keymap
directory.
```sh
cp src/keyboard/system76/<keyboard>/keymap/default.c src/keyboard/system76/<keyboard>/keymap/<custom>.c
```
The name of the keymap can be anything. Following QMK convention, the file name
could be your username.
## Modifying the layout
A keymap file is a C file that defines the position of key and its function.
Only the `LAYOUT`s should be modified.
There are 2 layers in a keymap file.
- `KEYMAP[0]`: The first `LAYOUT` defines the default layer
- `KEYMAP[1]`: The second `LAYOUT` defines the function layer
A `KT_FN` key must be assigned on the first layer in order to access the second
layer. The `KT_FN` key must be held to use keys on the second layer.
Change one key at a time to avoid losing your place.
Some related files are:
- `src/common/include/common/keymap.h`: Defines the key scancodes
- `src/keyboard/system76/<keyboard>/include/board/keymap.h`: Defines the
keyboard matrix
## Building with the new layout
Build the firmware specifying the `KEYMAP` you have added.
```sh
make BOARD=system76/lemp9 KEYMAP=custom
```
Use a config file to simplify this. In the EC project's root directory, create
a file named `config.mk`. Define the `BOARD` and `KEYMAP` variables.
```mk
BOARD?=system76/lemp9
KEYMAP?=custom
```
Then building the firmware only requires calling make.
```sh
# Make will read config.mk to determine which board and keymap to use.
make
```
## Flashing the new firmware
See [flashing firmware](./flashing.md) for details.
Do not use the keyboard or touchpad while it is flashing.
The system will power off as part of the flash process. Turn it back on after
it has powered off.
The keyboard can now be used with your new layout.
## Troubleshooting
If your layout does not work as you intended, only the internal keyboard will
be affected. An external USB keyboard or SSH session can be used to correct the
layout and reflash the firmware.

View File

@@ -18,7 +18,7 @@ it uses the ATmega16U2, find a different model.
A flexible printed circuit (FPC) breakout board is required. It should have:
- 24 pins with 0.1" (2.54mm) pitch
- One side with 0.5mm pitch FPC connector (for lemp9)
- One side with 0.5mm pitch FPC connector (for lemp9, lemp10, lemp11, galp5, and galp6)
- One side with 1.0mm pitch FPC connector (for all other models)
Depending on the vendor, the connectors may not come soldered to the board (or

13
docs/security.md Normal file
View File

@@ -0,0 +1,13 @@
# Firmware security
The firmware security feature can be configured by setting `CONFIG_SECURITY=1`
in the `src/board/system76/[board]/board.mk` file. This feature prevents
programming the EC firmware at runtime, unless the EC is unlocked with the
`system76-ectool security unlock` command. After this, on the next reboot, the
EC will respond to the SPI and reset commands. On boards where the `ME_WE` GPIO
exists, it will be set high when the EC security state is unlocked.
Other firmware components can use this state to perform their own locking and
unlocking primitives. For example, in `coreboot`, flash regions may be locked
when the EC security state is locked. In `EDK2`, a physical presence dialog may
be shown when the EC security state is unlocked.

Submodule ecflash updated: 1f947933e1...2b94b81b97

2
ecsim

Submodule ecsim updated: aee30bc263...2d672adae5

2
ecspy

Submodule ecspy updated: b3bde0a1be...f0bf26d577

View File

@@ -1,5 +0,0 @@
#!/usr/bin/env bash
set -e
cargo build --release --manifest-path tool/Cargo.toml
sudo tool/target/release/system76_ectool "$@"

View File

@@ -1,65 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
# This script produces layout data for the System76 Keyboard Configurator
set -e
rm -rf build/layouts
mkdir -p build/layouts
D="$(realpath build/layouts)"
binary="$D/keymap"
source="$binary.c"
header="src/common/include/common/keymap.h"
echo "#include <stdio.h>" > "$source"
echo "#include \"$header\"" >> "$source"
echo "int main(int argc, char **argv) {" >> "$source"
grep '^#define \(K_\|KT_FN\)' "$header" \
| cut -d ' ' -f2 \
| while read keycode
do
name="$(echo "$keycode" | cut -d '_' -f2-)"
echo "printf(\"${name},0x%04X\\n\", $keycode);" >> "$source"
done
echo "return 0;" >> "$source"
echo "}" >> "$source"
gcc -I. "$source" -o "$binary"
"$binary" | tee "$D/keymap.csv"
cd src/board
for board in */*
do
file="$board/include/board/keymap.h"
if [ ! -e "$file" ]
then
continue
fi
echo "# $board"
mkdir -p "$D/$board"
cp "$D/keymap.csv" "$D/$board"
row=0
rg \
--multiline \
--multiline-dotall \
--regexp '#define LAYOUT\(.*\) \{.*\}' \
"$file" \
| grep --only-matching '\{.*\}' \
| sed 's/^{ //' \
| sed 's/ }$//' \
| sed 's/, / /g' \
| while read line
do
col=0
for word in $line
do
if [ "$word" != "___" ]
then
echo "$word,$row,$col"
fi
col=$(expr $col + 1)
done
row=$(expr $row + 1)
done \
| sort -n \
| tee "$D/${board}/layout.csv"
done

View File

@@ -1 +0,0 @@
nightly-2020-07-27

4
rust-toolchain.toml Normal file
View File

@@ -0,0 +1,4 @@
[toolchain]
channel = "nightly-2024-05-11"
components = ["clippy", "rustfmt"]
profile = "minimal"

View File

@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-only
// Replace shifts with BIT macro
@@ expression val; @@
-(1 << val)
+BIT(val)
@@ expression val; @@
-(1U << val)
+BIT(val)
@@ expression val; @@
-1 << val
+BIT(val)

View File

@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
// SDCC extenstions that need to be defined away for spatch
#define __at(x)
#define __code
#define __critical
#define __data
#define __reentrant
#define ___

94
scripts/deps.sh Executable file
View File

@@ -0,0 +1,94 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
set -eE
function msg {
echo -e "\x1B[1m$*\x1B[0m" >&2
}
trap 'msg "\x1B[31mFailed to install dependencies!"' ERR
source /etc/os-release
msg "Installing system build dependencies"
if [[ "${ID}" =~ "debian" ]] || [[ "${ID_LIKE}" =~ "debian" ]]; then
sudo apt-get update
sudo apt-get install \
--no-install-recommends \
--yes \
avr-libc \
avrdude \
curl \
gcc \
gcc-avr \
libc-dev \
libhidapi-dev \
libudev-dev \
make \
pkgconf \
sdcc \
shellcheck \
uncrustify \
xxd
elif [[ "${ID}" =~ "fedora" ]] || [[ "${ID_LIKE}" =~ "fedora" ]]; then
sudo dnf install \
--assumeyes \
avr-gcc \
avr-libc \
avrdude \
curl \
gcc \
make \
sdcc \
ShellCheck \
systemd-devel \
uncrustify \
vim-common
elif [[ "${ID}" =~ "arch" ]] || [[ "${ID_LIKE}" =~ "arch" ]]; then
sudo pacman -S \
--noconfirm \
avr-gcc \
avr-libc \
avrdude \
curl \
gcc \
make \
pkgconf \
sdcc \
shellcheck \
systemd-libs \
uncrustify \
vim
else
msg "Please add support for your distribution to:"
msg "scripts/deps.sh"
exit 1
fi
msg "Initializing submodules"
git submodule update --init --recursive
msg "Installing git hooks"
make git-config
RUSTUP_NEW_INSTALL=0
if ! command -v rustup >/dev/null 2>&1; then
RUSTUP_NEW_INSTALL=1
msg "Installing Rust"
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --default-toolchain none
msg "Loading Rust environment"
source "${HOME}/.cargo/env"
fi
msg "Installing pinned Rust toolchain and components"
rustup show
if [[ $RUSTUP_NEW_INSTALL = 1 ]]; then
msg "rustup was just installed. Ensure cargo is on the PATH with:"
echo -e " source ~/.cargo/env\n"
fi
msg "\x1B[32mSuccessfully installed dependencies"

6
scripts/ectool.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
set -e
cargo build --release --quiet --manifest-path tool/Cargo.toml
sudo tool/target/release/system76_ectool "$@"

7
scripts/hooks/pre-commit.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
make lint 2>/dev/null || {
echo -e "\nissues found, not committing"
exit 1
}

52
scripts/lint/01-spdx-tags.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
# Check that all files have a SPDX license identifier
# TODO: Validate license tags against a whitelist
LINT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
. "$LINT_DIR/util.sh"
echo -n "Checking for SPDX tags..."
EXCLUDES=(
# Ignore license files
':!:LICENSE'
':!:**/LICENSE'
# Ignore cargo files
':!:**/Cargo.lock'
':!:**/Cargo.toml'
':!:rust-toolchain.toml'
# Ignore text files
':!:*.md'
':!:*.txt'
# Ignore dotfiles
':!:\.*'
':!:**/\.*'
)
needs_tag=()
for file in $(git ls-files "${EXCLUDES[@]}"); do
# Only check regular files
if [[ ! -f "$file" ]]; then
continue
fi
# SPDX must appear at head of file
if ! head "$file" | grep -q 'SPDX-License-Identifier:'; then
needs_tag+=("$file")
fi
done
if [[ "${#needs_tag[@]}" != "0" ]]; then
failed
for file in "${needs_tag[@]}"; do
echo "- $file"
done
exit 1
fi
passed

36
scripts/lint/02-uncrustify.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
# Check if any C files or headers need to be formatted.
# shellcheck disable=SC1091
LINT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
. "$LINT_DIR/util.sh"
echo -n "Checking C style..."
if ! command -v uncrustify > /dev/null; then
skipped "uncrustify not found"
exit 0
fi
needs_formatting=()
for file in $(git ls-files '*.c' '*.h'); do
if ! uncrustify -c .uncrustify.cfg -q --check "$file" >/dev/null 2>&1; then
needs_formatting+=("$file")
fi
done
if [[ "${#needs_formatting[@]}" != "0" ]]; then
failed
for file in "${needs_formatting[@]}"; do
echo "- $file"
done
exit 1
fi
passed

36
scripts/lint/03-shellcheck.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
# Check if any shell scripts have issues.
LINT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
. "$LINT_DIR/util.sh"
echo -n "Checking shell scripts..."
if ! command -v shellcheck > /dev/null; then
skipped "shellcheck not found"
exit 0
fi
readarray -t FILES < <(git ls-files '*.sh')
needs_formatting=()
for file in "${FILES[@]}"; do
# SC1091: Ignore external scripts
if ! shellcheck -f quiet --exclude=SC1091 "$file"; then
needs_formatting+=("$file")
fi
done
if [[ "${#needs_formatting[@]}" != "0" ]]; then
failed
for file in "${needs_formatting[@]}"; do
echo "- $file"
done
exit 1
fi
passed

14
scripts/lint/lint.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
# Run all lints.
LINT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
LINTS=$(find "$LINT_DIR" -type f -name "[0-9][0-9]-*" | sort)
FAILED=0
for lint in $LINTS; do
$lint || FAILED=1
done
[[ "$FAILED" = "0" ]] || exit 1

15
scripts/lint/util.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
passed() {
echo -e "\x1B[32mPASSED\x1B[0m"
}
skipped() {
local reason=$1
echo -e "\x1B[33mSKIPPED\x1B[0m ($reason)"
}
failed() {
echo -e "\x1B[31mFAILED\x1B[0m"
}

View File

@@ -1,9 +1,16 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
set -e
has_bat=0
if [ -d /sys/class/power_supply/BAT0/ ]
then
has_bat=1
fi
has_ec=0
if ./ectool.sh info 2> /dev/null
if ./scripts/ectool.sh info 2> /dev/null
then
has_ec=1
fi
@@ -27,7 +34,10 @@ do
if [ "${header}" == "1" ]
then
F="Time "
F="${F}\tBAT W"
if [ "${has_bat}" == "1" ]
then
F="${F}\tBAT W"
fi
F="${F}\tCPU W"
F="${F}\tCPU PL1"
F="${F}\tCPU PL2"
@@ -50,25 +60,28 @@ do
else
F="$(date "+%T")"
last_E="$(cat /sys/class/powercap/intel-rapl\:0/energy_uj)"
last_E="$(sudo cat '/sys/class/powercap/intel-rapl:0/energy_uj')"
sleep 1
uV="$(cat /sys/class/power_supply/BAT0/voltage_now)"
V="$(echo "${uV}/1000000" | bc -lq)"
uA="$(cat /sys/class/power_supply/BAT0/current_now)"
A="$(echo "${uA}/1000000" | bc -lq)"
bat_W="$(echo "${V} * ${A}" | bc -lq)"
F="${F}\t$(printf "%.2f" "${bat_W}")"
if [ "${has_bat}" == "1" ]
then
uV="$(cat /sys/class/power_supply/BAT0/voltage_now)"
V="$(echo "${uV}/1000000" | bc -lq)"
uA="$(cat /sys/class/power_supply/BAT0/current_now)"
A="$(echo "${uA}/1000000" | bc -lq)"
bat_W="$(echo "${V} * ${A}" | bc -lq)"
F="${F}\t$(printf "%.2f" "${bat_W}")"
fi
E="$(cat /sys/class/powercap/intel-rapl\:0/energy_uj)"
E="$(sudo cat '/sys/class/powercap/intel-rapl:0/energy_uj')"
W="$(echo "(${E} - ${last_E})/1000000" | bc -lq)"
F="${F}\t$(printf "%.1f" "${W}")"
PL1_uW="$(cat /sys/class/powercap/intel-rapl\:0/constraint_0_power_limit_uw)"
PL1_uW="$(sudo cat '/sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw')"
PL1_W="$(echo "${PL1_uW}/1000000" | bc -lq)"
F="${F}\t$(printf "%.1f" "${PL1_W}")"
PL2_uW="$(cat /sys/class/powercap/intel-rapl\:0/constraint_1_power_limit_uw)"
PL2_uW="$(sudo cat '/sys/class/powercap/intel-rapl:0/constraint_1_power_limit_uw')"
PL2_W="$(echo "${PL2_uW}/1000000" | bc -lq)"
F="${F}\t$(printf "%.1f" "${PL2_W}")"

11
scripts/spatch.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
spatch \
--sp-file ./scripts/coccinelle/bit-macro.cocci \
--macro-file ./scripts/coccinelle/macros.h \
--no-includes \
--include-headers \
--preprocess \
--in-place \
--dir src/

View File

@@ -1,27 +1,5 @@
# SPDX-License-Identifier: GPL-3.0-only
CC=sdcc -mmcs51 --model-large --code-size $(CODE_SIZE) --xram-size $(SRAM_SIZE) --Werror
OBJ=$(patsubst src/%.c,$(BUILD)/%.rel,$(SRC))
# Run EC rom in simulator
sim: $(BUILD)/ec.rom
cargo run \
--release \
--manifest-path ecsim/Cargo.toml \
--no-default-features \
-- $<
# Convert from Intel Hex file to binary file
$(BUILD)/ec.rom: $(BUILD)/ec.ihx
@mkdir -p $(@D)
makebin -s $(CODE_SIZE) -p < $< > $@
# Link object files into Intel Hex file
$(BUILD)/ec.ihx: $(OBJ)
@mkdir -p $(@D)
$(CC) $(LDFLAGS) -o $@ $^
# Compile C files into object files
$(OBJ): $(BUILD)/%.rel: src/%.c $(INCLUDE)
@mkdir -p $(@D)
$(CC) $(CFLAGS) -o $@ -c $<
arch-y += arch.c
arch-y += delay.c
arch-y += time.c

View File

@@ -15,8 +15,8 @@ void delay_ticks(uint16_t ticks) {
// Start timer in mode 1
TMOD = (TMOD & 0x0F) | 0x10;
TH1 = (unsigned char)(value >> 8);
TL1 = (unsigned char)value;
TH1 = (uint8_t)(value >> 8);
TL1 = (uint8_t)value;
TR1 = 1;
// Wait until complete
@@ -24,8 +24,8 @@ void delay_ticks(uint16_t ticks) {
}
// This loops through delays of one ms in order to avoid overflow
void delay_ms(int ms) {
for (int i = 0; i < ms; i++) {
void delay_ms(uint8_t ms) {
for (uint8_t i = ms; i != 0; i--) {
delay_us(1000);
}
}

View File

@@ -9,14 +9,12 @@ void delay_ticks(uint16_t ticks);
// 1 us * 9.2 MHz / 12 is 69/90
// Warning: this will round to the nearest tick
#define delay_us(X) \
delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89UL) / 90UL));
#define delay_us(X) delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89UL) / 90UL));
// 1 ns * 9.2 MHz / 12 is 69/90000
// Warning: this will round to the nearest tick
#define delay_ns(X) \
delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89999UL) / 90000UL));
void delay_ms(int ms);
#define delay_ns(X) delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89999UL) / 90000UL));
void delay_ms(uint8_t ms);
#endif // _ARCH_DELAY_H

View File

@@ -5,7 +5,9 @@
#include <stdint.h>
typedef uint16_t systick_t;
void time_init(void);
uint32_t time_get(void);
systick_t time_get(void);
#endif // _ARCH_TIME_H

View File

@@ -3,23 +3,34 @@
// Uses timer 0 to keep track of global time
#include <8051.h>
#include <arch/time.h>
static volatile uint32_t time_overflows = 0;
#define OSC_DIVISOR 12
#define TICK_INTERVAL_MS 1
// Value to reload into the timer when the overflow interrupt is triggered.
#define TIMER_RELOAD (0xFFFF - (TICK_INTERVAL_MS * (CONFIG_CLOCK_FREQ_KHZ / OSC_DIVISOR)))
static volatile systick_t time_overflows = 0;
void timer_0(void) __interrupt(1) {
// Hardware automatically clears the the interrupt
// Stop timer
TR0 = 0;
time_overflows++;
// Start timer
TH0 = 0xFD;
TL0 = 0x01;
// Reload the values
TH0 = TIMER_RELOAD >> 8;
TL0 = TIMER_RELOAD & 0xFF;
// Restart the timer
TR0 = 1;
}
/**
* Set up Timer 0 as the system tick.
*/
void time_init(void) __critical {
// Stop the timer
TR0 = 0;
@@ -27,17 +38,20 @@ void time_init(void) __critical {
time_overflows = 0;
// Enable timer interrupts
// Enable the interrupt
ET0 = 1;
// Start timer in mode 1
// (65536 - 64769) / (9.2 MHz / 12) = ~1 ms interval
// Set the timer to mode 1 (16-bit timer)
TMOD = (TMOD & 0xF0) | 0x01;
TH0 = 0xFD;
TL0 = 0x01;
// Set the initial values
TH0 = TIMER_RELOAD >> 8;
TL0 = TIMER_RELOAD & 0xFF;
// Start the timer
TR0 = 1;
}
uint32_t time_get(void) __critical {
systick_t time_get(void) __critical {
return time_overflows;
}

View File

@@ -0,0 +1,58 @@
# SPDX-License-Identifier: GPL-3.0-only
CC = sdcc -mmcs51 -MMD --model-large --code-size $(CODE_SIZE) --xram-size $(SRAM_SIZE) --Werror
AS = sdas8051
ASFLAGS = -plosgff
# XXX: SDCC "requires" main() to be in the first item passed to the linker.
# Ref: SDCC Manual 4.2.8; Section 3.2.3 Projects with Multiple Source Files
MAIN_SRC = $(filter %/main.c, $(SRC))
MAIN_OBJ = $(sort $(patsubst src/%.c, $(BUILD)/%.rel, $(MAIN_SRC)))
# NOTE: sdas *must* be used for assembly files as sdcc cannot compile them
# itself. They must use an extension of `.asm` so they can be filtered here.
ASM_SRC = $(filter %.asm, $(SRC))
ASM_OBJ = $(sort $(patsubst src/%.asm, $(BUILD)/%.rel, $(ASM_SRC)))
C_SRC = $(filter %.c, $(SRC))
C_OBJ = $(sort $(patsubst src/%.c, $(BUILD)/%.rel, $(C_SRC)))
OBJ = $(MAIN_OBJ) $(sort $(ASM_OBJ) $(C_OBJ))
# Run EC rom in simulator
sim: $(BUILD)/ec.rom
cargo run \
--release \
--manifest-path ecsim/Cargo.toml \
--no-default-features \
-- $<
# Convert from Intel Hex file to binary file
$(BUILD)/ec.rom: $(BUILD)/ec.ihx
@echo " OBJCOPY $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
objcopy -I ihex -O binary --gap-fill=0xFF --pad-to=$(CONFIG_EC_FLASH_SIZE) $< $@
# Link object files into Intel Hex file
$(BUILD)/ec.ihx: $(OBJ)
@echo " LINK $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
$(CC) $(LDFLAGS) -o $@ $^
# Compile ASM files into object files
$(ASM_OBJ): $(BUILD)/%.rel: src/%.asm
@echo " AS $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
$(AS) $(ASFLAGS) $@ $<
# Compile C files into object files
$(C_OBJ): $(BUILD)/%.rel: src/%.c $(INCLUDE)
@echo " CC $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
$(CC) $(CFLAGS) -o $@ -c $<
# Add dependency rules
DEP = $(OBJ:%.rel=%.d)
-include $(DEP)

View File

@@ -1,29 +1,6 @@
# SPDX-License-Identifier: GPL-3.0-only
CC=avr-gcc -mmcu=$(EC)
CFLAGS+=-Os -fstack-usage -Wall -Werror -Wl,--gc-sections -Wl,-u,vfprintf -lprintf_flt
OBJ=$(patsubst src/%.c,$(BUILD)/%.o,$(SRC))
# Run EC rom in simulator
sim: $(BUILD)/ec.elf
simavr $< --mcu $(EC)
# Convert from Intel Hex file to binary file
$(BUILD)/ec.rom: $(BUILD)/ec.ihx
@mkdir -p $(@D)
makebin -p < $< > $@
# Convert from ELF file to Intel Hex file
$(BUILD)/ec.ihx: $(BUILD)/ec.elf
@mkdir -p $(@D)
avr-objcopy -j .text -j .data -O ihex $< $@
# Link object files into ELF file
$(BUILD)/ec.elf: $(OBJ)
@mkdir -p $(@D)
$(CC) -o $@ $^
# Compile C files into object files
$(BUILD)/%.o: src/%.c $(INCLUDE)
@mkdir -p $(@D)
$(CC) $(CFLAGS) -o $@ -c $<
arch-y += gpio.c
arch-y += i2c.c
arch-y += i2c_slave.c
arch-y += uart.c

View File

@@ -2,7 +2,7 @@
#include <arch/gpio.h>
bool gpio_get_dir(struct Gpio * gpio) {
bool gpio_get_dir(const struct Gpio *const gpio) {
if (*gpio->ddr & gpio->value) {
return true;
} else {
@@ -10,7 +10,7 @@ bool gpio_get_dir(struct Gpio * gpio) {
}
}
void gpio_set_dir(struct Gpio * gpio, bool value) {
void gpio_set_dir(struct Gpio *const gpio, bool value) {
if (value) {
*gpio->ddr |= gpio->value;
} else {
@@ -18,7 +18,7 @@ void gpio_set_dir(struct Gpio * gpio, bool value) {
}
}
bool gpio_get(struct Gpio * gpio) {
bool gpio_get(const struct Gpio *const gpio) {
if (*gpio->pin & gpio->value) {
return true;
} else {
@@ -26,7 +26,7 @@ bool gpio_get(struct Gpio * gpio) {
}
}
void gpio_set(struct Gpio * gpio, bool value) {
void gpio_set(struct Gpio *const gpio, bool value) {
if (value) {
*gpio->port |= gpio->value;
} else {

View File

@@ -6,81 +6,93 @@
#include <board/cpu.h>
#include <common/i2c.h>
#include <common/macro.h>
#define TIMEOUT (F_CPU/1000)
#define TIMEOUT (F_CPU / 1000)
int i2c_start(struct I2C * i2c, uint8_t addr, bool read) {
uint32_t count;
int16_t i2c_start(struct I2C *const i2c, uint8_t addr, bool read) {
uint32_t count;
// reset TWI control register
TWCR = 0;
// transmit START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait for end of transmission
count = TIMEOUT;
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
if (count == 0) return -1;
// reset TWI control register
TWCR = 0;
// transmit START condition
TWCR = BIT(TWINT) | BIT(TWSTA) | BIT(TWEN);
// wait for end of transmission
count = TIMEOUT;
while (!(TWCR & BIT(TWINT)) && count > 0)
count -= 1;
if (count == 0)
return -1;
// check if the start condition was successfully transmitted
if((TWSR & 0xF8) != TW_START) return -1;
// check if the start condition was successfully transmitted
if ((TWSR & 0xF8) != TW_START)
return -1;
// load slave addr into data register
TWDR = ((addr << 1) | read);
// start transmission of addr
TWCR = (1<<TWINT) | (1<<TWEN);
// wait for end of transmission
count = TIMEOUT;
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
if (count == 0) return -1;
// load slave addr into data register
TWDR = ((addr << 1) | read);
// start transmission of addr
TWCR = BIT(TWINT) | BIT(TWEN);
// wait for end of transmission
count = TIMEOUT;
while (!(TWCR & BIT(TWINT)) && count > 0)
count -= 1;
if (count == 0)
return -1;
// check if the device has acknowledged the READ / WRITE mode
uint8_t twst = TW_STATUS & 0xF8;
if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) return -1;
// check if the device has acknowledged the READ / WRITE mode
uint8_t twst = TW_STATUS;
if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK))
return -1;
return 0;
return 0;
}
void i2c_stop(struct I2C * i2c) {
// transmit STOP condition
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
void i2c_stop(struct I2C *const i2c) {
// transmit STOP condition
TWCR = BIT(TWINT) | BIT(TWEN) | BIT(TWSTO);
}
int i2c_write(struct I2C * i2c, uint8_t * data, int length) {
int i;
for (i = 0; i < length; i++) {
// load data into data register
TWDR = data[i];
// start transmission of data
TWCR = (1<<TWINT) | (1<<TWEN);
// wait for end of transmission
uint32_t count = TIMEOUT;
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
// timed out
if (count == 0) return -1;
// failed to receive ack
if((TWSR & 0xF8) != TW_MT_DATA_ACK) return -1;
}
int16_t i2c_write(struct I2C *const i2c, const uint8_t *const data, uint16_t length) {
uint16_t i;
for (i = 0; i < length; i++) {
// load data into data register
TWDR = data[i];
// start transmission of data
TWCR = BIT(TWINT) | BIT(TWEN);
// wait for end of transmission
uint32_t count = TIMEOUT;
while (!(TWCR & BIT(TWINT)) && count > 0)
count -= 1;
// timed out
if (count == 0)
return -1;
// failed to receive ack
if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
return -1;
}
return i;
return i;
}
int i2c_read(struct I2C * i2c, uint8_t * data, int length) {
int i;
for (i = 0; i < length; i++) {
if ((i + 1) < length) {
// start TWI module and acknowledge data after reception
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
} else {
// start receiving without acknowledging reception
TWCR = (1<<TWINT) | (1<<TWEN);
}
// wait for end of transmission
uint32_t count = TIMEOUT;
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
if (count == 0) return -1;
// return received data from TWDR
data[i] = TWDR;
}
int16_t i2c_read(struct I2C *const i2c, uint8_t *const data, uint16_t length) {
uint16_t i;
for (i = 0; i < length; i++) {
if ((i + 1) < length) {
// start TWI module and acknowledge data after reception
TWCR = BIT(TWINT) | BIT(TWEN) | BIT(TWEA);
} else {
// start receiving without acknowledging reception
TWCR = BIT(TWINT) | BIT(TWEN);
}
// wait for end of transmission
uint32_t count = TIMEOUT;
while (!(TWCR & BIT(TWINT)) && count > 0)
count -= 1;
if (count == 0)
return -1;
// return received data from TWDR
data[i] = TWDR;
}
return i;
return i;
}

View File

@@ -9,81 +9,89 @@
#include <board/cpu.h>
#include <arch/i2c_slave.h>
#include <common/macro.h>
static void (* volatile i2c_slave_new_cb)() = NULL;
static void (* volatile i2c_slave_recv_cb)(uint8_t) = NULL;
static uint8_t (* volatile i2c_slave_send_cb)() = NULL;
// uncrustify:off
static void (*volatile i2c_slave_new_cb)() = NULL;
static void (*volatile i2c_slave_recv_cb)(uint8_t) = NULL;
static uint8_t (*volatile i2c_slave_send_cb)() = NULL;
// uncrustify:on
void i2c_slave_init(uint8_t address, void (*new_cb)(), void (*recv_cb)(uint8_t), uint8_t (*send_cb)()){
// ensure correct behavior by stopping before changing callbacks or address
i2c_slave_stop();
void i2c_slave_init(
uint8_t address,
void (*new_cb)(),
void (*recv_cb)(uint8_t),
uint8_t (*send_cb)()
) {
// ensure correct behavior by stopping before changing callbacks or address
i2c_slave_stop();
// clear interrupts
cli();
// clear interrupts
cli();
// setup callbacks
i2c_slave_new_cb = new_cb;
i2c_slave_recv_cb = recv_cb;
i2c_slave_send_cb = send_cb;
// load address into TWI address register
TWAR = (address << 1);
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
// setup callbacks
i2c_slave_new_cb = new_cb;
i2c_slave_recv_cb = recv_cb;
i2c_slave_send_cb = send_cb;
// load address into TWI address register
TWAR = (address << 1);
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
TWCR = BIT(TWIE) | BIT(TWEA) | BIT(TWINT) | BIT(TWEN);
// set interrupts
sei();
// set interrupts
sei();
}
void i2c_slave_stop(){
// clear interrupts
cli();
void i2c_slave_stop(void) {
// clear interrupts
cli();
// clear acknowledge and enable bits
TWCR &= ~((1<<TWEA) | (1<<TWEN));
// clear address
TWAR = 0;
// remove callbacks
i2c_slave_new_cb = NULL;
i2c_slave_recv_cb = NULL;
i2c_slave_send_cb = NULL;
// clear acknowledge and enable bits
TWCR &= ~(BIT(TWEA) | BIT(TWEN));
// clear address
TWAR = 0;
// remove callbacks
i2c_slave_new_cb = NULL;
i2c_slave_recv_cb = NULL;
i2c_slave_send_cb = NULL;
// set interrupts
sei();
// set interrupts
sei();
}
ISR(TWI_vect) {
uint8_t status = TW_STATUS;
switch(status) {
case TW_SR_SLA_ACK:
// master has started a new transaction, call the new callback
if (i2c_slave_new_cb != NULL) {
i2c_slave_new_cb();
}
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_SR_DATA_ACK:
// received data from master, call the receive callback
if(i2c_slave_send_cb != NULL){
i2c_slave_recv_cb(TWDR);
}
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_SLA_ACK:
case TW_ST_DATA_ACK:
// master is requesting data, call the send callback
if(i2c_slave_recv_cb != NULL) {
TWDR = i2c_slave_send_cb();
}
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_BUS_ERROR:
// some sort of erroneous state, prepare TWI to be readdressed
printf("TWI_vect bus error\n");
TWCR = 0;
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
default:
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
}
uint8_t status = TW_STATUS;
switch (status) {
case TW_SR_SLA_ACK:
// master has started a new transaction, call the new callback
if (i2c_slave_new_cb != NULL) {
i2c_slave_new_cb();
}
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
break;
case TW_SR_DATA_ACK:
// received data from master, call the receive callback
if (i2c_slave_send_cb != NULL) {
i2c_slave_recv_cb(TWDR);
}
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
break;
case TW_ST_SLA_ACK:
case TW_ST_DATA_ACK:
// master is requesting data, call the send callback
if (i2c_slave_recv_cb != NULL) {
TWDR = i2c_slave_send_cb();
}
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
break;
case TW_BUS_ERROR:
// some sort of erroneous state, prepare TWI to be readdressed
printf("TWI_vect bus error\n");
TWCR = 0;
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
break;
default:
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
break;
}
}

View File

@@ -3,14 +3,16 @@
#ifndef _ARCH_GPIO_H
#define _ARCH_GPIO_H
#include <common/macro.h>
#include <avr/io.h>
#include <stdbool.h>
#include <stdint.h>
struct Gpio {
volatile uint8_t * pin;
volatile uint8_t * ddr;
volatile uint8_t * port;
volatile uint8_t *pin;
volatile uint8_t *ddr;
volatile uint8_t *port;
uint8_t value;
};
@@ -18,12 +20,12 @@ struct Gpio {
.pin = &PIN ## BLOCK, \
.ddr = &DDR ## BLOCK, \
.port = &PORT ## BLOCK, \
.value = (1 << NUMBER), \
.value = BIT(NUMBER), \
}
bool gpio_get(struct Gpio * gpio);
void gpio_set(struct Gpio * gpio, bool value);
bool gpio_get_dir(struct Gpio * gpio);
void gpio_set_dir(struct Gpio * gpio, bool value);
bool gpio_get(const struct Gpio *const gpio);
void gpio_set(struct Gpio *const gpio, bool value);
bool gpio_get_dir(const struct Gpio *const gpio);
void gpio_set_dir(struct Gpio *const gpio, bool value);
#endif // _ARCH_GPIO_H

View File

@@ -3,7 +3,12 @@
#ifndef _ARCH_I2C_SLAVE_H
#define _ARCH_I2C_SLAVE_H
void i2c_slave_init(uint8_t address, void (*new_cb)(), void (*recv_cb)(uint8_t), uint8_t (*send_cb)());
void i2c_slave_stop();
void i2c_slave_init(
uint8_t address,
void (*new_cb)(),
void (*recv_cb)(uint8_t),
uint8_t (*send_cb)()
);
void i2c_slave_stop(void);
#endif // _ARCH_I2C_SLAVE_H

View File

@@ -6,12 +6,12 @@
#include <stdint.h>
struct Uart {
volatile uint8_t * a;
volatile uint8_t * b;
volatile uint8_t * c;
volatile uint8_t * data;
volatile uint8_t * baud_l;
volatile uint8_t * baud_h;
volatile uint8_t *a;
volatile uint8_t *b;
volatile uint8_t *c;
volatile uint8_t *data;
volatile uint8_t *baud_l;
volatile uint8_t *baud_h;
uint8_t a_read;
uint8_t a_write;
uint8_t a_init;
@@ -19,18 +19,18 @@ struct Uart {
uint8_t c_init;
};
void uart_init(struct Uart * uart, unsigned long baud);
void uart_init(struct Uart *const uart, uint32_t baud);
int uart_count();
struct Uart * uart_new(int num);
int16_t uart_count(void);
struct Uart *uart_new(int16_t num);
unsigned char uart_can_read(struct Uart * uart);
unsigned char uart_can_write(struct Uart * uart);
uint8_t uart_can_read(struct Uart *const uart);
uint8_t uart_can_write(struct Uart *const uart);
unsigned char uart_read(struct Uart * uart);
void uart_write(struct Uart * uart, unsigned char data);
uint8_t uart_read(struct Uart *const uart);
void uart_write(struct Uart *const uart, uint8_t data);
extern struct Uart * uart_stdio;
void uart_stdio_init(int num, unsigned long baud);
extern struct Uart *uart_stdio;
void uart_stdio_init(int16_t num, uint32_t baud);
#endif // _ARCH_UART_H

49
src/arch/avr/toolchain.mk Normal file
View File

@@ -0,0 +1,49 @@
# SPDX-License-Identifier: GPL-3.0-only
CC = avr-gcc -mmcu=$(EC_VARIANT)
CFLAGS += -MMD -Os -fstack-usage -Wall -Werror \
-Wl,--gc-sections -Wl,-u,vfprintf -lprintf_flt
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523
_gcc_version = $(shell avr-gcc --version 2>/dev/null)
ifneq ($(findstring 12.,$(_gcc_version)),)
CFLAGS += --param=min-pagesize=0
else ifneq ($(findstring 13.,$(_gcc_version)),)
CFLAGS += --param=min-pagesize=0
endif
OBJCOPY = avr-objcopy
OBJ=$(sort $(patsubst src/%.c,$(BUILD)/%.o,$(SRC)))
# Run EC rom in simulator
sim: $(BUILD)/ec.elf
simavr $< --mcu $(EC_VARIANT)
# Convert from Intel Hex file to binary file
$(BUILD)/ec.rom: $(BUILD)/ec.ihx
@echo " OBJCOPY $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
$(OBJCOPY) -I ihex -O binary --gap-fill 0xFF $< $@
# Convert from ELF file to Intel Hex file
$(BUILD)/ec.ihx: $(BUILD)/ec.elf
@echo " OBJCOPY $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
$(OBJCOPY) -j .text -j .data -O ihex $< $@
# Link object files into ELF file
$(BUILD)/ec.elf: $(OBJ)
@echo " LINK $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
$(CC) -o $@ $^
# Compile C files into object files
$(BUILD)/%.o: src/%.c $(INCLUDE)
@echo " CC $(subst $(BUILD)/,,$@)"
mkdir -p $(@D)
$(CC) $(CFLAGS) -o $@ -c $<
# Add dependency rules
DEP = $(OBJ:%.o=%.d)
-include $(DEP)

View File

@@ -22,29 +22,29 @@
}
#if defined(__AVR_ATmega328P__)
static struct Uart UARTS[] = {
UART(0)
};
static struct Uart UARTS[] = {
UART(0)
};
#elif defined(__AVR_ATmega32U4__)
static struct Uart UARTS[] = {
UART(1)
};
static struct Uart UARTS[] = {
UART(1)
};
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
static struct Uart UARTS[] = {
UART(0),
UART(1),
UART(2),
UART(3)
};
static struct Uart UARTS[] = {
UART(0),
UART(1),
UART(2),
UART(3)
};
#else
#error "Could not find UART definitions"
#endif
int uart_count() {
return sizeof(UARTS)/sizeof(struct Uart);
int16_t uart_count(void) {
return sizeof(UARTS) / sizeof(struct Uart);
}
struct Uart * uart_new(int num) {
struct Uart *uart_new(int16_t num) {
if (num < uart_count()) {
return &UARTS[num];
} else {
@@ -52,49 +52,49 @@ struct Uart * uart_new(int num) {
}
}
void uart_init(struct Uart * uart, unsigned long baud) {
unsigned long baud_prescale = (F_CPU / (baud * 16UL)) - 1;
*(uart->baud_h) = (uint8_t)(baud_prescale>>8);
void uart_init(struct Uart *const uart, uint32_t baud) {
uint32_t baud_prescale = (F_CPU / (baud * 16UL)) - 1;
*(uart->baud_h) = (uint8_t)(baud_prescale >> 8);
*(uart->baud_l) = (uint8_t)(baud_prescale);
*(uart->a) = uart->a_init;
*(uart->b) = uart->b_init;
*(uart->c) = uart->c_init;
}
unsigned char uart_can_read(struct Uart * uart) {
uint8_t uart_can_read(struct Uart *const uart) {
return (*(uart->a)) & uart->a_read;
}
unsigned char uart_read(struct Uart * uart) {
while (!uart_can_read(uart)) ;
uint8_t uart_read(struct Uart *const uart) {
while (!uart_can_read(uart)) {}
return *(uart->data);
}
unsigned char uart_can_write(struct Uart * uart) {
uint8_t uart_can_write(struct Uart *const uart) {
return (*(uart->a)) & uart->a_write;
}
void uart_write(struct Uart * uart, unsigned char data) {
while (!uart_can_write(uart)) ;
void uart_write(struct Uart *const uart, uint8_t data) {
while (!uart_can_write(uart)) {}
*(uart->data) = data;
}
struct Uart * uart_stdio = NULL;
struct Uart *uart_stdio = NULL;
int uart_stdio_get(FILE * stream) {
return (int)uart_read(uart_stdio);
int16_t uart_stdio_get(FILE *stream) {
return (int16_t)uart_read(uart_stdio);
}
int uart_stdio_put(char data, FILE * stream) {
uart_write(uart_stdio, (unsigned char)data);
int16_t uart_stdio_put(char data, FILE *stream) {
uart_write(uart_stdio, (uint8_t)data);
return 0;
}
FILE uart_stdio_file = FDEV_SETUP_STREAM(uart_stdio_put, uart_stdio_get, _FDEV_SETUP_RW);
void uart_stdio_init(int num, unsigned long baud) {
struct Uart * uart = uart_new(num);
if(uart != NULL) {
void uart_stdio_init(int16_t num, uint32_t baud) {
struct Uart *uart = uart_new(num);
if (uart != NULL) {
uart_init(uart, baud);
uart_stdio = uart;
stdin = stdout = stderr = &uart_stdio_file;

View File

@@ -4,19 +4,20 @@
#include <common/i2c.h>
int smbus_read(uint8_t address, uint8_t command, uint16_t * data) {
int16_t smbus_read(uint8_t address, uint8_t command, uint16_t *const data) {
return i2c_get(NULL, address, command, (uint8_t *)data, 2);
}
int smbus_write(uint8_t address, uint8_t command, uint16_t data) {
int16_t smbus_write(uint8_t address, uint8_t command, uint16_t data) {
return i2c_set(NULL, address, command, (uint8_t *)&data, 2);
}
void battery_debug(void) {
uint16_t data = 0;
int res = 0;
int16_t res = 0;
#define command(N, A, V) { \
#define command(N, A, V) \
{ \
printf(#N ": "); \
res = smbus_read(A, V, &data); \
if (res < 0) { \
@@ -45,5 +46,5 @@ void battery_debug(void) {
command(ProchotOption1, 0x09, 0x3D);
command(ProchotStatus, 0x09, 0x3A);
#undef command
#undef command
}

View File

@@ -1,6 +1,12 @@
# SPDX-License-Identifier: GPL-3.0-only
EC=atmega2560
board-y += battery.c
board-y += i2c.c
board-y += main.c
board-y += parallel.c
EC=atmega
EC_VARIANT=atmega2560
PORT=$(wildcard /dev/ttyACM*)
CONSOLE_BAUD=1000000
@@ -10,4 +16,4 @@ console:
sudo tio -b $(CONSOLE_BAUD) $(PORT)
flash: $(BUILD)/ec.ihx
sudo avrdude -v -v -p $(EC) -c wiring -P $(PORT) -b 115200 -D -U flash:w:$<:i
sudo avrdude -v -v -p $(EC_VARIANT) -c wiring -P $(PORT) -b 115200 -D -U flash:w:$<:i

View File

@@ -5,8 +5,8 @@
#include <board/cpu.h>
#include <board/i2c.h>
void i2c_init(unsigned long baud) {
TWAR = 0;
TWBR = (uint8_t)(((F_CPU / baud) - 16 ) / 2);
TWCR = 0;
void i2c_init(uint32_t baud) {
TWAR = 0;
TWBR = (uint8_t)(((F_CPU / baud) - 16) / 2);
TWCR = 0;
}

View File

@@ -3,6 +3,6 @@
#ifndef _BOARD_I2C_H
#define _BOARD_I2C_H
void i2c_init(unsigned long baud);
void i2c_init(uint32_t baud);
#endif // _BOARD_I2C_H

View File

@@ -12,7 +12,7 @@ void init(void) {
struct Gpio LED = GPIO(B, 7);
//TODO: .h file
void parallel_main(void);
int parallel_main(void);
int main(void) {
init();

View File

@@ -99,47 +99,51 @@ enum ParallelState {
// Parallel struct definition
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
struct Parallel {
#define PIN(N, P) struct Gpio * N;
#define PIN(N, P) struct Gpio *N;
PINS
#undef PIN
#undef PIN
enum ParallelState state;
};
// Parallel struct instance
static struct Parallel PORT = {
#define PIN(N, P) .N = &GPIOS[P - 1],
#define PIN(N, P) .N = &GPIOS[P - 1],
PINS
#undef PIN
#undef PIN
.state = PARALLEL_STATE_UNKNOWN,
};
// Set port to all high-impedance inputs
void parallel_hiz(struct Parallel * port) {
#define PIN(N, P) \
gpio_set_dir(port->N, false); \
gpio_set(port->N, false);
void parallel_hiz(struct Parallel *const port) {
#define PIN(N, P) \
gpio_set_dir(port->N, false); \
gpio_set(port->N, false);
PINS
#undef PIN
#undef PIN
}
// Place all data lines in high or low impendance state
void parallel_data_dir(struct Parallel * port, bool dir) {
#define DATA_BIT(B) gpio_set_dir(port->d ## B, dir);
void parallel_data_dir(struct Parallel *const port, bool dir) {
#define DATA_BIT(B) gpio_set_dir(port->d##B, dir);
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
}
#define parallel_data_forward(P) parallel_data_dir(P, true)
#define parallel_data_reverse(P) parallel_data_dir(P, false)
void parallel_data_set_high(struct Parallel * port, uint8_t byte) {
void parallel_data_set_high(struct Parallel *const port, uint8_t byte) {
// By convention all lines are high, so only set the ones needed
#define DATA_BIT(B) if (!(byte & (1 << B))) gpio_set(port->d ## B, true);
#define DATA_BIT(B) \
if (!(byte & (1 << B))) { \
gpio_set(port->d##B, true); \
}
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
}
// Set port to initial state required before being able to perform cycles
void parallel_reset(struct Parallel * port, bool host) {
void parallel_reset(struct Parallel *const port, bool host) {
parallel_hiz(port);
// nRESET: output on host, input on peripherals
@@ -164,9 +168,9 @@ void parallel_reset(struct Parallel * port, bool host) {
gpio_set_dir(port->wait_n, !host);
// Pull up data lines on host, leave floating on peripherals
#define DATA_BIT(B) gpio_set(port->d ## B, host);
#define DATA_BIT(B) gpio_set(port->d##B, host);
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
//TODO: something with straps
@@ -178,42 +182,57 @@ void parallel_reset(struct Parallel * port, bool host) {
}
}
void parallel_state(struct Parallel * port, enum ParallelState state) {
void parallel_state(struct Parallel *const port, enum ParallelState state) {
if (port->state != state) {
switch (state) {
case PARALLEL_STATE_UNKNOWN:
return;
case PARALLEL_STATE_HIZ:
parallel_hiz(port);
break;
case PARALLEL_STATE_HOST:
parallel_reset(port, true);
break;
case PARALLEL_STATE_PERIPHERAL:
parallel_reset(port, false);
break;
case PARALLEL_STATE_UNKNOWN:
return;
case PARALLEL_STATE_HIZ:
parallel_hiz(port);
break;
case PARALLEL_STATE_HOST:
parallel_reset(port, true);
break;
case PARALLEL_STATE_PERIPHERAL:
parallel_reset(port, false);
break;
}
port->state = state;
}
}
uint8_t parallel_read_data(struct Parallel * port) {
uint8_t parallel_read_data(struct Parallel *const port) {
uint8_t byte = 0;
#define DATA_BIT(B) if (gpio_get(port->d ## B)) byte |= (1 << B);
#define DATA_BIT(B) \
if (gpio_get(port->d##B)) { \
byte |= (1 << B); \
}
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
return byte;
}
void parallel_write_data(struct Parallel * port, uint8_t byte) {
void parallel_write_data(struct Parallel *const port, uint8_t byte) {
// By convention all lines are high, so only set the ones needed
#define DATA_BIT(B) if (!(byte & (1 << B))) gpio_set(port->d ## B, false);
#define DATA_BIT(B) \
if (!(byte & (1 << B))) { \
gpio_set(port->d##B, false); \
}
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
}
//TODO: timeout
int parallel_transaction(struct Parallel * port, uint8_t * data, int length, bool read, bool addr) {
int16_t parallel_transaction(
struct Parallel *const port,
uint8_t *const data,
int16_t length,
bool read,
bool addr
) {
if (!read) {
// Set write line low
gpio_set(port->write_n, false);
@@ -222,7 +241,7 @@ int parallel_transaction(struct Parallel * port, uint8_t * data, int length, boo
parallel_data_forward(port);
}
int i;
int16_t i;
uint8_t byte = 0;
for (i = 0; i < length; i++) {
// Wait for peripheral to indicate it's ready for next cycle
@@ -255,7 +274,7 @@ int parallel_transaction(struct Parallel * port, uint8_t * data, int length, boo
// Set data strobe high
gpio_set(port->data_n, true);
}
// Wait for peripheral to indicate it's ready for next cycle
while (gpio_get(port->wait_n)) {}
@@ -283,14 +302,23 @@ int parallel_transaction(struct Parallel * port, uint8_t * data, int length, boo
// host write -> peripheral read
// host read -> peripheral write
bool parallel_peripheral_cycle(struct Parallel * port, uint8_t * data, bool * read, bool * addr) {
bool parallel_peripheral_cycle(
struct Parallel *const port,
uint8_t *const data,
bool *const read,
bool *const addr
) {
if (!gpio_get(port->reset_n)) {
// XXX: Give host some time to get ready
_delay_ms(1);
return false;
}
while (gpio_get(port->data_n) && gpio_get(port->addr_n)) {}
// Check for data or address cycle
if (gpio_get(port->data_n) && gpio_get(port->addr_n)) {
// No cycle ready
return false;
}
*read = gpio_get(port->write_n);
*addr = !gpio_get(port->addr_n);
@@ -301,10 +329,11 @@ bool parallel_peripheral_cycle(struct Parallel * port, uint8_t * data, bool * re
parallel_write_data(port, *data);
}
// Tell host we are ready for cycle
gpio_set(port->wait_n, true);
// Wait for host to finish strobe
while (!gpio_get(port->addr_n) || !gpio_get(port->data_n)) {}
while (!gpio_get(port->data_n) || !gpio_get(port->addr_n)) {}
if (*read) {
// Set data lines back to inputs
@@ -314,7 +343,7 @@ bool parallel_peripheral_cycle(struct Parallel * port, uint8_t * data, bool * re
*data = parallel_read_data(port);
}
// Tell host we're ready for next cycle
// Tell host we are ready for next cycle
gpio_set(port->wait_n, false);
return true;
@@ -322,39 +351,84 @@ bool parallel_peripheral_cycle(struct Parallel * port, uint8_t * data, bool * re
static uint8_t ADDRESS_INDAR1 = 0x05;
static uint8_t ADDRESS_INDDR = 0x08;
static uint8_t ADDRESS_ECMSADDR0 = 0x2E;
static uint8_t ADDRESS_ECMSADDR1 = 0x2F;
static uint8_t ADDRESS_ECMSDATA = 0x30;
static uint8_t ZERO = 0x00;
static uint8_t SPI_ENABLE = 0xFE;
static uint8_t SPI_DATA = 0xFD;
int16_t parallel_ecms_read(
struct Parallel *const port,
uint16_t addr,
uint8_t *const data,
int16_t length
) {
int16_t res;
res = parallel_set_address(port, &ADDRESS_ECMSADDR1, 1);
if (res < 0)
return res;
res = parallel_write(port, ((uint8_t *)&addr) + 1, 1);
if (res < 0)
return res;
res = parallel_set_address(port, &ADDRESS_ECMSADDR0, 1);
if (res < 0)
return res;
res = parallel_write(port, (uint8_t *)&addr, 1);
if (res < 0)
return res;
res = parallel_set_address(port, &ADDRESS_ECMSDATA, 1);
if (res < 0)
return res;
return parallel_read(port, data, length);
}
// Disable chip
int parallel_spi_reset(struct Parallel *port) {
int res;
int16_t parallel_spi_reset(struct Parallel *const port) {
int16_t res;
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_write(port, &SPI_ENABLE, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_set_address(port, &ADDRESS_INDDR, 1);
if (res < 0) return res;
if (res < 0)
return res;
return parallel_write(port, &ZERO, 1);
}
// Enable chip and read or write data
int parallel_spi_transaction(struct Parallel *port, uint8_t * data, int length, bool read) {
int res;
int16_t parallel_spi_transaction(
struct Parallel *const port,
uint8_t *const data,
int16_t length,
bool read
) {
int16_t res;
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_write(port, &SPI_DATA, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_set_address(port, &ADDRESS_INDDR, 1);
if (res < 0) return res;
if (res < 0)
return res;
return parallel_transaction(port, data, length, read, false);
}
@@ -363,16 +437,22 @@ int parallel_spi_transaction(struct Parallel *port, uint8_t * data, int length,
#define parallel_spi_write(P, D, L) parallel_spi_transaction(P, D, L, false)
// "Hardware" accelerated SPI programming, requires ECINDARs to be set
int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, bool initialized) {
int16_t parallel_spi_program(
struct Parallel *const port,
const uint8_t *const data,
int16_t length,
bool initialized
) {
static uint8_t aai[6] = { 0xAD, 0, 0, 0, 0, 0 };
int res;
int i;
int16_t res;
int16_t i;
uint8_t status;
for(i = 0; (i + 1) < length; i+=2) {
for (i = 0; (i + 1) < length; i += 2) {
// Disable chip to begin command
res = parallel_spi_reset(port);
if (res < 0) return res;
if (res < 0)
return res;
if (!initialized) {
// If not initialized, the start address must be sent
@@ -384,7 +464,8 @@ int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, boo
aai[5] = data[i + 1];
res = parallel_spi_write(port, aai, 6);
if (res < 0) return res;
if (res < 0)
return res;
initialized = true;
} else {
@@ -392,36 +473,41 @@ int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, boo
aai[2] = data[i + 1];
res = parallel_spi_write(port, aai, 3);
if (res < 0) return res;
if (res < 0)
return res;
}
// Wait for SPI busy flag to clear
for (;;) {
// Disable chip to begin command
res = parallel_spi_reset(port);
if (res < 0) return res;
if (res < 0)
return res;
status = 0x05;
res = parallel_spi_write(port, &status, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_spi_read(port, &status, 1);
if (res < 0) return res;
if (res < 0)
return res;
if (!(status & 1)) break;
if (!(status & 1))
break;
}
}
return i;
}
int serial_transaction(uint8_t * data, int length, bool read) {
int i;
int16_t serial_transaction(uint8_t *const data, int16_t length, bool read) {
int16_t i;
for (i = 0; i < length; i++) {
if (read) {
data[i] = (uint8_t)uart_read(uart_stdio);
} else {
uart_write(uart_stdio, (unsigned char)data[i]);
uart_write(uart_stdio, (uint8_t)data[i]);
}
}
@@ -432,25 +518,26 @@ int serial_transaction(uint8_t * data, int length, bool read) {
#define serial_write(D, L) serial_transaction(D, L, false)
int parallel_main(void) {
int res = 0;
int16_t res = 0;
struct Parallel * port = &PORT;
struct Parallel *port = &PORT;
parallel_state(port, PARALLEL_STATE_HIZ);
static uint8_t data[128];
char command;
int length;
int i;
int16_t length;
int16_t i;
uint8_t address;
bool set_address = false;
bool program_aai = false;
unsigned char console_msg[] = "Entering console mode\n";
uint8_t console_msg[] = "Entering console mode\n";
for (;;) {
// Read command and length
res = serial_read(data, 2);
if (res < 0) goto err;
if (res < 0)
goto err;
// Command is a character
command = (char)data[0];
@@ -466,125 +553,185 @@ int parallel_main(void) {
}
// Length is received data + 1
length = ((int)data[1]) + 1;
length = ((int16_t)data[1]) + 1;
// Truncate length to size of data
if (length > sizeof(data)) length = sizeof(data);
if (length > sizeof(data))
length = sizeof(data);
switch (command) {
// Buffer size
case 'B':
// Fill buffer size - 1
for (i = 0; i < length; i++) {
if (i == 0) {
data[i] = (uint8_t)(sizeof(data) - 1);
} else {
data[i] = 0;
}
// Buffer size
case 'B':
// Fill buffer size - 1
for (i = 0; i < length; i++) {
if (i == 0) {
data[i] = (uint8_t)(sizeof(data) - 1);
} else {
data[i] = 0;
}
}
// Write data to serial
res = serial_write(data, length);
if (res < 0) goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0)
goto err;
break;
break;
// Debug console
case 'C':
parallel_state(port, PARALLEL_STATE_PERIPHERAL);
// Debug console
case 'C':
// Set parallel lines to peripheral mode
parallel_state(port, PARALLEL_STATE_PERIPHERAL);
serial_write(console_msg, sizeof(console_msg));
for (;;) {
bool read = false;
bool addr = false;
bool ret = parallel_peripheral_cycle(port, data, &read, &addr);
if (ret && !read && !addr) {
// Tell the user the console is ready
serial_write(console_msg, sizeof(console_msg));
for (;;) {
bool read = false;
bool addr = false;
if (parallel_peripheral_cycle(port, data, &read, &addr)) {
if (!read && !addr) {
res = serial_write(data, 1);
if (res < 0) goto err;
if (res < 0)
goto err;
}
}
}
break;
break;
// Echo
case 'E':
// Read data from serial
res = serial_read(data, length);
if (res < 0) goto err;
// Echo
case 'E':
// Read data from serial
res = serial_read(data, length);
if (res < 0)
goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0) goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0)
goto err;
break;
break;
// Read data
case 'R':
parallel_state(port, PARALLEL_STATE_HOST);
// Forced debug console (can be used on all firmware but may miss bytes)
case 'F':
serial_write(console_msg, sizeof(console_msg));
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0) goto err;
set_address = false;
// We must be in host mode
parallel_state(port, PARALLEL_STATE_HOST);
uint16_t head = 0;
for (;;) {
// Read current position
res = parallel_ecms_read(port, 0xF00, data, 1);
if (res < 0)
goto err;
uint16_t tail = (uint16_t)data[0];
if (tail == 0 || head == tail) {
// No new data
continue;
}
// Read data from parallel
res = parallel_read(port, data, length);
if (res < 0) goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0) goto err;
break;
// Accelerated program function
case 'P':
parallel_state(port, PARALLEL_STATE_HOST);
// Read data from serial
res = serial_read(data, length);
if (res < 0) goto err;
// Run accelerated programming function
res = parallel_spi_program(port, data, length, program_aai);
if (res < 0) goto err;
program_aai = true;
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0) goto err;
break;
// Write data
case 'W':
parallel_state(port, PARALLEL_STATE_HOST);
// Read data from serial
res = serial_read(data, length);
if (res < 0) goto err;
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0) goto err;
set_address = false;
if (head == 0) {
// Set head if necessary
head = tail;
continue;
}
// Write data to parallel
res = parallel_write(port, data, length);
if (res < 0) goto err;
while (head != tail) {
head += 1;
if (head >= 256) {
head = 1;
}
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0) goto err;
// Read byte at head
res = parallel_ecms_read(port, 0xF00 + head, data, 1);
if (res < 0)
goto err;
break;
// Print read byte
serial_write(data, 1);
}
}
break;
// Read data
case 'R':
parallel_state(port, PARALLEL_STATE_HOST);
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0)
goto err;
set_address = false;
}
// Read data from parallel
res = parallel_read(port, data, length);
if (res < 0)
goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0)
goto err;
break;
// Accelerated program function
case 'P':
parallel_state(port, PARALLEL_STATE_HOST);
// Read data from serial
res = serial_read(data, length);
if (res < 0)
goto err;
// Run accelerated programming function
res = parallel_spi_program(port, data, length, program_aai);
if (res < 0)
goto err;
program_aai = true;
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0)
goto err;
break;
// Write data
case 'W':
parallel_state(port, PARALLEL_STATE_HOST);
// Read data from serial
res = serial_read(data, length);
if (res < 0)
goto err;
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0)
goto err;
set_address = false;
}
// Write data to parallel
res = parallel_write(port, data, length);
if (res < 0)
goto err;
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0)
goto err;
break;
}
}

View File

@@ -1,6 +1,9 @@
# SPDX-License-Identifier: GPL-3.0-only
EC=atmega32u4
board-y += main.c
EC=atmega
EC_VARIANT=atmega32u4
PORT=$(wildcard /dev/ttyACM*)
CONSOLE_BAUD=1000000
@@ -10,4 +13,4 @@ console:
sudo tio -b $(CONSOLE_BAUD) $(PORT)
flash: $(BUILD)/ec.ihx
sudo avrdude -v -v -p $(EC) -c avr109 -P $(PORT) -b 115200 -D -U flash:w:$<:i
sudo avrdude -v -v -p $(EC_VARIANT) -c avr109 -P $(PORT) -b 115200 -D -U flash:w:$<:i

View File

@@ -4,19 +4,20 @@
#include <common/i2c.h>
int smbus_read(uint8_t address, uint8_t command, uint16_t * data) {
int16_t smbus_read(uint8_t address, uint8_t command, uint16_t *data) {
return i2c_get(NULL, address, command, (uint8_t *)data, 2);
}
int smbus_write(uint8_t address, uint8_t command, uint16_t data) {
int16_t smbus_write(uint8_t address, uint8_t command, uint16_t data) {
return i2c_set(NULL, address, command, (uint8_t *)&data, 2);
}
void battery_debug(void) {
uint16_t data = 0;
int res = 0;
int16_t res = 0;
#define command(N, A, V) { \
#define command(N, A, V) \
{ \
printf(#N ": "); \
res = smbus_read(A, V, &data); \
if (res < 0) { \
@@ -45,5 +46,5 @@ void battery_debug(void) {
command(ProchotOption1, 0x09, 0x3D);
command(ProchotStatus, 0x09, 0x3A);
#undef command
#undef command
}

View File

@@ -1,6 +1,12 @@
# SPDX-License-Identifier: GPL-3.0-only
EC=atmega328p
board-y += battery.c
board-y += i2c.c
board-y += main.c
board-y += parallel.c
EC=atmega
EC_VARIANT=atmega328p
PORT=$(wildcard /dev/ttyACM*)
CONSOLE_BAUD=1000000
@@ -10,4 +16,4 @@ console:
sudo tio -b $(CONSOLE_BAUD) $(PORT)
flash: $(BUILD)/ec.ihx
sudo avrdude -v -v -p $(EC) -c arduino -P $(PORT) -b 115200 -D -U flash:w:$<:i
sudo avrdude -v -v -p $(EC_VARIANT) -c arduino -P $(PORT) -b 115200 -D -U flash:w:$<:i

View File

@@ -5,8 +5,8 @@
#include <board/cpu.h>
#include <board/i2c.h>
void i2c_init(unsigned long baud) {
TWAR = 0;
TWBR = (uint8_t)(((F_CPU / baud) - 16 ) / 2);
TWCR = 0;
void i2c_init(uint32_t baud) {
TWAR = 0;
TWBR = (uint8_t)(((F_CPU / baud) - 16) / 2);
TWCR = 0;
}

View File

@@ -3,6 +3,6 @@
#ifndef _BOARD_I2C_H
#define _BOARD_I2C_H
void i2c_init(unsigned long baud);
void i2c_init(uint32_t baud);
#endif // _BOARD_I2C_H

View File

@@ -12,7 +12,7 @@ void init(void) {
struct Gpio LED = GPIO(B, 5);
//TODO: .h file
void parallel_main(void);
int parallel_main(void);
int main(void) {
init();

View File

@@ -65,49 +65,53 @@ static struct Gpio GPIOS[13] = {
GPIO(C, 0),
};
// Parallel struct definition
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
struct Parallel {
#define PIN(N, P) struct Gpio * N;
#define PIN(N, P) struct Gpio *N;
PINS
#undef PIN
#undef PIN
};
// Parallel struct instance
static struct Parallel PORT = {
#define PIN(N, P) .N = &GPIOS[P - 1],
#define PIN(N, P) .N = &GPIOS[P - 1],
PINS
#undef PIN
#undef PIN
};
// Set port to all high-impedance inputs
void parallel_hiz(struct Parallel * port) {
#define PIN(N, P) \
gpio_set_dir(port->N, false); \
gpio_set(port->N, false);
void parallel_hiz(struct Parallel *const port) {
#define PIN(N, P) \
gpio_set_dir(port->N, false); \
gpio_set(port->N, false);
PINS
#undef PIN
#undef PIN
}
// Place all data lines in high or low impendance state
void parallel_data_dir(struct Parallel * port, bool dir) {
#define DATA_BIT(B) gpio_set_dir(port->d ## B, dir);
void parallel_data_dir(struct Parallel *const port, bool dir) {
#define DATA_BIT(B) gpio_set_dir(port->d##B, dir);
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
}
#define parallel_data_forward(P) parallel_data_dir(P, true)
#define parallel_data_reverse(P) parallel_data_dir(P, false)
void parallel_data_set_high(struct Parallel * port, uint8_t byte) {
void parallel_data_set_high(struct Parallel *const port, uint8_t byte) {
// By convention all lines are high, so only set the ones needed
#define DATA_BIT(B) if (!(byte & (1 << B))) gpio_set(port->d ## B, true);
#define DATA_BIT(B) \
if (!(byte & (1 << B))) { \
gpio_set(port->d##B, true); \
}
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
}
// Set port to initial state required before being able to perform cycles
void parallel_reset(struct Parallel * port, bool host) {
void parallel_reset(struct Parallel *const port, bool host) {
parallel_hiz(port);
// nRESET: output on host, input on peripherals
@@ -132,9 +136,9 @@ void parallel_reset(struct Parallel * port, bool host) {
gpio_set_dir(port->wait_n, !host);
// Pull up data lines on host, leave floating on peripherals
#define DATA_BIT(B) gpio_set(port->d ## B, host);
#define DATA_BIT(B) gpio_set(port->d##B, host);
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
//TODO: something with straps
@@ -146,23 +150,37 @@ void parallel_reset(struct Parallel * port, bool host) {
}
}
uint8_t parallel_read_data(struct Parallel * port) {
uint8_t parallel_read_data(struct Parallel *const port) {
uint8_t byte = 0;
#define DATA_BIT(B) if (gpio_get(port->d ## B)) byte |= (1 << B);
#define DATA_BIT(B) \
if (gpio_get(port->d##B)) { \
byte |= (1 << B); \
}
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
return byte;
}
void parallel_write_data(struct Parallel * port, uint8_t byte) {
void parallel_write_data(struct Parallel *const port, uint8_t byte) {
// By convention all lines are high, so only set the ones needed
#define DATA_BIT(B) if (!(byte & (1 << B))) gpio_set(port->d ## B, false);
#define DATA_BIT(B) \
if (!(byte & (1 << B))) { \
gpio_set(port->d##B, false); \
}
DATA_BITS
#undef DATA_BIT
#undef DATA_BIT
}
//TODO: timeout
int parallel_transaction(struct Parallel * port, uint8_t * data, int length, bool read, bool addr) {
int16_t parallel_transaction(
struct Parallel *const port,
uint8_t *const data,
int16_t length,
bool read,
bool addr
) {
if (!read) {
// Set write line low
gpio_set(port->write_n, false);
@@ -171,7 +189,7 @@ int parallel_transaction(struct Parallel * port, uint8_t * data, int length, boo
parallel_data_forward(port);
}
int i;
int16_t i;
uint8_t byte = 0;
for (i = 0; i < length; i++) {
// Wait for peripheral to indicate it's ready for next cycle
@@ -233,7 +251,12 @@ int parallel_transaction(struct Parallel * port, uint8_t * data, int length, boo
// host write -> peripheral read
// host read -> peripheral write
bool parallel_peripheral_cycle(struct Parallel * port, uint8_t * data, bool * read, bool * addr) {
bool parallel_peripheral_cycle(
struct Parallel *const port,
uint8_t *const data,
bool *const read,
bool *const addr
) {
if (!gpio_get(port->reset_n)) {
// XXX: Give host some time to get ready
_delay_ms(1);
@@ -278,33 +301,44 @@ static uint8_t SPI_ENABLE = 0xFE;
static uint8_t SPI_DATA = 0xFD;
// Disable chip
int parallel_spi_reset(struct Parallel *port) {
int res;
int16_t parallel_spi_reset(struct Parallel *const port) {
int16_t res;
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_write(port, &SPI_ENABLE, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_set_address(port, &ADDRESS_INDDR, 1);
if (res < 0) return res;
if (res < 0)
return res;
return parallel_write(port, &ZERO, 1);
}
// Enable chip and read or write data
int parallel_spi_transaction(struct Parallel *port, uint8_t * data, int length, bool read) {
int res;
int16_t parallel_spi_transaction(
struct Parallel *const port,
uint8_t *const data,
int16_t length,
bool read
) {
int16_t res;
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_write(port, &SPI_DATA, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_set_address(port, &ADDRESS_INDDR, 1);
if (res < 0) return res;
if (res < 0)
return res;
return parallel_transaction(port, data, length, read, false);
}
@@ -313,16 +347,22 @@ int parallel_spi_transaction(struct Parallel *port, uint8_t * data, int length,
#define parallel_spi_write(P, D, L) parallel_spi_transaction(P, D, L, false)
// "Hardware" accelerated SPI programming, requires ECINDARs to be set
int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, bool initialized) {
int16_t parallel_spi_program(
struct Parallel *const port,
const uint8_t *const data,
int16_t length,
bool initialized
) {
static uint8_t aai[6] = { 0xAD, 0, 0, 0, 0, 0 };
int res;
int i;
int16_t res;
int16_t i;
uint8_t status;
for(i = 0; (i + 1) < length; i+=2) {
for (i = 0; (i + 1) < length; i += 2) {
// Disable chip to begin command
res = parallel_spi_reset(port);
if (res < 0) return res;
if (res < 0)
return res;
if (!initialized) {
// If not initialized, the start address must be sent
@@ -334,7 +374,8 @@ int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, boo
aai[5] = data[i + 1];
res = parallel_spi_write(port, aai, 6);
if (res < 0) return res;
if (res < 0)
return res;
initialized = true;
} else {
@@ -342,36 +383,41 @@ int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, boo
aai[2] = data[i + 1];
res = parallel_spi_write(port, aai, 3);
if (res < 0) return res;
if (res < 0)
return res;
}
// Wait for SPI busy flag to clear
for (;;) {
// Disable chip to begin command
res = parallel_spi_reset(port);
if (res < 0) return res;
if (res < 0)
return res;
status = 0x05;
res = parallel_spi_write(port, &status, 1);
if (res < 0) return res;
if (res < 0)
return res;
res = parallel_spi_read(port, &status, 1);
if (res < 0) return res;
if (res < 0)
return res;
if (!(status & 1)) break;
if (!(status & 1))
break;
}
}
return i;
}
int serial_transaction(uint8_t * data, int length, bool read) {
int i;
int16_t serial_transaction(uint8_t *const data, int16_t length, bool read) {
int16_t i;
for (i = 0; i < length; i++) {
if (read) {
data[i] = (uint8_t)uart_read(uart_stdio);
} else {
uart_write(uart_stdio, (unsigned char)data[i]);
uart_write(uart_stdio, (uint8_t)data[i]);
}
}
@@ -381,26 +427,27 @@ int serial_transaction(uint8_t * data, int length, bool read) {
#define serial_read(D, L) serial_transaction(D, L, true)
#define serial_write(D, L) serial_transaction(D, L, false)
int parallel_main(void) {
int res = 0;
int16_t parallel_main(void) {
int16_t res = 0;
struct Parallel * port = &PORT;
struct Parallel *port = &PORT;
parallel_reset(port, true);
static uint8_t data[128];
char command;
int length;
int i;
int16_t length;
int16_t i;
uint8_t address;
bool set_address = false;
bool program_aai = false;
unsigned char console_msg[] = "Entering console mode\n";
uint8_t console_msg[] = "Entering console mode\n";
for (;;) {
// Read command and length
res = serial_read(data, 2);
if (res < 0) goto err;
if (res < 0)
goto err;
// Command is a character
command = (char)data[0];
@@ -416,120 +463,135 @@ int parallel_main(void) {
}
// Length is received data + 1
length = ((int)data[1]) + 1;
length = ((int16_t)data[1]) + 1;
// Truncate length to size of data
if (length > sizeof(data)) length = sizeof(data);
if (length > sizeof(data))
length = sizeof(data);
switch (command) {
// Buffer size
case 'B':
// Fill buffer size - 1
for (i = 0; i < length; i++) {
if (i == 0) {
data[i] = (uint8_t)(sizeof(data) - 1);
} else {
data[i] = 0;
}
// Buffer size
case 'B':
// Fill buffer size - 1
for (i = 0; i < length; i++) {
if (i == 0) {
data[i] = (uint8_t)(sizeof(data) - 1);
} else {
data[i] = 0;
}
}
// Write data to serial
res = serial_write(data, length);
if (res < 0) goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0)
goto err;
break;
break;
// Debug console
case 'C':
serial_write(console_msg, sizeof(console_msg));
// Debug console
case 'C':
serial_write(console_msg, sizeof(console_msg));
// Reconfigure as a peripheral
parallel_reset(port, false);
// Reconfigure as a peripheral
parallel_reset(port, false);
for (;;) {
bool read = false;
bool addr = false;
bool ret = parallel_peripheral_cycle(port, data, &read, &addr);
for (;;) {
bool read = false;
bool addr = false;
bool ret = parallel_peripheral_cycle(port, data, &read, &addr);
if (ret && !read && !addr) {
res = serial_write(data, 1);
if (res < 0) goto err;
}
if (ret && !read && !addr) {
res = serial_write(data, 1);
if (res < 0)
goto err;
}
}
break;
break;
// Echo
case 'E':
// Read data from serial
res = serial_read(data, length);
if (res < 0) goto err;
// Echo
case 'E':
// Read data from serial
res = serial_read(data, length);
if (res < 0)
goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0) goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0)
goto err;
break;
break;
// Read data
case 'R':
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0) goto err;
set_address = false;
}
// Read data
case 'R':
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0)
goto err;
set_address = false;
}
// Read data from parallel
res = parallel_read(port, data, length);
if (res < 0) goto err;
// Read data from parallel
res = parallel_read(port, data, length);
if (res < 0)
goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0) goto err;
// Write data to serial
res = serial_write(data, length);
if (res < 0)
goto err;
break;
break;
// Accelerated program function
case 'P':
// Read data from serial
res = serial_read(data, length);
if (res < 0) goto err;
// Accelerated program function
case 'P':
// Read data from serial
res = serial_read(data, length);
if (res < 0)
goto err;
// Run accelerated programming function
res = parallel_spi_program(port, data, length, program_aai);
if (res < 0) goto err;
program_aai = true;
// Run accelerated programming function
res = parallel_spi_program(port, data, length, program_aai);
if (res < 0)
goto err;
program_aai = true;
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0) goto err;
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0)
goto err;
break;
break;
// Write data
case 'W':
// Read data from serial
res = serial_read(data, length);
if (res < 0) goto err;
// Write data
case 'W':
// Read data from serial
res = serial_read(data, length);
if (res < 0)
goto err;
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0) goto err;
set_address = false;
}
// Update parallel address if necessary
if (set_address) {
res = parallel_set_address(port, &address, 1);
if (res < 0)
goto err;
set_address = false;
}
// Write data to parallel
res = parallel_write(port, data, length);
if (res < 0) goto err;
// Write data to parallel
res = parallel_write(port, data, length);
if (res < 0)
goto err;
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0) goto err;
// Send ACK of data length
data[0] = (uint8_t)(length - 1);
res = serial_write(data, 1);
if (res < 0)
goto err;
break;
break;
}
}

View File

@@ -1,14 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <arch/time.h>
#include <board/battery.h>
#include <board/board.h>
#include <board/dgpu.h>
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
extern uint8_t main_cycle;
@@ -20,10 +14,6 @@ void board_init(void) {
gpio_set(&BKL_EN, true);
// Enable camera
gpio_set(&CCD_EN, true);
// Enable wireless
gpio_set(&BT_EN, true);
gpio_set(&WLAN_EN, true);
gpio_set(&WLAN_PWR_EN, true);
// Enable right USB port
gpio_set(&USB_PWR_EN_N, false);
// Assert SMI#, SCI#, and SWI#
@@ -32,45 +22,7 @@ void board_init(void) {
gpio_set(&SWI_N, true);
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
if (main_cycle == 0) {
// Set keyboard LEDs
static uint8_t last_kbc_leds = 0;

View File

@@ -1,13 +1,21 @@
# SPDX-License-Identifier: GPL-3.0-only
EC=it8587e
board-y += board.c
board-y += gpio.c
# Add keymap to src
KEYMAP?=default
SRC+=$(BOARD_DIR)/keymap/$(KEYMAP).c
EC=ite
CONFIG_EC_ITE_IT8587E=y
CONFIG_EC_FLASH_SIZE_128K = y
# Set discrete GPU I2C bus
CFLAGS+=-DI2C_DGPU=I2C_1
# Intel-based host
CONFIG_PLATFORM_INTEL = y
# Include keyboard
KEYBOARD=15in_102
# Set keyboard LED mechanism
CONFIG_HAVE_KBLED = y
KBLED=rgb_pwm
# Set battery I2C bus
CFLAGS+=-DI2C_SMBUS=I2C_0
@@ -17,41 +25,38 @@ CFLAGS+=-DPS2_TOUCHPAD=PS2_3
# Set smart charger parameters
CFLAGS+=\
-DCHARGER_CHARGE_CURRENT=1536 \
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=10 \
-DCHARGER_CHARGE_CURRENT=3072 \
-DCHARGER_CHARGE_VOLTAGE=12600 \
-DCHARGER_INPUT_CURRENT=11800
# Set battery charging thresholds
CFLAGS+=\
-DBATTERY_START_THRESHOLD=0 \
-DBATTERY_END_THRESHOLD=100
# Set CPU power limits in watts
CFLAGS+=\
-DPOWER_LIMIT_AC=180 \
-DPOWER_LIMIT_DC=28
-DPOWER_LIMIT_DC=45
# Custom fan curve
CFLAGS+=-DBOARD_HEATUP=5
CFLAGS+=-DBOARD_COOLDOWN=20
CFLAGS+=-DBOARD_FAN_POINTS="\
# Enable dGPU support
CONFIG_HAVE_DGPU = y
CFLAGS += -DI2C_DGPU=I2C_1
# Fan configs
CFLAGS += -DFAN1_PWM=DCR2
CFLAGS += -DBOARD_FAN1_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100) \
FAN_POINT(80, 100), \
"
# Enable DGPU support
CFLAGS+=-DHAVE_DGPU=1
CFLAGS+=-DBOARD_DGPU_HEATUP=5
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
CFLAGS += -DFAN2_PWM=DCR4
CFLAGS += -DBOARD_FAN2_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100) \
FAN_POINT(80, 100), \
"
# Add system76 common code

View File

@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/gpio.h>
#include <common/debug.h>
#include <common/macro.h>
// uncrustify:off
struct Gpio __code ACIN_N = GPIO(B, 6);
struct Gpio __code AC_PRESENT = GPIO(E, 7);
struct Gpio __code ALL_SYS_PWRGD = GPIO(C, 0);
@@ -25,10 +26,12 @@ struct Gpio __code LED_NUM_N = GPIO(J, 4);
struct Gpio __code LED_PWR = GPIO(H, 5);
struct Gpio __code LED_SCROLL_N = GPIO(J, 3);
struct Gpio __code LID_SW_N = GPIO(D, 1);
struct Gpio __code ME_WE = GPIO(I, 2);
struct Gpio __code PM_CLKRUN_N = GPIO(H, 0); // renamed to ECCLKRUN#
struct Gpio __code PM_PWROK = GPIO(C, 6);
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
struct Gpio __code PWR_SW_N = GPIO(D, 0);
struct Gpio __code RGBKB_DET_N = GPIO(E, 2);
struct Gpio __code SB_KBCRST_N = GPIO(E, 6);
struct Gpio __code SCI_N = GPIO(D, 4);
struct Gpio __code SMI_N = GPIO(D, 3);
@@ -39,27 +42,28 @@ struct Gpio __code USB_PWR_EN_N = GPIO(F, 7);
struct Gpio __code VA_EC_EN = GPIO(J, 0); // renamed to SLP_SUS_EC#
struct Gpio __code WLAN_EN = GPIO(J, 2);
struct Gpio __code WLAN_PWR_EN = GPIO(B, 0);
// uncrustify:on
void gpio_init() {
void gpio_init(void) {
// Enable LPC reset on GPD2
GCR = 0x04;
// Set GPIO data
// SYS_FAN
GPDRA = (1 << 3);
GPDRA = BIT(3);
GPDRB = 0x00;
GPDRC = 0x00;
// PWR_BTN#, SCI#, SMI#
GPDRD = (1 << 5) | (1 << 4) | (1 << 3);
GPDRD = BIT(5) | BIT(4) | BIT(3);
GPDRE = 0x00;
// H_PECI
GPDRF = (1 << 6);
GPDRF = BIT(6);
// AIRPLAN_LED#
GPDRG = (1 << 6);
GPDRG = BIT(6);
GPDRH = 0x00;
GPDRI = 0x00;
// LED_CAP#, LED_NUM#, LED_SCROLL#, KBC_MUTE#
GPDRJ = (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1);
GPDRJ = BIT(5) | BIT(4) | BIT(3) | BIT(1);
// Set GPIO control
// EC_PWM_LEDKB_P
@@ -101,11 +105,11 @@ void gpio_init() {
// SMD_VGA_THERM
GPCRC2 = GPIO_OUT;
// KB-SO16
GPCRC3 = GPIO_IN | GPIO_UP;
GPCRC3 = GPIO_ALT | GPIO_UP;
// CNVI_DET#_EC
GPCRC4 = GPIO_IN | GPIO_UP;
// KB-SO17
GPCRC5 = GPIO_IN | GPIO_UP;
GPCRC5 = GPIO_ALT | GPIO_UP;
// PM_PWROK
GPCRC6 = GPIO_OUT;
// LED_ACIN
@@ -188,8 +192,6 @@ void gpio_init() {
GPCRH5 = GPIO_OUT | GPIO_UP;
// SUSB#_PCH
GPCRH6 = GPIO_IN;
// TODO
GPCRH7 = GPIO_IN;
// BAT_DET
GPCRI0 = GPIO_ALT;
// BAT_VOLT
@@ -237,40 +239,3 @@ void gpio_init() {
// SERIRQ
GPCRM6 = GPIO_ALT;
}
#if GPIO_DEBUG
void gpio_debug_bank(
char * bank,
uint8_t data,
uint8_t mirror,
uint8_t pot,
volatile uint8_t * control
) {
for(char i = 0; i < 8; i++) {
DEBUG(
"%s%d:\n\tdata %d\n\tmirror %d\n\tpot %d\n\tcontrol %02X\n",
bank,
i,
(data >> i) & 1,
(mirror >> i) & 1,
(pot >> i) & 1,
*(control + i)
);
}
}
void gpio_debug(void) {
#define bank(BANK) gpio_debug_bank(#BANK, GPDR ## BANK, GPDMR ## BANK, GPOT ## BANK, &GPCR ## BANK ## 0)
bank(A);
bank(B);
bank(C);
bank(D);
bank(E);
bank(F);
bank(G);
bank(H);
bank(I);
bank(J);
#undef bank
}
#endif

View File

@@ -5,14 +5,7 @@
#include <ec/gpio.h>
#define GPIO_ALT 0x00
#define GPIO_IN 0x80
#define GPIO_OUT 0x40
#define GPIO_UP 0x04
#define GPIO_DOWN 0x02
void gpio_init(void);
void gpio_debug(void);
extern struct Gpio __code ACIN_N;
extern struct Gpio __code AC_PRESENT;
@@ -36,12 +29,14 @@ extern struct Gpio __code LED_NUM_N;
extern struct Gpio __code LED_PWR;
extern struct Gpio __code LED_SCROLL_N;
extern struct Gpio __code LID_SW_N;
extern struct Gpio __code ME_WE;
#define HAVE_PCH_DPWROK_EC 0
#define HAVE_PCH_PWROK_EC 0
extern struct Gpio __code PM_CLKRUN_N;
extern struct Gpio __code PM_PWROK;
extern struct Gpio __code PWR_BTN_N;
extern struct Gpio __code PWR_SW_N;
extern struct Gpio __code RGBKB_DET_N;
extern struct Gpio __code SB_KBCRST_N;
extern struct Gpio __code SCI_N;
#define HAVE_SLP_SUS_N 0

View File

@@ -1,36 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/kbled.h>
#include <ec/pwm.h>
void kbled_init(void) {
//TODO: enable PWMs
kbled_reset();
}
void kbled_reset(void) {
// Set brightness and color
kbled_set_color(0xFFFFFF);
kbled_set(0x00);
}
uint8_t kbled_get(void) {
// Get PWM for power
return DCR0;
}
void kbled_set(uint8_t level) {
// Set PWM for power
DCR0 = level;
}
void kbled_set_color(uint32_t color) {
// Set PWM for blue component
DCR7 = (uint8_t)(color);
// Set PWM for green component
DCR6 = (uint8_t)(color >> 8);
// Set PWM for red component
DCR5 = (uint8_t)(color >> 16);
}

View File

@@ -1,24 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
// Default layout
#include <board/keymap.h>
uint16_t __code KEYMAP[KM_LAY][KM_OUT][KM_IN] = {
LAYOUT(
K_ESC, K_F1, K_F2, K_F3, K_F4, K_F5, K_F6, K_F7, K_F8, K_F9, K_F10, K_F11, K_F12, K_PRINT_SCREEN, K_INSERT, K_DEL, K_HOME, K_END, K_PGUP, K_PGDN,
K_TICK, K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9, K_0, K_MINUS, K_EQUALS, K_BKSP, K_NUM_LOCK, K_NUM_SLASH, K_NUM_ASTERISK, K_NUM_MINUS,
K_TAB, K_Q, K_W, K_E, K_R, K_T, K_Y, K_U, K_I, K_O, K_P, K_BRACE_OPEN, K_BRACE_CLOSE, K_BACKSLASH, K_NUM_7, K_NUM_8, K_NUM_9, K_NUM_PLUS,
KT_FN, K_A, K_S, K_D, K_F, K_G, K_H, K_J, K_K, K_L, K_SEMICOLON, K_QUOTE, K_ENTER, K_NUM_4, K_NUM_5, K_NUM_6,
K_LEFT_SHIFT, K_Z, K_X, K_C, K_V, K_B, K_N, K_M, K_COMMA, K_PERIOD, K_SLASH, K_RIGHT_SHIFT, K_UP, K_NUM_1, K_NUM_2, K_NUM_3, K_NUM_ENTER,
K_LEFT_CTRL, KT_FN, K_LEFT_ALT, K_LEFT_SUPER, K_SPACE, KT_FN, K_RIGHT_ALT, K_RIGHT_CTRL, K_LEFT, K_DOWN, K_RIGHT, K_NUM_0, K_NUM_PERIOD
),
LAYOUT(
K_ESC, K_TOUCHPAD, K_DISPLAY_TOGGLE, K_MUTE, K_F4, K_VOLUME_DOWN, K_VOLUME_UP, K_DISPLAY_MODE, K_BRIGHTNESS_DOWN, K_BRIGHTNESS_UP, K_CAMERA_TOGGLE, K_AIRPLANE_MODE, K_SUSPEND, K_PRINT_SCREEN, K_INSERT, K_DEL, K_HOME, K_END, K_PGUP, K_PGDN,
K_PLAY_PAUSE, K_FAN_TOGGLE, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9, K_0, K_MINUS, K_EQUALS, K_DEL, K_NUM_LOCK, K_KBD_COLOR, K_KBD_TOGGLE, K_KBD_DOWN,
K_TAB, K_Q, K_W, K_E, K_R, K_T, K_Y, K_PGUP, K_HOME, K_PGDN, K_P, K_BRACE_OPEN, K_BRACE_CLOSE, K_BACKSLASH, K_NUM_7, K_NUM_8, K_NUM_9, K_KBD_UP,
KT_FN, K_A, K_S, K_D, K_F, K_G, K_LEFT, K_DOWN, K_UP, K_RIGHT, K_BKSP, K_DEL, K_ENTER, K_NUM_4, K_NUM_5, K_NUM_6,
K_LEFT_SHIFT, K_Z, K_X, K_C, K_V, K_B, K_END, K_M, K_COMMA, K_PERIOD, K_SLASH, K_RIGHT_SHIFT, K_UP, K_NUM_1, K_NUM_2, K_NUM_3, K_NUM_ENTER,
K_LEFT_CTRL, KT_FN, K_LEFT_ALT, K_LEFT_SUPER, K_ESC, KT_FN, K_RIGHT_ALT, K_RIGHT_CTRL, K_LEFT, K_DOWN, K_RIGHT, K_NUM_0, K_NUM_PERIOD
)
};

View File

@@ -1,15 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <arch/time.h>
#include <board/battery.h>
#include <board/board.h>
#include <board/dgpu.h>
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
#include <ec/ec.h>
extern uint8_t main_cycle;
@@ -18,65 +14,14 @@ void board_init(void) {
gpio_set(&BKL_EN, true);
// Enable camera
gpio_set(&CCD_EN, true);
// Enable wireless
gpio_set(&WLAN_EN, true);
gpio_set(&WLAN_PWR_EN, true);
// Assert SMI#, SCI#, and SWI#
gpio_set(&SCI_N, true);
gpio_set(&SMI_N, true);
gpio_set(&SWI_N, true);
// Enable POST codes
SPCTRL1 |= 0xC8;
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
// Read POST codes
while (P80H81HS & 1) {
uint8_t p80h = P80HD;
uint8_t p81h = P81HD;
P80H81HS |= 1;
DEBUG("POST %02X%02X\n", p81h, p80h);
}
ec_read_post_codes();
if (main_cycle == 0) {
// Set keyboard LEDs

View File

@@ -1,13 +1,21 @@
# SPDX-License-Identifier: GPL-3.0-only
EC=it5570e
board-y += board.c
board-y += gpio.c
# Add keymap to src
KEYMAP?=default
SRC+=$(BOARD_DIR)/keymap/$(KEYMAP).c
EC=ite
CONFIG_EC_ITE_IT5570E=y
CONFIG_EC_FLASH_SIZE_128K = y
# Set discrete GPU I2C bus
CFLAGS+=-DI2C_DGPU=I2C_1
# Intel-based host
CONFIG_PLATFORM_INTEL = y
# Include keyboard
KEYBOARD=15in_102
# Set keyboard LED mechanism
CONFIG_HAVE_KBLED = y
KBLED=rgb_pwm
# Set battery I2C bus
CFLAGS+=-DI2C_SMBUS=I2C_4
@@ -17,41 +25,38 @@ CFLAGS+=-DPS2_TOUCHPAD=PS2_3
# Set smart charger parameters
CFLAGS+=\
-DCHARGER_CHARGE_CURRENT=1536 \
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=10 \
-DCHARGER_CHARGE_CURRENT=3072 \
-DCHARGER_CHARGE_VOLTAGE=12600 \
-DCHARGER_INPUT_CURRENT=11800
# Set battery charging thresholds
CFLAGS+=\
-DBATTERY_START_THRESHOLD=0 \
-DBATTERY_END_THRESHOLD=100
# Set CPU power limits in watts
CFLAGS+=\
-DPOWER_LIMIT_AC=180 \
-DPOWER_LIMIT_DC=28
-DPOWER_LIMIT_DC=45
# Custom fan curve
CFLAGS+=-DBOARD_HEATUP=5
CFLAGS+=-DBOARD_COOLDOWN=20
CFLAGS+=-DBOARD_FAN_POINTS="\
# Enable dGPU support
CONFIG_HAVE_DGPU = y
CFLAGS += -DI2C_DGPU=I2C_1
# Fan configs
CFLAGS += -DFAN1_PWM=DCR2
CFLAGS += -DBOARD_FAN1_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100) \
FAN_POINT(80, 100), \
"
# Enable DGPU support
CFLAGS+=-DHAVE_DGPU=1
CFLAGS+=-DBOARD_DGPU_HEATUP=5
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
CFLAGS += -DFAN2_PWM=DCR4
CFLAGS += -DBOARD_FAN2_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100) \
FAN_POINT(80, 100), \
"
# Add system76 common code

View File

@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/gpio.h>
#include <common/debug.h>
#include <common/macro.h>
// uncrustify:off
struct Gpio __code ACIN_N = GPIO(B, 0);
struct Gpio __code AC_PRESENT = GPIO(E, 1);
struct Gpio __code ALL_SYS_PWRGD = GPIO(C, 0);
@@ -24,10 +25,12 @@ struct Gpio __code LED_NUM_N = GPIO(G, 0);
struct Gpio __code LED_PWR = GPIO(D, 0);
struct Gpio __code LED_SCROLL_N = GPIO(J, 3);
struct Gpio __code LID_SW_N = GPIO(B, 1);
struct Gpio __code ME_WE = GPIO(I, 2);
struct Gpio __code PM_CLKRUN_N = GPIO(H, 0); // renamed to ECCLKRUN#
struct Gpio __code PM_PWROK = GPIO(C, 6);
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
struct Gpio __code PWR_SW_N = GPIO(B, 3);
struct Gpio __code RGBKB_DET_N = GPIO(I, 5);
struct Gpio __code SCI_N = GPIO(D, 3);
struct Gpio __code SMI_N = GPIO(D, 4);
struct Gpio __code SUSB_N_PCH = GPIO(H, 6);
@@ -37,33 +40,39 @@ struct Gpio __code VA_EC_EN = GPIO(J, 4);
struct Gpio __code WLAN_EN = GPIO(G, 1);
struct Gpio __code WLAN_PWR_EN = GPIO(J, 7);
struct Gpio __code XLP_OUT = GPIO(B, 4);
// uncrustify:on
void gpio_init(void) {
// PWRSW WDT 2 Enable 2
GCR9 = BIT(5);
// PWRSW WDT 2 Enable 1
GCR8 = BIT(4);
void gpio_init() {
// Enable LPC reset on GPD2
GCR = 0x04;
// Enable SMBus channel 4
GCR15 = (1 << 4);
GCR15 = BIT(4);
// Set GPF2 and GPF3 to 3.3V
GCR20 = 0;
// Set GPIO data
GPDRA = 0x00;
// XLP_OUT, PWR_SW#
GPDRB = (1 << 4) | (1 << 3);
GPDRB = BIT(4) | BIT(3);
GPDRC = 0x00;
// PWR_BTN#, SCI#, SMI#
GPDRD = (1 << 5) | (1 << 4) | (1 << 3);
GPDRD = BIT(5) | BIT(4) | BIT(3);
// PLVDD_RST_EC
GPDRE = (1 << 6);
GPDRE = BIT(6);
// EC_PECI
GPDRF = (1 << 6);
GPDRF = BIT(6);
// H_PROCHOT#_EC, LED_NUM#
GPDRG = (1 << 6) | (1 << 0);
GPDRG = BIT(6) | BIT(0);
// AIRPLAN_LED#
GPDRH = 0x80; // (1 << 7)
GPDRH = BIT(7);
GPDRI = 0x00;
// LED_SCROLL#, LED_CAP#
GPDRJ = (1 << 3) | (1 << 2);
GPDRJ = BIT(3) | BIT(2);
// Set GPIO control
// EC_PWM_LEDKB_P
@@ -96,8 +105,6 @@ void gpio_init() {
GPCRB5 = GPIO_OUT | GPIO_UP;
// SUSBC_EN
GPCRB6 = GPIO_OUT | GPIO_UP;
//
GPCRB7 = GPIO_IN;
// ALL_SYS_PWRGD
GPCRC0 = GPIO_IN;
// SMC_VGA_THERM
@@ -105,11 +112,11 @@ void gpio_init() {
// SMD_VGA_THERM
GPCRC2 = GPIO_ALT;
// KB-SO16
GPCRC3 = GPIO_IN;
GPCRC3 = GPIO_ALT | GPIO_UP;
// CNVI_DET#_EC
GPCRC4 = GPIO_IN | GPIO_UP;
// KB-SO17
GPCRC5 = GPIO_IN;
GPCRC5 = GPIO_ALT | GPIO_UP;
// PM_PWROK
GPCRC6 = GPIO_OUT;
// LED_ACIN
@@ -241,40 +248,3 @@ void gpio_init() {
// SERIRQ
GPCRM6 = GPIO_ALT;
}
#if GPIO_DEBUG
void gpio_debug_bank(
char * bank,
uint8_t data,
uint8_t mirror,
uint8_t pot,
volatile uint8_t * control
) {
for(char i = 0; i < 8; i++) {
DEBUG(
"%s%d:\n\tdata %d\n\tmirror %d\n\tpot %d\n\tcontrol %02X\n",
bank,
i,
(data >> i) & 1,
(mirror >> i) & 1,
(pot >> i) & 1,
*(control + i)
);
}
}
void gpio_debug(void) {
#define bank(BANK) gpio_debug_bank(#BANK, GPDR ## BANK, GPDMR ## BANK, GPOT ## BANK, &GPCR ## BANK ## 0)
bank(A);
bank(B);
bank(C);
bank(D);
bank(E);
bank(F);
bank(G);
bank(H);
bank(I);
bank(J);
#undef bank
}
#endif

View File

@@ -5,19 +5,13 @@
#include <ec/gpio.h>
#define GPIO_ALT 0x00
#define GPIO_IN 0x80
#define GPIO_OUT 0x40
#define GPIO_UP 0x04
#define GPIO_DOWN 0x02
void gpio_init(void);
void gpio_debug(void);
extern struct Gpio __code ACIN_N;
extern struct Gpio __code AC_PRESENT;
extern struct Gpio __code ALL_SYS_PWRGD;
extern struct Gpio __code BKL_EN;
#define HAVE_BT_EN 0
extern struct Gpio __code BUF_PLT_RST_N;
extern struct Gpio __code CCD_EN;
extern struct Gpio __code DD_ON;
@@ -35,12 +29,14 @@ extern struct Gpio __code LED_NUM_N;
extern struct Gpio __code LED_PWR;
extern struct Gpio __code LED_SCROLL_N;
extern struct Gpio __code LID_SW_N;
extern struct Gpio __code ME_WE;
#define HAVE_PCH_DPWROK_EC 0
#define HAVE_PCH_PWROK_EC 0
extern struct Gpio __code PM_CLKRUN_N; // renamed to ECCLKRUN#
extern struct Gpio __code PM_PWROK;
extern struct Gpio __code PWR_BTN_N;
extern struct Gpio __code PWR_SW_N;
extern struct Gpio __code RGBKB_DET_N;
extern struct Gpio __code SCI_N;
#define HAVE_SLP_SUS_N 0
extern struct Gpio __code SMI_N;

View File

@@ -1,36 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/kbled.h>
#include <ec/pwm.h>
void kbled_init(void) {
//TODO: enable PWMs
kbled_reset();
}
void kbled_reset(void) {
// Set brightness and color
kbled_set_color(0xFFFFFF);
kbled_set(0x00);
}
uint8_t kbled_get(void) {
// Get PWM for power
return DCR0;
}
void kbled_set(uint8_t level) {
// Set PWM for power
DCR0 = level;
}
void kbled_set_color(uint32_t color) {
// Set PWM for blue component
DCR7 = (uint8_t)(color);
// Set PWM for green component
DCR6 = (uint8_t)(color >> 8);
// Set PWM for red component
DCR5 = (uint8_t)(color >> 16);
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/battery.h>
#include <board/board.h>
#include <board/espi.h>
#include <board/gctrl.h>
#include <board/gpio.h>
#include <common/debug.h>
#include <ec/ec.h>
void board_init(void) {
espi_init();
// Make sure charger is in off state, also enables PSYS
battery_charger_disable();
// Allow backlight to be turned on
gpio_set(&BKL_EN, true);
// Enable camera
gpio_set(&CCD_EN, true);
}
void board_event(void) {
espi_event();
ec_read_post_codes();
}

View File

@@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-3.0-only
board-y += board.c
board-y += gpio.c
EC=ite
CONFIG_EC_ITE_IT5570E=y
CONFIG_EC_FLASH_SIZE_128K = y
# Intel-based host
CONFIG_PLATFORM_INTEL = y
CONFIG_BUS_ESPI=y
# Enable firmware security
CONFIG_SECURITY=y
# Include keyboard
KEYBOARD=15in_102
# Set keyboard LED mechanism
CONFIG_HAVE_KBLED = y
KBLED=rgb_pwm
# Set battery I2C bus
CFLAGS+=-DI2C_SMBUS=I2C_4
# Set touchpad PS2 bus
CFLAGS+=-DPS2_TOUCHPAD=PS2_3
# Set smart charger parameters
# TODO: actually bq24800
# FIXME: Verify parts and values.
CHARGER=bq24780s
CFLAGS+=\
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=10 \
-DCHARGER_CHARGE_CURRENT=1536 \
-DCHARGER_CHARGE_VOLTAGE=17600 \
-DCHARGER_INPUT_CURRENT=14000
# Set CPU power limits in watts
CFLAGS+=\
-DPOWER_LIMIT_AC=280 \
-DPOWER_LIMIT_DC=55
# Enable dGPU support
CONFIG_HAVE_DGPU = y
CFLAGS += -DI2C_DGPU=I2C_1
# Fan configs
CFLAGS += -DFAN1_PWM=DCR2
CFLAGS += -DBOARD_FAN1_HEATUP=5
CFLAGS += -DBOARD_FAN1_COOLDOWN=20
CFLAGS += -DBOARD_FAN1_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100), \
"
CFLAGS += -DFAN2_PWM=DCR4
CFLAGS += -DBOARD_FAN2_HEATUP=5
CFLAGS += -DBOARD_FAN2_COOLDOWN=20
CFLAGS += -DBOARD_FAN2_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100), \
"
# Add system76 common code
include src/board/system76/common/common.mk

View File

@@ -0,0 +1,272 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/gpio.h>
#include <common/macro.h>
// uncrustify:off
struct Gpio __code ACIN_N = GPIO(B, 0);
struct Gpio __code AC_PRESENT = GPIO(E, 1);
struct Gpio __code ALL_SYS_PWRGD = GPIO(C, 0);
struct Gpio __code BKL_EN = GPIO(C, 7);
struct Gpio __code BUF_PLT_RST_N = GPIO(D, 2); // renamed to ESPI_RESET_N
struct Gpio __code CCD_EN = GPIO(D, 1);
struct Gpio __code DD_ON = GPIO(E, 4);
struct Gpio __code DGPU_PWR_EN = GPIO(J, 2);
struct Gpio __code EC_EN = GPIO(B, 6); // renamed to SUSBC_EN#
struct Gpio __code EC_RSMRST_N = GPIO(E, 5);
struct Gpio __code GC6_FB_EN = GPIO(J, 3);
struct Gpio __code LAN_WAKEUP_N = GPIO(B, 2);
struct Gpio __code LED_ACIN = GPIO(H, 2);
struct Gpio __code LED_BAT_CHG = GPIO(H, 5);
struct Gpio __code LED_BAT_FULL = GPIO(J, 0);
struct Gpio __code LED_PWR = GPIO(D, 0);
struct Gpio __code LID_SW_N = GPIO(B, 1);
struct Gpio __code ME_WE = GPIO(H, 0);
struct Gpio __code PCH_DPWROK_EC = GPIO(F, 3);
struct Gpio __code PM_PWROK = GPIO(C, 6);
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
struct Gpio __code PWR_SW_N = GPIO(B, 3);
struct Gpio __code RGBKB_DET_N = GPIO(E, 2);
struct Gpio __code SLP_SUS_N = GPIO(H, 7);
struct Gpio __code VA_EC_EN = GPIO(J, 4);
struct Gpio __code WLAN_EN = GPIO(G, 1);
struct Gpio __code WLAN_PWR_EN = GPIO(D, 3);
struct Gpio __code XLP_OUT = GPIO(B, 4);
// uncrustify:on
void gpio_init(void) {
// PWRSW WDT 2 Enable 2
GCR9 = BIT(5);
// PWRSW WDT 2 Enable 1
GCR8 = BIT(4);
// Enable LPC reset on GPD2
GCR = 0x04;
// Disable UARTs
GCR6 = 0;
// Enable SMBus channel 4
GCR15 = BIT(4);
// Set GPD2 to 1.8V
GCR19 = BIT(0);
// Set GPF2 and GPF3 to 3.3V
GCR20 = 0;
//TODO: what do these do?
GCR1 = 0;
GCR2 = 0;
GCR10 = 0x02;
GCR21 = 0;
GCR22 = 0x80;
GCR22 = 0x80;
GCR23 = 0x01;
// Set GPIO data
GPDRA = 0;
// BL_PWM_EN_EC, XLP_OUT
GPDRB = BIT(5) | BIT(4);
GPDRC = 0;
// PLVDD_RST_EC
GPDRD = BIT(4);
// USB_PWR_EN
GPDRE = BIT(3);
// PCH_DPWROK_EC
GPDRF = BIT(3);
// H_PROCHOT_EC
GPDRG = BIT(6);
GPDRH = 0;
GPDRI = 0;
// CC_EN
GPDRJ = BIT(7);
GPOTA = 0;
GPOTB = 0;
GPOTD = 0;
GPOTE = 0;
GPOTF = 0;
GPOTH = 0;
GPOTJ = 0;
// Set GPIO control
// EC_PWM_LEDKB_P
GPCRA0 = GPIO_ALT;
// KBC_BEEP
GPCRA1 = GPIO_ALT;
// CPU_FAN
GPCRA2 = GPIO_ALT;
// DDS_EC_PWM
GPCRA3 = GPIO_IN;
// VGA_FAN
GPCRA4 = GPIO_ALT;
// EC_PWM_LEDKB_R
GPCRA5 = GPIO_ALT;
// EC_PWM_LEDKB_G
GPCRA6 = GPIO_ALT;
// EC_PWM_LEDKB_B
GPCRA7 = GPIO_ALT;
// AC_IN#
GPCRB0 = GPIO_IN | GPIO_UP;
// LID_SW#
GPCRB1 = GPIO_IN | GPIO_UP;
// LAN_WAKEUP#
GPCRB2 = GPIO_IN;
// PWR_SW#
GPCRB3 = GPIO_IN;
// XLP_OUT
GPCRB4 = GPIO_OUT;
// BL_PWM_EN_EC
GPCRB5 = GPIO_OUT;
// SUSBC_EC#
GPCRB6 = GPIO_OUT | GPIO_UP;
// ALL_SYS_PWRGD
GPCRC0 = GPIO_IN;
// SMC_VGA_THERM
GPCRC1 = GPIO_ALT | GPIO_UP;
// SMD_VGA_THERM
GPCRC2 = GPIO_ALT | GPIO_UP;
// KB_SO16
GPCRC3 = GPIO_ALT | GPIO_UP;
// CNVI_DET#
GPCRC4 = GPIO_IN | GPIO_UP;
// KB_SO17
GPCRC5 = GPIO_ALT | GPIO_UP;
// PM_PWROK
GPCRC6 = GPIO_OUT;
// BKL_EN
GPCRC7 = GPIO_OUT | GPIO_UP;
// LED_PWR
GPCRD0 = GPIO_OUT | GPIO_UP;
// CCD_EN
GPCRD1 = GPIO_OUT;
// ESPI_RESET#
GPCRD2 = GPIO_ALT;
// WLAN_PWR_EN
GPCRD3 = GPIO_OUT;
// PLVDD_RST_EC
GPCRD4 = GPIO_OUT;
// PWR_BTN#
GPCRD5 = GPIO_OUT | GPIO_UP;
// CPU_FANSEN
GPCRD6 = GPIO_ALT;
// VGA_FANSEN
GPCRD7 = GPIO_ALT;
// SMC_BAT
GPCRE0 = GPIO_ALT | GPIO_UP;
// AC_PRESENT
GPCRE1 = GPIO_OUT | GPIO_UP;
// RGBKB-DET#
GPCRE2 = GPIO_IN | GPIO_UP;
// USB_PWR_EN
GPCRE3 = GPIO_OUT;
// DD_ON
GPCRE4 = GPIO_OUT | GPIO_DOWN;
// EC_RSMRST#
GPCRE5 = GPIO_OUT;
// SB_KBCRST#
GPCRE6 = GPIO_IN;
// SMD_BAT
GPCRE7 = GPIO_ALT | GPIO_UP;
// 80CLK
GPCRF0 = GPIO_IN;
// USB_CHARGE_EN
GPCRF1 = GPIO_OUT | GPIO_UP;
// 3IN1
GPCRF2 = GPIO_IN | GPIO_UP;
// PCH_DPWROK_EC
GPCRF3 = GPIO_OUT;
// TP_CLK
GPCRF4 = GPIO_ALT | GPIO_UP;
// TP_DATA
GPCRF5 = GPIO_ALT | GPIO_UP;
// H_PECI
GPCRF6 = GPIO_ALT;
// SINK_CTRL
GPCRF7 = GPIO_IN;
// EC_GPG0
GPCRG0 = GPIO_IN;
// WLAN_EN
GPCRG1 = GPIO_OUT;
// AUTO_LOAD_PWR
GPCRG2 = GPIO_IN;
// ALSPI_CE#
GPCRG3 = GPIO_ALT;
// ALSPI_MSI
GPCRG4 = GPIO_ALT;
// ALSPI_MSO
GPCRG5 = GPIO_ALT;
// H_PROCHOT_EC
GPCRG6 = GPIO_OUT | GPIO_UP;
// ALSPI_SCLK
GPCRG7 = GPIO_ALT;
// ME_WE
GPCRH0 = GPIO_OUT;
// SUSC#_PCH
GPCRH1 = GPIO_IN;
// LED_ACIN
GPCRH2 = GPIO_OUT | GPIO_UP;
// MUX_CTRL_BIOS
GPCRH3 = GPIO_OUT;
// ACE_I2C_IRQ2Z_EC
GPCRH4 = GPIO_IN;
// LED_BAT_CHG
GPCRH5 = GPIO_OUT | GPIO_UP;
// SUSB#_PCH
GPCRH6 = GPIO_IN;
// SLP_SUS#
GPCRH7 = GPIO_IN;
// BAT_DET
GPCRI0 = GPIO_ALT;
// BAT_VOLT
GPCRI1 = GPIO_ALT;
// THERM_VOLT2
GPCRI2 = GPIO_ALT;
// THERM_VOLT
GPCRI3 = GPIO_ALT;
// TOTAL_CUR
GPCRI4 = GPIO_ALT;
// CC1_DET
GPCRI5 = GPIO_IN;
// CC2_DET
GPCRI6 = GPIO_IN;
// MODEL_ID
GPCRI7 = GPIO_IN;
// LED_BAT_FULL
GPCRJ0 = GPIO_OUT | GPIO_UP;
// KBC_MUTE#
GPCRJ1 = GPIO_IN;
// DGPU_PWR_EN
GPCRJ2 = GPIO_IN;
// GC6_FB_EN_PCH
GPCRJ3 = GPIO_IN;
// VA_EC_EN
GPCRJ4 = GPIO_OUT;
// VBATT_BOOST#
GPCRJ5 = GPIO_IN;
// EC_GPIO
GPCRJ6 = GPIO_IN;
// CC_EN
GPCRJ7 = GPIO_OUT;
// ESPI_IO0_EC
GPCRM0 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO1_EC
GPCRM1 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO2_EC
GPCRM2 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO3_EC
GPCRM3 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_CLK_EC
GPCRM4 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_CS_EC#
GPCRM5 = GPIO_ALT;
// SERIRQ_ESPI_ALERT0
GPCRM6 = GPIO_IN | GPIO_UP | GPIO_DOWN;
}

View File

@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-only
#ifndef _BOARD_GPIO_H
#define _BOARD_GPIO_H
#include <ec/gpio.h>
void gpio_init(void);
extern struct Gpio __code ACIN_N;
extern struct Gpio __code AC_PRESENT;
extern struct Gpio __code ALL_SYS_PWRGD;
extern struct Gpio __code BKL_EN;
#define HAVE_BT_EN 0
extern struct Gpio __code BUF_PLT_RST_N;
extern struct Gpio __code CCD_EN;
extern struct Gpio __code DD_ON;
extern struct Gpio __code DGPU_PWR_EN;
extern struct Gpio __code EC_EN;
extern struct Gpio __code EC_RSMRST_N;
extern struct Gpio __code GC6_FB_EN;
extern struct Gpio __code LAN_WAKEUP_N;
extern struct Gpio __code LED_ACIN;
#define HAVE_LED_AIRPLANE_N 0
extern struct Gpio __code LED_BAT_CHG;
extern struct Gpio __code LED_BAT_FULL;
extern struct Gpio __code LED_PWR;
extern struct Gpio __code LID_SW_N;
extern struct Gpio __code ME_WE;
extern struct Gpio __code PCH_DPWROK_EC;
#define HAVE_PCH_PWROK_EC 0
extern struct Gpio __code PM_PWROK;
extern struct Gpio __code PWR_BTN_N;
extern struct Gpio __code PWR_SW_N;
extern struct Gpio __code RGBKB_DET_N;
extern struct Gpio __code SLP_SUS_N;
#define HAVE_SUS_PWR_ACK 0
extern struct Gpio __code VA_EC_EN;
extern struct Gpio __code WLAN_EN;
extern struct Gpio __code WLAN_PWR_EN;
extern struct Gpio __code XLP_OUT;
#endif // _BOARD_GPIO_H

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/battery.h>
#include <board/board.h>
#include <board/espi.h>
#include <board/gctrl.h>
#include <board/gpio.h>
#include <common/debug.h>
#include <ec/ec.h>
void board_init(void) {
espi_init();
// Make sure charger is in off state, also enables PSYS
battery_charger_disable();
// Allow backlight to be turned on
gpio_set(&BKL_EN, true);
// Enable camera
gpio_set(&CCD_EN, true);
}
void board_event(void) {
espi_event();
ec_read_post_codes();
}

View File

@@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-3.0-only
board-y += board.c
board-y += gpio.c
EC = ite
CONFIG_EC_ITE_IT5570E = y
CONFIG_EC_FLASH_SIZE_256K = y
# Intel-based host
CONFIG_PLATFORM_INTEL = y
CONFIG_BUS_ESPI = y
CONFIG_PECI_OVER_ESPI = y
# Enable firmware security
CONFIG_SECURITY = y
# Set keyboard configs
KEYBOARD = 18H9LHA04
CONFIG_HAVE_KBLED = y
KBLED = rgb_pwm
# Set touchpad PS2 bus
CFLAGS += -DPS2_TOUCHPAD=PS2_3
# Set smart charger parameters
CHARGER = oz26786
CFLAGS += -DI2C_SMBUS=I2C_4
CFLAGS += \
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=10 \
-DCHARGER_CHARGE_CURRENT=3072 \
-DCHARGER_CHARGE_VOLTAGE=17400 \
-DCHARGER_INPUT_CURRENT=11500
# Set CPU power limits in watts
CFLAGS += \
-DPOWER_LIMIT_AC=230 \
-DPOWER_LIMIT_DC=45
# Enable DGPU support
CONFIG_HAVE_DGPU = y
CFLAGS += -DI2C_DGPU=I2C_1
# Fan configs
CFLAGS += -DFAN1_PWM=DCR2
CFLAGS += -DBOARD_FAN1_HEATUP=5
CFLAGS += -DBOARD_FAN1_COOLDOWN=20
CFLAGS += -DBOARD_FAN1_POINTS="\
FAN_POINT(60, 28), \
FAN_POINT(65, 28), \
FAN_POINT(70, 40), \
FAN_POINT(75, 60), \
FAN_POINT(80, 75), \
FAN_POINT(85, 90), \
FAN_POINT(90, 100), \
"
CFLAGS += -DFAN2_PWM=DCR4
CFLAGS += -DBOARD_FAN2_HEATUP=5
CFLAGS += -DBOARD_FAN2_COOLDOWN=20
CFLAGS += -DBOARD_FAN2_POINTS="\
FAN_POINT(60, 28), \
FAN_POINT(65, 28), \
FAN_POINT(70, 40), \
FAN_POINT(75, 60), \
FAN_POINT(80, 75), \
FAN_POINT(85, 90), \
FAN_POINT(90, 100), \
"
# Add system76 common code
include src/board/system76/common/common.mk

View File

@@ -0,0 +1,259 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/gpio.h>
#include <common/macro.h>
// uncrustify:off
struct Gpio __code ACIN_N = GPIO(B, 0);
struct Gpio __code AC_PRESENT = GPIO(E, 1);
struct Gpio __code ALL_SYS_PWRGD = GPIO(C, 0);
struct Gpio __code BKL_EN = GPIO(C, 7);
struct Gpio __code BUF_PLT_RST_N = GPIO(D, 2); // renamed to ESPI_RESET_N
struct Gpio __code CCD_EN = GPIO(D, 1);
struct Gpio __code DD_ON = GPIO(E, 4);
struct Gpio __code DGPU_PWR_EN = GPIO(H, 6);
struct Gpio __code EC_EN = GPIO(B, 6); // renamed to SUSBC_EN#
struct Gpio __code EC_RSMRST_N = GPIO(E, 5);
struct Gpio __code GC6_FB_EN = GPIO(B, 5);
struct Gpio __code LAN_WAKEUP_N = GPIO(B, 2);
struct Gpio __code LED_ACIN = GPIO(H, 2);
struct Gpio __code LED_BAT_CHG = GPIO(H, 5);
struct Gpio __code LED_BAT_FULL = GPIO(J, 0);
struct Gpio __code LED_PWR = GPIO(D, 0);
struct Gpio __code LID_SW_N = GPIO(B, 1);
struct Gpio __code ME_WE = GPIO(I, 2);
struct Gpio __code PCH_DPWROK_EC = GPIO(F, 3);
struct Gpio __code PM_PWROK = GPIO(C, 6);
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
struct Gpio __code PWR_SW_N = GPIO(B, 3);
struct Gpio __code RGBKB_DET_N = GPIO(E, 2);
struct Gpio __code SLP_SUS_N = GPIO(H, 7);
struct Gpio __code VA_EC_EN = GPIO(J, 4);
//struct Gpio __code WLAN_EN = GPIO(G, 1);
struct Gpio __code WLAN_PWR_EN = GPIO(H, 3);
struct Gpio __code XLP_OUT = GPIO(B, 4);
// uncrustify:on
void gpio_init(void) {
// PWRSW WDT 2 Enable 2
GCR9 = BIT(5);
// PWRSW WDT 2 Enable 1
GCR8 = BIT(4);
// Enable LPC reset on GPD2
GCR = 0x04;
// Disable UARTs
GCR6 = 0;
// Enable SMBus channel 4
GCR15 = BIT(4);
// Set GPD2 to 1.8V
GCR19 = BIT(0);
// Set GPF2 and GPF3 to 3.3V
GCR20 = 0;
// Set GPM6 power domain to VCC
GCR23 = BIT(0);
// Set GPIO data
// DDS_EC_PWM
GPDRA = BIT(3);
// XLP_OUT, PWR_SW#
GPDRB = BIT(4) | BIT(3);
GPDRC = 0;
// VGA_HEATSINK_SW
GPDRD = BIT(3);
// USB_PWR_EN#
GPDRE = BIT(3);
GPDRF = 0;
// H_PROCHOT_EC, BL_PWM_EN_EC
GPDRG = BIT(6) | BIT(0);
GPDRH = 0;
GPDRI = 0;
// PLVDD_RST_EC, KBC_MUTE#
GPDRJ = BIT(7) | BIT(1);
// Set GPIO control
// EC_PWM_LEDKB_P
GPCRA0 = GPIO_ALT;
// KBC_BEEP
GPCRA1 = GPIO_ALT;
// CPU_FAN_PWM
GPCRA2 = GPIO_ALT;
// DDS_EC_PWM
GPCRA3 = GPIO_IN;
// VGA_FAN_PWM
GPCRA4 = GPIO_ALT;
// EC_PWM_LEDKB_R
GPCRA5 = GPIO_ALT;
// EC_PWM_LEDKB_G
GPCRA6 = GPIO_ALT;
// EC_PWM_LEDKB_B
GPCRA7 = GPIO_ALT;
// AC_IN#
GPCRB0 = GPIO_IN | GPIO_UP;
// LID_SW#
GPCRB1 = GPIO_IN | GPIO_UP;
// EC_LAN_WAKEUP#
GPCRB2 = GPIO_IN;
// PWR_SW#
GPCRB3 = GPIO_IN;
// XLP_OUT
GPCRB4 = GPIO_OUT;
// GC6_FB_EN_PCH
GPCRB5 = GPIO_IN;
// SUSBC_EC#
GPCRB6 = GPIO_OUT | GPIO_UP;
// ALL_SYS_PWRGD
GPCRC0 = GPIO_IN;
// SMC_VGA_THERM
GPCRC1 = GPIO_ALT | GPIO_UP;
// SMD_VGA_THERM
GPCRC2 = GPIO_ALT | GPIO_UP;
// KB-SO16
GPCRC3 = GPIO_ALT | GPIO_UP;
// CNVI_DET#
GPCRC4 = GPIO_IN | GPIO_UP;
// KB-SO17
GPCRC5 = GPIO_ALT | GPIO_UP;
// PM_PWROK
GPCRC6 = GPIO_OUT;
// BKL_EN
GPCRC7 = GPIO_OUT | GPIO_UP;
// LED_PWR
GPCRD0 = GPIO_OUT | GPIO_UP;
// CCD_EN
GPCRD1 = GPIO_OUT;
// ESPI_RESET#
GPCRD2 = GPIO_ALT;
// VGA_HEATSINK_SW
GPCRD3 = GPIO_OUT;
// 7411_SINK_CTRL
GPCRD4 = GPIO_IN;
// PWR_BTN#
GPCRD5 = GPIO_OUT | GPIO_UP;
// CPU_FANSEN
GPCRD6 = GPIO_ALT;
// VGA_HEATSINK_FANSEN
GPCRD7 = GPIO_ALT;
// SMC_BAT
GPCRE0 = GPIO_ALT | GPIO_UP;
// AC_PRESENT
GPCRE1 = GPIO_OUT | GPIO_UP;
// RGBKB-DET#
GPCRE2 = GPIO_IN | GPIO_UP;
// USB_PWR_EN# (XXX: Active high, despite pin name)
GPCRE3 = GPIO_OUT;
// DD_ON
GPCRE4 = GPIO_OUT | GPIO_DOWN;
// EC_RSMRST#
GPCRE5 = GPIO_OUT;
// JACK_IN#_EC
GPCRE6 = GPIO_IN;
// SMD_BAT
GPCRE7 = GPIO_ALT | GPIO_UP;
// 80CLK
GPCRF0 = GPIO_IN;
// USB_CHARGE_EN
GPCRF1 = GPIO_OUT | GPIO_UP;
// 3IN1
GPCRF2 = GPIO_IN | GPIO_UP;
// PCH_DPWROK_EC
GPCRF3 = GPIO_OUT;
// TP_CLK
GPCRF4 = GPIO_ALT | GPIO_UP;
// TP_DATA
GPCRF5 = GPIO_ALT | GPIO_UP;
// EC_SMD_EN#
GPCRF6 = GPIO_IN;
// MUX_CTRL_BIOS
GPCRF7 = GPIO_OUT;
// BL_PWM_EN_EC
GPCRG0 = GPIO_OUT;
// EC_WLAN_EN (NC)
GPCRG1 = GPIO_IN;
// AUTO_LOAD_PWR
GPCRG2 = GPIO_IN;
// ALSPI_CE#
GPCRG3 = GPIO_ALT;
// ALSPI_MSI
GPCRG4 = GPIO_ALT;
// ALSPI_MSO
GPCRG5 = GPIO_ALT;
// H_PROCHOT_EC
GPCRG6 = GPIO_OUT | GPIO_UP;
// ALSPI_SCLK
GPCRG7 = GPIO_ALT;
// PM_SLP_S0_CS_N
GPCRH0 = GPIO_IN;
// EC_TEST_R_2
GPCRH1 = GPIO_IN;
// LED_ACIN
GPCRH2 = GPIO_OUT | GPIO_UP;
// WLAN_PWR_EN
GPCRH3 = GPIO_OUT;
// OVERT#_EC
GPCRH4 = GPIO_IN | GPIO_UP;
// LED_BAT_CHG
GPCRH5 = GPIO_OUT | GPIO_UP;
// DGPU_PWR_EN
GPCRH6 = GPIO_IN;
// SLP_SUS#
GPCRH7 = GPIO_IN;
// BAT_DET
GPCRI0 = GPIO_ALT;
// BAT_VOLT
GPCRI1 = GPIO_ALT;
// ME_WE
GPCRI2 = GPIO_OUT;
// THERM_VOLT_CPU
GPCRI3 = GPIO_ALT;
// TOTAL_CUR
GPCRI4 = GPIO_ALT;
// THERM_VOLT_GPU
GPCRI5 = GPIO_ALT;
// THERM_VOLT_HEATSINK
GPCRI6 = GPIO_ALT;
// MODEL_ID
GPCRI7 = GPIO_IN;
// LED_BAT_FULL
GPCRJ0 = GPIO_OUT | GPIO_UP;
// KBC_MUTE# / USB charger detection
GPCRJ1 = GPIO_IN;
// PCH_FAN
GPCRJ2 = GPIO_ALT;
// HEATSINK_FANSEN_R
GPCRJ3 = GPIO_IN;
// VA_EC_EN
GPCRJ4 = GPIO_OUT;
// VBATT_BOOST#
GPCRJ5 = GPIO_IN;
// EC_GPIO
GPCRJ6 = GPIO_IN;
// PLVDD_RST_EC
GPCRJ7 = GPIO_OUT;
// ESPI_IO0_EC
GPCRM0 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO1_EC
GPCRM1 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO2_EC
GPCRM2 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO3_EC
GPCRM3 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_CLK_EC
GPCRM4 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_CS_EC#
GPCRM5 = GPIO_ALT;
// ESPI_ALRT0#
GPCRM6 = GPIO_IN | GPIO_UP | GPIO_DOWN;
}

View File

@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-only
#ifndef _BOARD_GPIO_H
#define _BOARD_GPIO_H
#include <ec/gpio.h>
void gpio_init(void);
extern struct Gpio __code ACIN_N;
extern struct Gpio __code AC_PRESENT;
extern struct Gpio __code ALL_SYS_PWRGD;
extern struct Gpio __code BKL_EN;
#define HAVE_BT_EN 0
extern struct Gpio __code BUF_PLT_RST_N;
extern struct Gpio __code CCD_EN;
extern struct Gpio __code DD_ON;
extern struct Gpio __code DGPU_PWR_EN;
extern struct Gpio __code EC_EN;
extern struct Gpio __code EC_RSMRST_N;
extern struct Gpio __code GC6_FB_EN;
extern struct Gpio __code LAN_WAKEUP_N;
extern struct Gpio __code LED_ACIN;
#define HAVE_LED_AIRPLANE_N 0
extern struct Gpio __code LED_BAT_CHG;
extern struct Gpio __code LED_BAT_FULL;
extern struct Gpio __code LED_PWR;
extern struct Gpio __code LID_SW_N;
extern struct Gpio __code ME_WE;
extern struct Gpio __code PCH_DPWROK_EC;
#define HAVE_PCH_PWROK_EC 0
extern struct Gpio __code PM_PWROK;
extern struct Gpio __code PWR_BTN_N;
extern struct Gpio __code PWR_SW_N;
extern struct Gpio __code RGBKB_DET_N;
extern struct Gpio __code SLP_SUS_N;
#define HAVE_SUS_PWR_ACK 0
extern struct Gpio __code VA_EC_EN;
#define HAVE_WLAN_EN 0
extern struct Gpio __code WLAN_PWR_EN;
extern struct Gpio __code XLP_OUT;
#endif // _BOARD_GPIO_H

View File

@@ -1,17 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <arch/time.h>
#include <board/battery.h>
#include <board/board.h>
#include <board/dgpu.h>
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
extern uint8_t main_cycle;
#include <ec/ec.h>
void board_init(void) {
// Allow CPU to boot
@@ -20,66 +13,14 @@ void board_init(void) {
gpio_set(&BKL_EN, true);
// Enable camera
gpio_set(&CCD_EN, true);
// Enable wireless
gpio_set(&BT_EN, true);
gpio_set(&WLAN_EN, true);
gpio_set(&WLAN_PWR_EN, true);
// Enable USB port power?
gpio_set(&USB_PWR_EN_N, false);
// Assert SMI#, SCI#, and SWI#
gpio_set(&SCI_N, true);
gpio_set(&SMI_N, true);
gpio_set(&SWI_N, true);
// Enable POST codes
SPCTRL1 |= 0xC8;
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
// Read POST codes
while (P80H81HS & 1) {
uint8_t p80h = P80HD;
uint8_t p81h = P81HD;
P80H81HS |= 1;
DEBUG("POST %02X%02X\n", p81h, p80h);
}
ec_read_post_codes();
}

View File

@@ -1,13 +1,21 @@
# SPDX-License-Identifier: GPL-3.0-only
EC=it5570e
board-y += board.c
board-y += gpio.c
# Add keymap to src
KEYMAP?=default
SRC+=$(BOARD_DIR)/keymap/$(KEYMAP).c
EC=ite
CONFIG_EC_ITE_IT5570E=y
CONFIG_EC_FLASH_SIZE_128K = y
# Set discrete GPU I2C bus
CFLAGS+=-DI2C_DGPU=I2C_1
# Intel-based host
CONFIG_PLATFORM_INTEL = y
# Include keyboard
KEYBOARD=15in_102_nkey
# Set keyboard LED mechanism
CONFIG_HAVE_KBLED = y
KBLED=bonw14
# Set battery I2C bus
CFLAGS+=-DI2C_SMBUS=I2C_4
@@ -17,41 +25,38 @@ CFLAGS+=-DPS2_TOUCHPAD=PS2_3
# Set smart charger parameters
CFLAGS+=\
-DCHARGER_CHARGE_CURRENT=1536 \
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=10 \
-DCHARGER_CHARGE_CURRENT=3072 \
-DCHARGER_CHARGE_VOLTAGE=16800 \
-DCHARGER_INPUT_CURRENT=14000
# Set battery charging thresholds
CFLAGS+=\
-DBATTERY_START_THRESHOLD=0 \
-DBATTERY_END_THRESHOLD=100
# Set CPU power limits in watts
CFLAGS+=\
-DPOWER_LIMIT_AC=180 \
-DPOWER_LIMIT_DC=28
-DPOWER_LIMIT_DC=45
# Custom fan curve
CFLAGS+=-DBOARD_HEATUP=5
CFLAGS+=-DBOARD_COOLDOWN=20
CFLAGS+=-DBOARD_FAN_POINTS="\
# Enable dGPU support
CONFIG_HAVE_DGPU = y
CFLAGS += -DI2C_DGPU=I2C_1
# Fan configs
CFLAGS += -DFAN1_PWM=DCR2
CFLAGS += -DBOARD_FAN1_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100) \
FAN_POINT(80, 100), \
"
# Enable DGPU support
CFLAGS+=-DHAVE_DGPU=1
CFLAGS+=-DBOARD_DGPU_HEATUP=5
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
CFLAGS += -DFAN2_PWM=DCR4
CFLAGS += -DBOARD_FAN2_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100) \
FAN_POINT(80, 100), \
"
# Add system76 common code

View File

@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/gpio.h>
#include <common/debug.h>
#include <common/macro.h>
// uncrustify:off
struct Gpio __code ACIN_N = GPIO(B, 0);
struct Gpio __code AC_PRESENT = GPIO(E, 1);
struct Gpio __code AC_V1_EC = GPIO(J, 7);
@@ -38,12 +39,18 @@ struct Gpio __code VA_EC_EN = GPIO(J, 4); // renamed to SLP_SUS#
struct Gpio __code WLAN_EN = GPIO(G, 1);
struct Gpio __code WLAN_PWR_EN = GPIO(A, 3);
struct Gpio __code XLP_OUT = GPIO(B, 4); // renamed to EN_3V
// uncrustify:on
void gpio_init(void) {
// PWRSW WDT 2 Enable 2
GCR9 = BIT(5);
// PWRSW WDT 2 Enable 1
GCR8 = BIT(4);
void gpio_init() {
// Enable LPC reset on GPD2
GCR = 0x04;
// Enable SMBus channel 4
GCR15 = (1 << 4);
GCR15 = BIT(4);
// Set GPF2 and GPF3 to 3.3V
GCR20 = 0;
@@ -90,8 +97,6 @@ void gpio_init() {
GPCRB5 = GPIO_OUT | GPIO_UP;
// EC_EN
GPCRB6 = GPIO_OUT | GPIO_UP;
// NO PIN
GPCRB7 = GPIO_IN;
// ALL_SYS_PWRGD
GPCRC0 = GPIO_IN;
// KBC_SMBus_CLK1
@@ -99,11 +104,11 @@ void gpio_init() {
// KBC_SMBus_DAT1
GPCRC2 = GPIO_ALT;
// KB-SO16
GPCRC3 = GPIO_IN;
GPCRC3 = GPIO_ALT | GPIO_UP;
// CNVI_DET#
GPCRC4 = GPIO_IN | GPIO_UP;
// KB-SO17
GPCRC5 = GPIO_IN;
GPCRC5 = GPIO_ALT | GPIO_UP;
// PM_PWROK
GPCRC6 = GPIO_OUT;
// LED_ACIN
@@ -235,40 +240,3 @@ void gpio_init() {
// SERIRQ
GPCRM6 = GPIO_ALT;
}
#if GPIO_DEBUG
void gpio_debug_bank(
char * bank,
uint8_t data,
uint8_t mirror,
uint8_t pot,
volatile uint8_t * control
) {
for(char i = 0; i < 8; i++) {
DEBUG(
"%s%d:\n\tdata %d\n\tmirror %d\n\tpot %d\n\tcontrol %02X\n",
bank,
i,
(data >> i) & 1,
(mirror >> i) & 1,
(pot >> i) & 1,
*(control + i)
);
}
}
void gpio_debug(void) {
#define bank(BANK) gpio_debug_bank(#BANK, GPDR ## BANK, GPDMR ## BANK, GPOT ## BANK, &GPCR ## BANK ## 0)
bank(A);
bank(B);
bank(C);
bank(D);
bank(E);
bank(F);
bank(G);
bank(H);
bank(I);
bank(J);
#undef bank
}
#endif

View File

@@ -5,14 +5,7 @@
#include <ec/gpio.h>
#define GPIO_ALT 0x00
#define GPIO_IN 0x80
#define GPIO_OUT 0x40
#define GPIO_UP 0x04
#define GPIO_DOWN 0x02
void gpio_init(void);
void gpio_debug(void);
extern struct Gpio __code ACIN_N;
extern struct Gpio __code AC_PRESENT;

View File

@@ -0,0 +1,81 @@
# SPDX-License-Identifier: GPL-3.0-only
board-y += ../bonw15/board.c
board-y += ../bonw15/gpio.c
# FIXME: Handle this better
CFLAGS += -I$(BOARD_DIR)/../bonw15/include
EC = ite
CONFIG_EC_ITE_IT5570E = y
CONFIG_EC_FLASH_SIZE_256K = y
# Intel-based host
CONFIG_PLATFORM_INTEL = y
CONFIG_BUS_ESPI = y
# Enable firmware security
CONFIG_SECURITY = y
# Include keyboard
KEYBOARD = 15in_102
# Set keyboard LED mechanism
CONFIG_HAVE_KBLED = y
KBLED = bonw14
# Set battery I2C bus
CFLAGS += -DI2C_SMBUS=I2C_4
# Set touchpad PS2 bus
CFLAGS += -DPS2_TOUCHPAD=PS2_3
# Set smart charger parameters
# XXX: PRS1 and PRS2 are in parallel for adapter Rsense?
CHARGER = oz26786
CFLAGS += \
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=5 \
-DCHARGER_CHARGE_CURRENT=3072 \
-DCHARGER_CHARGE_VOLTAGE=17400 \
-DCHARGER_INPUT_CURRENT=16920
# Set USB-PD parameters
CONFIG_HAVE_USBPD = y
CONFIG_USBPD_TPS65987 = y
CFLAGS += -DI2C_USBPD=I2C_1
# Set CPU power limits in watts
CFLAGS += \
-DPOWER_LIMIT_AC=330 \
-DPOWER_LIMIT_DC=55
# Enable dGPU support
CONFIG_HAVE_DGPU = y
CFLAGS += -DI2C_DGPU=I2C_1
# Fan configs
CFLAGS += -DFAN1_PWM=DCR2
CFLAGS += -DBOARD_FAN1_HEATUP=5
CFLAGS += -DBOARD_FAN1_COOLDOWN=20
CFLAGS += -DBOARD_FAN1_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100), \
"
CFLAGS += -DFAN2_PWM=DCR4
CFLAGS += -DBOARD_FAN2_HEATUP=5
CFLAGS += -DBOARD_FAN2_COOLDOWN=20
CFLAGS += -DBOARD_FAN2_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100), \
"
# Add system76 common code
include src/board/system76/common/common.mk

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/battery.h>
#include <board/board.h>
#include <board/espi.h>
#include <board/gpio.h>
#include <ec/ec.h>
void board_init(void) {
espi_init();
// Make sure charger is in off state, also enables PSYS
battery_charger_disable();
// Allow backlight to be turned on
gpio_set(&BKL_EN, true);
// Enable camera
gpio_set(&CCD_EN, true);
}
void board_event(void) {
espi_event();
ec_read_post_codes();
}

View File

@@ -0,0 +1,79 @@
# SPDX-License-Identifier: GPL-3.0-only
board-y += board.c
board-y += gpio.c
EC=ite
CONFIG_EC_ITE_IT5570E=y
CONFIG_EC_FLASH_SIZE_128K = y
# Intel-based host
CONFIG_PLATFORM_INTEL = y
CONFIG_BUS_ESPI = y
# Enable firmware security
CONFIG_SECURITY=y
# Include keyboard
KEYBOARD=15in_102
# Set keyboard LED mechanism
CONFIG_HAVE_KBLED = y
KBLED=bonw14
# Set battery I2C bus
CFLAGS+=-DI2C_SMBUS=I2C_4
# Set touchpad PS2 bus
CFLAGS+=-DPS2_TOUCHPAD=PS2_3
# Set smart charger parameters
# XXX: PRS1 and PRS2 are in parallel for adapter Rsense?
CHARGER=oz26786
CFLAGS+=\
-DCHARGER_ADAPTER_RSENSE=5 \
-DCHARGER_BATTERY_RSENSE=5 \
-DCHARGER_CHARGE_CURRENT=3072 \
-DCHARGER_CHARGE_VOLTAGE=17400 \
-DCHARGER_INPUT_CURRENT=16920
# Set USB-PD parameters
CONFIG_HAVE_USBPD = y
CONFIG_USBPD_TPS65987 = y
CFLAGS += -DI2C_USBPD=I2C_1
# Set CPU power limits in watts
CFLAGS+=\
-DPOWER_LIMIT_AC=330 \
-DPOWER_LIMIT_DC=55
# Enable dGPU support
CONFIG_HAVE_DGPU = y
CFLAGS += -DI2C_DGPU=I2C_1
# Fan configs
CFLAGS += -DFAN1_PWM=DCR2
CFLAGS += -DBOARD_FAN1_HEATUP=5
CFLAGS += -DBOARD_FAN1_COOLDOWN=20
CFLAGS += -DBOARD_FAN1_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100), \
"
CFLAGS += -DFAN2_PWM=DCR4
CFLAGS += -DBOARD_FAN2_HEATUP=5
CFLAGS += -DBOARD_FAN2_COOLDOWN=20
CFLAGS += -DBOARD_FAN2_POINTS="\
FAN_POINT(60, 40), \
FAN_POINT(65, 60), \
FAN_POINT(70, 75), \
FAN_POINT(75, 90), \
FAN_POINT(80, 100), \
"
# Add system76 common code
include src/board/system76/common/common.mk

View File

@@ -0,0 +1,275 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/gpio.h>
#include <common/macro.h>
// uncrustify:off
struct Gpio __code ACIN_N = GPIO(B, 0);
struct Gpio __code AC_PRESENT = GPIO(E, 1);
struct Gpio __code ALL_SYS_PWRGD = GPIO(C, 0);
struct Gpio __code BKL_EN = GPIO(C, 7);
struct Gpio __code BUF_PLT_RST_N = GPIO(D, 2); // renamed to ESPI_RESET_N
struct Gpio __code CCD_EN = GPIO(D, 1);
struct Gpio __code DD_ON = GPIO(E, 4);
struct Gpio __code DGPU_PWR_EN = GPIO(J, 2);
struct Gpio __code EC_EN = GPIO(B, 6); // renamed to SUSBC_EC#
struct Gpio __code EC_RSMRST_N = GPIO(E, 5);
struct Gpio __code GC6_FB_EN = GPIO(J, 3);
struct Gpio __code JACK_IN_N = GPIO(E, 6);
struct Gpio __code LAN_WAKEUP_N = GPIO(B, 2);
struct Gpio __code LED_ACIN = GPIO(H, 2);
struct Gpio __code LED_BAT_CHG = GPIO(H, 5);
struct Gpio __code LED_BAT_FULL = GPIO(J, 0);
struct Gpio __code LED_PWR = GPIO(D, 0);
struct Gpio __code LID_SW_N = GPIO(B, 1);
struct Gpio __code ME_WE = GPIO(I, 2);
struct Gpio __code PCH_DPWROK_EC = GPIO(F, 3);
struct Gpio __code PCH_PWROK_EC = GPIO(I, 5); // renamed to SYS_PWROK_EC
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
struct Gpio __code PWR_SW_N = GPIO(B, 3);
struct Gpio __code RGBKB_DET_N = GPIO(E, 2);
struct Gpio __code SINK_CTRL = GPIO(H, 0);
struct Gpio __code SLP_SUS_N = GPIO(H, 7);
struct Gpio __code VA_EC_EN = GPIO(J, 4);
struct Gpio __code WLAN_EN = GPIO(G, 1);
struct Gpio __code WLAN_PWR_EN = GPIO(B, 5);
struct Gpio __code XLP_OUT = GPIO(B, 4);
// uncrustify:on
void gpio_init(void) {
// PWRSW WDT 2 Enable 2
GCR9 = BIT(5);
// PWRSW WDT 2 Enable 1
GCR8 = BIT(4);
// Enable LPC reset on GPD2
GCR = 0x04;
// Disable UARTs
GCR6 = 0;
// Enable SMBus channel 4
GCR15 = BIT(4);
// Set GPD2 to 1.8V
GCR19 = BIT(0);
// Set GPF2 and GPF3 to 3.3V
GCR20 = 0;
//TODO: what do these do?
GCR1 = 0;
GCR2 = 0;
GCR10 = 0x02;
GCR21 = 0;
GCR22 = 0x80;
GCR23 = 0x01;
// Set GPIO data
GPDRA = 0;
// XLP_OUT, PWR_SW#
GPDRB = BIT(4) | BIT(3);
// PLVDD_RST_EC
GPDRC = BIT(6);
// BL_PWM_EN_EC
GPDRD = BIT(3);
// USB_PWR_EN# (inverted)
GPDRE = BIT(3);
// PCH_DPWROK_EC
GPDRF = BIT(3);
// H_PROCHOT#_EC
GPDRG = BIT(6);
// EC_AMP_EN
GPDRH = BIT(6);
GPDRI = 0;
GPDRJ = 0;
GPOTA = 0;
GPOTB = 0;
GPOTD = 0;
GPOTE = 0;
GPOTF = 0;
GPOTH = 0;
GPOTJ = 0;
// Set GPIO control
// EC_PWM_LEDKB_P
GPCRA0 = GPIO_ALT;
// KBC_BEEP
GPCRA1 = GPIO_ALT;
// CPU_FAN
GPCRA2 = GPIO_ALT;
// DDS_EC_PWM
GPCRA3 = GPIO_IN;
// VGA_FAN
GPCRA4 = GPIO_ALT;
// EC_PWM_LEDKB_R
GPCRA5 = GPIO_ALT;
// EC_PWM_LEDKB_G
GPCRA6 = GPIO_ALT;
// EC_PWM_LEDKB_B
GPCRA7 = GPIO_ALT;
// AC_IN#
GPCRB0 = GPIO_IN | GPIO_UP;
// LID_SW#
GPCRB1 = GPIO_IN | GPIO_UP;
// EC_LAN_WAKEUP#
GPCRB2 = GPIO_IN | GPIO_UP;
// PWR_SW#
GPCRB3 = GPIO_IN;
// XLP_OUT
GPCRB4 = GPIO_OUT;
// WLAN_PWR_EN
GPCRB5 = GPIO_OUT;
// SUSBC_EC#
GPCRB6 = GPIO_OUT | GPIO_UP;
// ALL_SYS_PWRGD
GPCRC0 = GPIO_IN;
// SMC_VGA_THERM
GPCRC1 = GPIO_ALT | GPIO_UP;
// SMD_VGA_THERM
GPCRC2 = GPIO_ALT | GPIO_UP;
// KB-SO16
GPCRC3 = GPIO_ALT | GPIO_UP;
// CNVI_DET#
GPCRC4 = GPIO_IN | GPIO_UP;
// KB-SO17
GPCRC5 = GPIO_ALT | GPIO_UP;
// PLVDD_RST_EC
GPCRC6 = GPIO_OUT;
// BKL_EN
GPCRC7 = GPIO_OUT | GPIO_UP;
// LED_PWR
GPCRD0 = GPIO_OUT;
// CCD_EN
GPCRD1 = GPIO_OUT;
// ESPI_RESET_N
GPCRD2 = GPIO_ALT;
// BL_PWM_EN_EC
GPCRD3 = GPIO_OUT;
// MUX_CTRL_BIOS
GPCRD4 = GPIO_OUT;
// PWR_BTN#
GPCRD5 = GPIO_OUT | GPIO_UP;
// CPU_FANSEN
GPCRD6 = GPIO_ALT;
// VGA_FANSEN
GPCRD7 = GPIO_ALT;
// SMC_BAT
GPCRE0 = GPIO_ALT | GPIO_UP;
// AC_PRESENT
GPCRE1 = GPIO_OUT | GPIO_UP;
// RGBKB_DET#
GPCRE2 = GPIO_IN | GPIO_UP;
// USB_PWR_EN#
GPCRE3 = GPIO_OUT;
// DD_ON
GPCRE4 = GPIO_OUT | GPIO_DOWN;
// EC_RSMRST#
GPCRE5 = GPIO_OUT;
// JACK_IN#_EC
GPCRE6 = GPIO_IN;
// SMD_BAT
GPCRE7 = GPIO_ALT | GPIO_UP;
// 80CLK
GPCRF0 = GPIO_IN;
// USB_CHARGE_EN
GPCRF1 = GPIO_OUT | GPIO_UP;
// 3IN1
GPCRF2 = GPIO_IN | GPIO_UP;
// PCH_DPWROK_EC
GPCRF3 = GPIO_OUT;
// TP_CLK
GPCRF4 = GPIO_ALT | GPIO_UP;
// TP_DATA
GPCRF5 = GPIO_ALT | GPIO_UP;
// H_PECI
GPCRF6 = GPIO_ALT;
// CPU_C10_GATE#
GPCRF7 = GPIO_IN;
// dGPU_OVERT_EC
GPCRG0 = GPIO_IN;
// WLAN_EN
GPCRG1 = GPIO_OUT;
// 100k pull up to VDD3
GPCRG2 = GPIO_IN;
// ALSPI_CE#
GPCRG3 = GPIO_ALT;
// ALSPI_MSI
GPCRG4 = GPIO_ALT;
// ALSPI_MSO
GPCRG5 = GPIO_ALT;
// H_PROCHOT#_EC
GPCRG6 = GPIO_OUT | GPIO_UP;
// ALSPI_SCLK
GPCRG7 = GPIO_ALT;
// SINK_CTRL
GPCRH0 = GPIO_IN;
// SUSC#_PCH
GPCRH1 = GPIO_IN;
// LED_ACIN
GPCRH2 = GPIO_OUT | GPIO_UP;
// TBT_I2C_IRQ2Z
GPCRH3 = GPIO_IN;
// BOARD_ID0
GPCRH4 = GPIO_IN;
// LED_BAT_CHG
GPCRH5 = GPIO_OUT | GPIO_UP;
// EC_AMP_EN
GPCRH6 = GPIO_OUT;
// SLP_SUS#
GPCRH7 = GPIO_IN;
// BAT_DET
GPCRI0 = GPIO_ALT;
// BAT_VOLT
GPCRI1 = GPIO_ALT;
// ME_WE
GPCRI2 = GPIO_OUT;
// THERM_VOLT_CPU
GPCRI3 = GPIO_ALT;
// TOTAL_CUR
GPCRI4 = GPIO_ALT;
// SYS_PWROK_EC
GPCRI5 = GPIO_OUT;
// THERM_VOLT_CPU
GPCRI6 = GPIO_ALT;
// BOARD_ID1
GPCRI7 = GPIO_IN;
// LED_BAT_FULL
GPCRJ0 = GPIO_OUT | GPIO_UP;
// KBC_MUTE#
GPCRJ1 = GPIO_IN;
// DGPU_PWR_EN
GPCRJ2 = GPIO_IN;
// GC6_FB_EN_PCH
GPCRJ3 = GPIO_IN;
// VA_EC_EN
GPCRJ4 = GPIO_OUT;
// VBATT_BOOST#
GPCRJ5 = GPIO_IN;
// EC_GPIO
GPCRJ6 = GPIO_IN | GPIO_DOWN;
// PERKB_DET#
GPCRJ7 = GPIO_IN | GPIO_UP;
// ESPI_IO0_EC
GPCRM0 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO1_EC
GPCRM1 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO2_EC
GPCRM2 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_IO3_EC
GPCRM3 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_CLK_EC
GPCRM4 = GPIO_ALT | GPIO_UP | GPIO_DOWN;
// ESPI_CS_EC#
GPCRM5 = GPIO_ALT;
// ESPI_ALERT0#
GPCRM6 = GPIO_IN | GPIO_UP | GPIO_DOWN;
}

View File

@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-3.0-only
#ifndef _BOARD_GPIO_H
#define _BOARD_GPIO_H
#include <ec/gpio.h>
void gpio_init(void);
extern struct Gpio __code ACIN_N;
extern struct Gpio __code AC_PRESENT;
extern struct Gpio __code ALL_SYS_PWRGD;
extern struct Gpio __code BKL_EN;
#define HAVE_BT_EN 0
extern struct Gpio __code BUF_PLT_RST_N;
extern struct Gpio __code CCD_EN;
extern struct Gpio __code CPU_C10_GATE_N;
extern struct Gpio __code DD_ON;
extern struct Gpio __code DGPU_PWR_EN;
extern struct Gpio __code EC_EN;
extern struct Gpio __code EC_RSMRST_N;
extern struct Gpio __code GC6_FB_EN;
extern struct Gpio __code JACK_IN_N;
extern struct Gpio __code LAN_WAKEUP_N;
extern struct Gpio __code LED_ACIN;
#define HAVE_LED_AIRPLANE_N 0
extern struct Gpio __code LED_BAT_CHG;
extern struct Gpio __code LED_BAT_FULL;
extern struct Gpio __code LED_PWR;
extern struct Gpio __code LID_SW_N;
extern struct Gpio __code ME_WE;
extern struct Gpio __code PCH_DPWROK_EC;
extern struct Gpio __code PCH_PWROK_EC;
#define HAVE_PM_PWROK 0
extern struct Gpio __code PWR_BTN_N;
extern struct Gpio __code PWR_SW_N;
extern struct Gpio __code RGBKB_DET_N;
extern struct Gpio __code SINK_CTRL;
extern struct Gpio __code SLP_SUS_N;
#define HAVE_SUS_PWR_ACK 0
extern struct Gpio __code VA_EC_EN;
extern struct Gpio __code WLAN_EN;
extern struct Gpio __code WLAN_PWR_EN;
extern struct Gpio __code XLP_OUT;
#endif // _BOARD_GPIO_H

View File

@@ -3,12 +3,17 @@
#include <board/acpi.h>
#include <board/battery.h>
#include <board/dgpu.h>
#include <board/fan.h>
#include <board/gpio.h>
#include <board/kbled.h>
#include <board/lid.h>
#include <board/peci.h>
#include <board/pwm.h>
#include <common/debug.h>
#include <ec/pwm.h>
#include <common/macro.h>
#if CONFIG_PLATFORM_INTEL
#include <board/peci.h>
#endif
#ifndef HAVE_LED_AIRPLANE_N
#define HAVE_LED_AIRPLANE_N 1
@@ -24,31 +29,48 @@ static uint8_t fbuf[4] = { 0, 0, 0, 0 };
void fcommand(void) {
switch (fcmd) {
// Keyboard backlight
case 0xCA:
switch (fdat) {
// Set white LED brightness
case 0x00:
kbled_set(fbuf[0]);
break;
// Get white LED brightness
case 0x01:
fbuf[0] = kbled_get();
break;
// Set LED color
case 0x03:
kbled_set_color(
((uint32_t)fbuf[0]) |
((uint32_t)fbuf[1] << 16) |
((uint32_t)fbuf[2] << 8)
);
break;
// Set LED brightness
case 0x06:
kbled_set(fbuf[0]);
break;
}
#if CONFIG_HAVE_KBLED
// Keyboard backlight
case 0xCA:
switch (fdat) {
// Set brightness
case 0:
kbled_set(fbuf[0]);
break;
// Get brightness
case 1:
fbuf[0] = kbled_get();
break;
// Get type
case 2:
fbuf[0] = kbled_kind;
break;
// Set color
case 3:
kbled_set_color(
((uint32_t)fbuf[0]) |
((uint32_t)fbuf[1] << 16) |
((uint32_t)fbuf[2] << 8)
);
break;
// Get color
case 4:
// uncrustify:off
{
uint32_t color = kbled_get_color();
fbuf[0] = color & 0xFF;
fbuf[1] = (color >> 16) & 0xFF;
fbuf[2] = (color >> 8) & 0xFF;
}
// uncrustify:on
break;
// DUPLICATE: Set brightness
case 6:
kbled_set(fbuf[0]);
break;
}
break;
#endif // CONFIG_HAVE_KBLED
}
}
@@ -65,6 +87,7 @@ void acpi_reset(void) {
#endif
}
// uncrustify:off
uint8_t acpi_read(uint8_t addr) {
uint8_t data = 0;
@@ -86,47 +109,53 @@ uint8_t acpi_read(uint8_t addr) {
case 0x03:
if (gpio_get(&LID_SW_N)) {
// Lid is open
data |= 1 << 0;
data |= BIT(0);
}
if (lid_wake) {
data |= 1 << 2;
data |= BIT(2);
}
break;
ACPI_8(0x07, peci_temp >> 6);
#if CONFIG_PLATFORM_INTEL
ACPI_8(0x07, peci_temp);
#endif
// Handle AC adapter and battery present
case 0x10:
if (!gpio_get(&ACIN_N)) {
// AC adapter connected
data |= 1 << 0;
data |= BIT(0);
}
if (battery_status & BATTERY_INITIALIZED) {
if (battery_info.status & BATTERY_INITIALIZED) {
// BAT0 connected
data |= 1 << 2;
data |= BIT(2);
}
break;
ACPI_16(0x16, battery_design_capacity);
ACPI_16(0x1A, battery_full_capacity);
ACPI_16(0x22, battery_design_voltage);
ACPI_16(0x16, battery_info.design_capacity);
ACPI_16(0x1A, battery_info.full_capacity);
ACPI_16(0x22, battery_info.design_voltage);
case 0x26:
// If AC adapter connected
if (!gpio_get(&ACIN_N)) {
// And battery is not fully charged
if (battery_current != 0) {
if (battery_info.current != 0) {
// Battery is charging
data |= 1 << 1;
data |= BIT(1);
}
}
break;
ACPI_16(0x2A, battery_current);
ACPI_16(0x2E, battery_remaining_capacity);
ACPI_16(0x32, battery_voltage);
ACPI_16(0x2A, battery_info.current);
ACPI_16(0x2E, battery_info.remaining_capacity);
ACPI_16(0x32, battery_info.voltage);
ACPI_8(0x68, acpi_ecos);
ACPI_16(0x42, battery_info.cycle_count);
case 0x68:
data = acpi_ecos;
break;
case 0xBC:
data = battery_get_start_threshold();
@@ -138,86 +167,87 @@ uint8_t acpi_read(uint8_t addr) {
ACPI_8(0xCC, sci_extra);
ACPI_8(0xCE, DCR2);
ACPI_8(0xD0, F1TLRR);
ACPI_8(0xD1, F1TMRR);
#if HAVE_DGPU
ACPI_8(0xCE, fan1_pwm_actual);
ACPI_16(0xD0, fan1_rpm);
#if CONFIG_HAVE_DGPU
ACPI_8(0xCD, dgpu_temp);
ACPI_8(0xCF, DCR4);
ACPI_8(0xD2, F2TLRR);
ACPI_8(0xD3, F2TMRR);
#endif // HAVE_DGPU
#endif // CONFIG_HAVE_DGPU
#ifdef FAN2_PWM
ACPI_8(0xCF, fan2_pwm_actual);
ACPI_16(0xD2, fan2_rpm);
#endif // FAN2_PWM
#if HAVE_LED_AIRPLANE_N
// Airplane mode LED
case 0xD9:
if (!gpio_get(&LED_AIRPLANE_N)) {
data |= (1 << 6);
data |= BIT(6);
}
break;
#endif // HAVE_LED_AIRPLANE_N
// Set size of flash (from old firmware)
ACPI_8 (0xE5, 0x80);
ACPI_8(0xE5, 0x80);
ACPI_8 (0xF8, fcmd);
ACPI_8 (0xF9, fdat);
ACPI_8 (0xFA, fbuf[0]);
ACPI_8 (0xFB, fbuf[1]);
ACPI_8 (0xFC, fbuf[2]);
ACPI_8 (0xFD, fbuf[3]);
ACPI_8(0xF8, fcmd);
ACPI_8(0xF9, fdat);
ACPI_8(0xFA, fbuf[0]);
ACPI_8(0xFB, fbuf[1]);
ACPI_8(0xFC, fbuf[2]);
ACPI_8(0xFD, fbuf[3]);
}
DEBUG("acpi_read %02X = %02X\n", addr, data);
TRACE("acpi_read %02X = %02X\n", addr, data);
return data;
}
// uncrustify:on
void acpi_write(uint8_t addr, uint8_t data) {
DEBUG("acpi_write %02X = %02X\n", addr, data);
TRACE("acpi_write %02X = %02X\n", addr, data);
switch (addr) {
// Lid state and other flags
case 0x03:
lid_wake = (bool)(data & (1 << 2));
break;
// Lid state and other flags
case 0x03:
lid_wake = (bool)(data & BIT(2));
break;
case 0x68:
acpi_ecos = (enum EcOs)data;
break;
case 0x68:
acpi_ecos = (enum EcOs)data;
break;
case 0xBC:
battery_set_start_threshold(data);
break;
case 0xBC:
battery_set_start_threshold(data);
break;
case 0xBD:
battery_set_end_threshold(data);
break;
case 0xBD:
battery_set_end_threshold(data);
break;
#if HAVE_LED_AIRPLANE_N
// Airplane mode LED
case 0xD9:
gpio_set(&LED_AIRPLANE_N, !(bool)(data & (1 << 6)));
break;
// Airplane mode LED
case 0xD9:
gpio_set(&LED_AIRPLANE_N, !(bool)(data & BIT(6)));
break;
#endif
case 0xF8:
fcmd = data;
fcommand();
break;
case 0xF9:
fdat = data;
break;
case 0xFA:
fbuf[0] = data;
break;
case 0xFB:
fbuf[1] = data;
break;
case 0xFC:
fbuf[2] = data;
break;
case 0xFD:
fbuf[3] = data;
break;
case 0xF8:
fcmd = data;
fcommand();
break;
case 0xF9:
fdat = data;
break;
case 0xFA:
fbuf[0] = data;
break;
case 0xFB:
fbuf[1] = data;
break;
case 0xFC:
fbuf[2] = data;
break;
case 0xFD:
fbuf[3] = data;
break;
}
}

View File

@@ -1,25 +1,17 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/battery.h>
#include <board/gpio.h>
#include <board/smbus.h>
#include <common/debug.h>
#define BATTERY_ADDRESS 0x0B
#define CHARGER_ADDRESS 0x09
struct battery_info battery_info = { 0 };
// ChargeOption0 flags
// Low Power Mode Enable
#define SBC_EN_LWPWR ((uint16_t)(1 << 15))
// Watchdog Timer Adjust
#define SBC_WDTMR_ADJ_175S ((uint16_t)(0b11 << 13))
// Switching Frequency
#define SBC_PWM_FREQ_800KHZ ((uint16_t)(0b01 << 8))
// IDCHG Amplifier Gain
#define SBC_IDCHC_GAIN ((uint16_t)(1 << 3))
uint16_t battery_charger_input_current = CHARGER_INPUT_CURRENT;
// Default values to disable battery charging thresholds
#define BATTERY_START_DEFAULT 0
#define BATTERY_END_DEFAULT 100
#define BATTERY_START_DEFAULT 0
#define BATTERY_END_DEFAULT 100
// Represents a battery percentage level, below which charging will begin.
// Valid values are [0, 100]
@@ -59,94 +51,25 @@ bool battery_set_end_threshold(uint8_t value) {
return true;
}
// XXX: Assumption: ac_last is initialized high.
static bool charger_enabled = false;
int battery_charger_disable(void) {
int res = 0;
if (!charger_enabled) return 0;
// Set charge option 0 with 175s watchdog
res = smbus_write(
CHARGER_ADDRESS,
0x12,
SBC_EN_LWPWR |
SBC_WDTMR_ADJ_175S |
SBC_PWM_FREQ_800KHZ |
SBC_IDCHC_GAIN
);
// Disable charge current
res = smbus_write(CHARGER_ADDRESS, 0x14, 0);
if (res < 0) return res;
// Disable charge voltage
res = smbus_write(CHARGER_ADDRESS, 0x15, 0);
if (res < 0) return res;
// Disable input current
res = smbus_write(CHARGER_ADDRESS, 0x3F, 0);
if (res < 0) return res;
DEBUG("Charger disabled\n");
charger_enabled = false;
return 0;
}
int battery_charger_enable(void) {
int res = 0;
if (charger_enabled) return 0;
res = battery_charger_disable();
if (res < 0) return res;
// Set charge current in mA
res = smbus_write(CHARGER_ADDRESS, 0x14, CHARGER_CHARGE_CURRENT);
if (res < 0) return res;
// Set charge voltage in mV
res = smbus_write(CHARGER_ADDRESS, 0x15, CHARGER_CHARGE_VOLTAGE);
if (res < 0) return res;
// Set input current in mA
res = smbus_write(CHARGER_ADDRESS, 0x3F, CHARGER_INPUT_CURRENT);
if (res < 0) return res;
// Set charge option 0 with watchdog disabled
res = smbus_write(
CHARGER_ADDRESS,
0x12,
SBC_EN_LWPWR |
SBC_PWM_FREQ_800KHZ |
SBC_IDCHC_GAIN
);
DEBUG("Charger enabled\n");
charger_enabled = true;
return 0;
}
/**
* Configure the charger based on charging threshold values.
*/
int battery_charger_configure(void) {
int16_t battery_charger_configure(void) {
static bool should_charge = true;
bool ac_present = !gpio_get(&ACIN_N);
if (battery_get_end_threshold() == BATTERY_END_DEFAULT) {
// Stop threshold not configured: Always charge on AC.
should_charge = true;
}
else if (battery_charge >= battery_get_end_threshold()) {
if (!ac_present || (battery_info.status & BATTERY_FULLY_CHARGED)) {
// Always disable charger if:
// - AC is not plugged in, or
// - Battery is fully charged
should_charge = false;
} else if (battery_info.charge > battery_get_end_threshold()) {
// Stop threshold configured: Stop charging at threshold.
should_charge = false;
}
else if (battery_get_start_threshold() == BATTERY_START_DEFAULT) {
} else if (battery_get_start_threshold() == BATTERY_START_DEFAULT) {
// Start threshold not configured: Always charge up to stop threshold.
should_charge = true;
}
else if (battery_charge <= battery_get_start_threshold()) {
} else if (battery_info.charge < battery_get_start_threshold()) {
// Start threshold configured: Start charging at threshold.
should_charge = true;
}
@@ -156,74 +79,33 @@ int battery_charger_configure(void) {
return battery_charger_disable();
}
uint16_t battery_temp = 0;
uint16_t battery_voltage = 0;
uint16_t battery_current = 0;
uint16_t battery_charge = 0;
uint16_t battery_remaining_capacity = 0;
uint16_t battery_full_capacity = 0;
uint16_t battery_status = 0;
uint16_t battery_design_capacity = 0;
uint16_t battery_design_voltage = 0;
void battery_event(void) {
int res = 0;
int16_t res = 0;
#define command(N, V) { \
#define command(N, V) \
{ \
res = smbus_read(BATTERY_ADDRESS, V, &N); \
if (res < 0) { \
N = 0; \
} \
}
command(battery_temp, 0x08);
command(battery_voltage, 0x09);
command(battery_current, 0x0A);
command(battery_charge, 0x0D);
command(battery_remaining_capacity, 0x0F);
command(battery_full_capacity, 0x10);
command(battery_status, 0x16);
command(battery_design_capacity, 0x18);
command(battery_design_voltage, 0x19);
command(battery_info.temp, 0x08);
command(battery_info.voltage, 0x09);
command(battery_info.current, 0x0A);
command(battery_info.charge, 0x0D);
command(battery_info.remaining_capacity, 0x0F);
command(battery_info.full_capacity, 0x10);
command(battery_info.status, 0x16);
command(battery_info.cycle_count, 0x17);
command(battery_info.design_capacity, 0x18);
command(battery_info.design_voltage, 0x19);
#undef command
}
#undef command
void battery_debug(void) {
uint16_t data = 0;
int res = 0;
TRACE("BAT %d mV %d mA\n", battery_info.voltage, battery_info.current);
#define command(N, A, V) { \
DEBUG(" " #N ": "); \
res = smbus_read(A, V, &data); \
if (res < 0) { \
DEBUG("ERROR %04X\n", -res); \
} else { \
DEBUG("%04X\n", data); \
} \
}
DEBUG("Battery:\n");
command(Temperature, BATTERY_ADDRESS, 0x08);
command(Voltage, BATTERY_ADDRESS, 0x09);
command(Current, BATTERY_ADDRESS, 0x0A);
command(Charge, BATTERY_ADDRESS, 0x0D);
command(Status, BATTERY_ADDRESS, 0x16);
DEBUG("Charger:\n");
command(ChargeOption0, CHARGER_ADDRESS, 0x12);
command(ChargeOption1, CHARGER_ADDRESS, 0x3B);
command(ChargeOption2, CHARGER_ADDRESS, 0x38);
command(ChargeOption3, CHARGER_ADDRESS, 0x37);
command(ChargeCurrent, CHARGER_ADDRESS, 0x14);
command(ChargeVoltage, CHARGER_ADDRESS, 0x15);
command(DishargeCurrent, CHARGER_ADDRESS, 0x39);
command(InputCurrent, CHARGER_ADDRESS, 0x3F);
command(ProchotOption0, CHARGER_ADDRESS, 0x3C);
command(ProchotOption1, CHARGER_ADDRESS, 0x3D);
command(ProchotStatus, CHARGER_ADDRESS, 0x3A);
#undef command
battery_charger_event();
}
void battery_reset(void) {

View File

@@ -0,0 +1,215 @@
// SPDX-License-Identifier: GPL-3.0-only
//
// TI BQ24780S Smart Charger
// https://www.ti.com/lit/ds/symlink/bq24780s.pdf
#include <board/battery.h>
#include <board/smbus.h>
#include <common/macro.h>
#include <common/debug.h>
// uncrustify:off
// Registers
#define REG_CHARGE_CURRENT 0x14
#define REG_CHARGE_VOLTAGE 0x15
#define REG_DISCHARGE_CURRENT 0x39
#define REG_INPUT_CURRENT 0x3F
#define REG_CHARGE_OPTION_0 0x12
#define REG_CHARGE_OPTION_1 0x3B
#define REG_CHARGE_OPTION_2 0x38
#define REG_CHARGE_OPTION_3 0x37
// ChargeOption0 flags
// Low Power Mode Enable
#define SBC_EN_LWPWR ((uint16_t)(BIT(15)))
// Watchdog Timer Adjust
#define SBC_WDTMR_ADJ_175S ((uint16_t)(0b11 << 13))
// Switching Frequency
#define SBC_PWM_FREQ_800KHZ ((uint16_t)(0b01 << 8))
// IDCHG Amplifier Gain
#define SBC_IDCHC_GAIN ((uint16_t)(BIT(3)))
// ChargeOption1 flags
// Independent Comparator Deglitch
#define SBC_CMP_DEG_1US (0b01 << 4)
// PMON Gain
#define SBC_PMON_RATIO BIT(9)
// Adapter:Battery RSENSE ratio
#define SBC_RSENSE_RATIO_1_1 (0b00 << 12)
#define SBC_RSENSE_RATIO_2_1 (0b01 << 12)
#define SBC_RSENSE_RATIO_1_2 (0b10 << 12)
// Battery depletion threshold
#define SBC_BAT_DEPL_VTH (0b11 << 14)
// Bits 0-5 are ignored. Bits 13-15 must be 0.
#define CHARGE_CURRENT_MASK 0x1FC0
#if CHARGER_BATTERY_RSENSE == 5
#define CHARGE_CURRENT (MIN((CHARGER_CHARGE_CURRENT >> 1), CHARGE_CURRENT_MASK) & CHARGE_CURRENT_MASK)
#elif CHARGER_BATTERY_RSENSE == 10
#define CHARGE_CURRENT (MIN(CHARGER_CHARGE_CURRENT, CHARGE_CURRENT_MASK) & CHARGE_CURRENT_MASK)
#elif CHARGER_BATTERY_RSENSE == 20
#define CHARGE_CURRENT (MIN((CHARGER_CHARGE_CURRENT << 1), CHARGE_CURRENT_MASK) & CHARGE_CURRENT_MASK)
#else
#error Invalid battery RSENSE value
#endif
// Bits 0-3, 15 are ignored.
#define CHARGE_VOLTAGE_MASK 0x7FF0
#define CHARGE_VOLTAGE (MIN(CHARGER_CHARGE_VOLTAGE, CHARGE_VOLTAGE_MASK) & CHARGE_VOLTAGE_MASK)
// Bits 0-6 are ignored. Bits 13-15 must be 0.
#define INPUT_CURRENT_MASK 0x1F80
#if CHARGER_ADAPTER_RSENSE == 5
#define INPUT_CURRENT(X) (MIN(((X) >> 1), INPUT_CURRENT_MASK) & INPUT_CURRENT_MASK)
#elif CHARGER_ADAPTER_RSENSE == 10
#define INPUT_CURRENT(X) (MIN((X), INPUT_CURRENT_MASK) & INPUT_CURRENT_MASK)
#elif CHARGER_ADAPTER_RSENSE == 20
#define INPUT_CURRENT(X) (MIN(((X) << 1), INPUT_CURRENT_MASK) & INPUT_CURRENT_MASK)
#else
#error Invalid adapter RSENSE value
#endif
#if (CHARGER_ADAPTER_RSENSE == 5 && CHARGER_BATTERY_RSENSE == 5) || \
(CHARGER_ADAPTER_RSENSE == 10 && CHARGER_BATTERY_RSENSE == 10) || \
(CHARGER_ADAPTER_RSENSE == 20 && CHARGER_BATTERY_RSENSE == 20)
#define RSENSE_RATIO SBC_RSENSE_RATIO_1_1
#elif (CHARGER_ADAPTER_RSENSE == 10 && CHARGER_BATTERY_RSENSE == 5) || \
(CHARGER_ADAPTER_RSENSE == 20 && CHARGER_BATTERY_RSENSE == 10)
#define RSENSE_RATIO SBC_RSENSE_RATIO_2_1
#elif (CHARGER_ADAPTER_RSENSE == 5 && CHARGER_BATTERY_RSENSE == 10) || \
(CHARGER_ADAPTER_RSENSE == 10 && CHARGER_BATTERY_RSENSE == 20)
#define RSENSE_RATIO SBC_RSENSE_RATIO_1_2
#else
#error Invalid adapter:battery RSENSE ratio
#endif
// uncrustify:on
// XXX: Assumption: ac_last is initialized high.
static bool charger_enabled = false;
int16_t battery_charger_disable(void) {
int16_t res = 0;
if (!charger_enabled)
return 0;
// Set charge option 0 with 175s watchdog
res = smbus_write(
CHARGER_ADDRESS,
REG_CHARGE_OPTION_0,
SBC_EN_LWPWR | SBC_WDTMR_ADJ_175S | SBC_PWM_FREQ_800KHZ | SBC_IDCHC_GAIN
);
// Disable charge current
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_CURRENT, 0);
if (res < 0)
return res;
// Disable charge voltage
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_VOLTAGE, 0);
if (res < 0)
return res;
// Disable input current
res = smbus_write(CHARGER_ADDRESS, REG_INPUT_CURRENT, 0);
if (res < 0)
return res;
DEBUG("Charger disabled\n");
charger_enabled = false;
return 0;
}
int16_t battery_charger_enable(void) {
int16_t res = 0;
if (charger_enabled)
return 0;
res = battery_charger_disable();
if (res < 0)
return res;
// Set charge current in mA
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_CURRENT, CHARGE_CURRENT);
if (res < 0)
return res;
// Set charge voltage in mV
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_VOLTAGE, CHARGE_VOLTAGE);
if (res < 0)
return res;
// Set input current in mA
res = smbus_write(
CHARGER_ADDRESS,
REG_INPUT_CURRENT,
INPUT_CURRENT(battery_charger_input_current)
);
if (res < 0)
return res;
// Set charge option 0 with watchdog disabled
res = smbus_write(
CHARGER_ADDRESS,
REG_CHARGE_OPTION_0,
SBC_EN_LWPWR | SBC_PWM_FREQ_800KHZ | SBC_IDCHC_GAIN
);
// Set the RSENSE ratio
res = smbus_write(
CHARGER_ADDRESS,
REG_CHARGE_OPTION_1,
SBC_CMP_DEG_1US | SBC_PMON_RATIO | RSENSE_RATIO | SBC_BAT_DEPL_VTH
);
DEBUG("Charger enabled\n");
charger_enabled = true;
return 0;
}
void battery_charger_event(void) {
//TODO: watchdog
}
void battery_debug(void) {
uint16_t data = 0;
int16_t res = 0;
#define command(N, A, V) \
{ \
DEBUG(" " #N ": "); \
res = smbus_read(A, V, &data); \
if (res < 0) { \
DEBUG("ERROR %04X\n", -res); \
} else { \
DEBUG("%04X\n", data); \
} \
}
DEBUG("Battery:\n");
command(Temperature, BATTERY_ADDRESS, 0x08);
command(Voltage, BATTERY_ADDRESS, 0x09);
command(Current, BATTERY_ADDRESS, 0x0A);
command(Charge, BATTERY_ADDRESS, 0x0D);
command(Status, BATTERY_ADDRESS, 0x16);
DEBUG("Charger (bq24780s):\n");
command(ChargeOption0, CHARGER_ADDRESS, REG_CHARGE_OPTION_0);
command(ChargeOption1, CHARGER_ADDRESS, REG_CHARGE_OPTION_1);
command(ChargeOption2, CHARGER_ADDRESS, REG_CHARGE_OPTION_2);
command(ChargeOption3, CHARGER_ADDRESS, REG_CHARGE_OPTION_3);
command(ChargeCurrent, CHARGER_ADDRESS, REG_CHARGE_CURRENT);
command(ChargeVoltage, CHARGER_ADDRESS, REG_CHARGE_VOLTAGE);
command(DishargeCurrent, CHARGER_ADDRESS, REG_DISCHARGE_CURRENT);
command(InputCurrent, CHARGER_ADDRESS, REG_INPUT_CURRENT);
command(ProchotOption0, CHARGER_ADDRESS, 0x3C);
command(ProchotOption1, CHARGER_ADDRESS, 0x3D);
command(ProchotStatus, CHARGER_ADDRESS, 0x3A);
#undef command
}

View File

@@ -0,0 +1,223 @@
// SPDX-License-Identifier: GPL-3.0-only
//
// O2 Micro OZ26786
// No public datasheet
#include <board/battery.h>
#include <board/smbus.h>
#include <common/debug.h>
#include <common/macro.h>
// uncrustify:off
// Registers
#define REG_CHARGE_CURRENT 0x14
#define REG_CHARGE_VOLTAGE 0x15
#define REG_CHARGE_OPTION_1 0x3D
#define CHARGE_OPTION_1_600KHZ BIT(11)
#define REG_CHARGE_OPTION_2 0x3B
#define CHARGE_OPTION_2_PSYS_EN BIT(11)
#define REG_ADAPTER_CURRENT 0x3F
// Bits 0-5, 13-15 are ignored.
#define CHARGE_CURRENT_MASK 0x1FC0
#if CHARGER_BATTERY_RSENSE == 5
#define CHARGE_CURRENT (MIN((CHARGER_CHARGE_CURRENT >> 1), CHARGE_CURRENT_MASK) & CHARGE_CURRENT_MASK)
// XXX: According to the datasheet, only 10 and 20 are valid.
#define BATTERY_RSENSE (RSENSE_10 << 8)
#elif CHARGER_BATTERY_RSENSE == 10
#define CHARGE_CURRENT (MIN(CHARGER_CHARGE_CURRENT, CHARGE_CURRENT_MASK) & CHARGE_CURRENT_MASK)
#define BATTERY_RSENSE (RSENSE_10 << 8)
#elif CHARGER_BATTERY_RSENSE == 20
#define CHARGE_CURRENT (MIN((CHARGER_CHARGE_CURRENT << 1), CHARGE_CURRENT_MASK) & CHARGE_CURRENT_MASK)
#define BATTERY_RSENSE (RSENSE_20 << 8)
#else
#error Invalid battery RSENSE value
#endif
// Bits 0-3, 15 are ignored.
#define CHARGE_VOLTAGE_MASK 0x7FF0
#define CHARGE_VOLTAGE (MIN(CHARGER_CHARGE_VOLTAGE, CHARGE_VOLTAGE_MASK) & CHARGE_VOLTAGE_MASK)
// Bits 0-6 are ignored. Bits 12-15 must be 0.
#define INPUT_CURRENT_MASK 0x0F80
#if CHARGER_ADAPTER_RSENSE == 5
#define INPUT_CURRENT(X) (MIN(((X) >> 2), INPUT_CURRENT_MASK) & INPUT_CURRENT_MASK)
#define ADAPTER_RSENSE RSENSE_5
#elif CHARGER_ADAPTER_RSENSE == 10
#define INPUT_CURRENT(X) (MIN(((X) >> 1), INPUT_CURRENT_MASK) & INPUT_CURRENT_MASK)
#define ADAPTER_RSENSE RSENSE_10
#elif CHARGER_ADAPTER_RSENSE == 20
#define INPUT_CURRENT(X) (MIN((X), INPUT_CURRENT_MASK) & INPUT_CURRENT_MASK)
#define ADAPTER_RSENSE RSENSE_20
#else
#error Invalid adapter RSENSE value
#endif
// PSYS gain in nA/W
#ifndef CHARGER_PSYS_GAIN
#define CHARGER_PSYS_GAIN 1000
#endif
#if CHARGER_PSYS_GAIN == 1000
#define CHARGE_OPTION_2_PSYS_GAIN (0 << 8)
#elif CHARGER_PSYS_GAIN == 500
#define CHARGE_OPTION_2_PSYS_GAIN (1 << 8)
#elif CHARGER_PSYS_GAIN == 250
#define CHARGE_OPTION_2_PSYS_GAIN (2 << 8)
#elif CHARGER_PSYS_GAIN == 2000
#define CHARGE_OPTION_2_PSYS_GAIN (3 << 8)
#else
#error Invalid CHARGER_PSYS_GAIN value
#endif
// uncrustify:on
// Sense resistor values in milliohms.
enum sense_resistor {
RSENSE_10 = 0,
RSENSE_20 = 1,
RSENSE_5 = 2,
};
// XXX: Assumption: ac_last is initialized high.
static bool charger_enabled = false;
int16_t battery_charger_disable(void) {
int16_t res = 0;
if (!charger_enabled)
return 0;
// Set charge option 1 to converter frequency 600 KHz
//TODO: needed when charging disabled?
res = smbus_write(
CHARGER_ADDRESS,
REG_CHARGE_OPTION_1,
CHARGE_OPTION_1_600KHZ | ADAPTER_RSENSE | BATTERY_RSENSE
);
if (res < 0)
return res;
// Set charge option 2 to PSYS enable
//TODO: needed when charging disabled?
res = smbus_write(
CHARGER_ADDRESS,
REG_CHARGE_OPTION_2,
CHARGE_OPTION_2_PSYS_EN | CHARGE_OPTION_2_PSYS_GAIN
);
if (res < 0)
return res;
// Disable charge current
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_CURRENT, 0);
if (res < 0)
return res;
// Disable charge voltage
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_VOLTAGE, 0);
if (res < 0)
return res;
// Disable input current
res = smbus_write(CHARGER_ADDRESS, REG_ADAPTER_CURRENT, 0);
if (res < 0)
return res;
DEBUG("Charger disabled\n");
charger_enabled = false;
return 0;
}
int16_t battery_charger_enable(void) {
int16_t res = 0;
if (charger_enabled)
return 0;
res = battery_charger_disable();
if (res < 0)
return res;
// Set charge option 1 to converter frequency 600 KHz
res = smbus_write(
CHARGER_ADDRESS,
REG_CHARGE_OPTION_1,
CHARGE_OPTION_1_600KHZ | ADAPTER_RSENSE | BATTERY_RSENSE
);
if (res < 0)
return res;
// Set charge option 2 to PSYS enable
res = smbus_write(
CHARGER_ADDRESS,
REG_CHARGE_OPTION_2,
CHARGE_OPTION_2_PSYS_EN | CHARGE_OPTION_2_PSYS_GAIN
);
if (res < 0)
return res;
// Set charge current in mA
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_CURRENT, CHARGE_CURRENT);
if (res < 0)
return res;
// Set charge voltage in mV
res = smbus_write(CHARGER_ADDRESS, REG_CHARGE_VOLTAGE, CHARGE_VOLTAGE);
if (res < 0)
return res;
// Set input current in mA
res = smbus_write(
CHARGER_ADDRESS,
REG_ADAPTER_CURRENT,
INPUT_CURRENT(battery_charger_input_current)
);
if (res < 0)
return res;
DEBUG("Charger enabled\n");
charger_enabled = true;
return 0;
}
void battery_charger_event(void) {
// Avoid watchdog timeout
if (charger_enabled) {
// Set charge voltage in mV
smbus_write(CHARGER_ADDRESS, REG_CHARGE_VOLTAGE, CHARGE_VOLTAGE);
}
}
void battery_debug(void) {
uint16_t data = 0;
int16_t res = 0;
#define command(N, A, V) \
{ \
DEBUG(" " #N ": "); \
res = smbus_read(A, V, &data); \
if (res < 0) { \
DEBUG("ERROR %04X\n", -res); \
} else { \
DEBUG("%04X\n", data); \
} \
}
DEBUG("Battery:\n");
command(Temperature, BATTERY_ADDRESS, 0x08);
command(Voltage, BATTERY_ADDRESS, 0x09);
command(Current, BATTERY_ADDRESS, 0x0A);
command(Charge, BATTERY_ADDRESS, 0x0D);
command(Status, BATTERY_ADDRESS, 0x16);
DEBUG("Charger (oz26786):\n");
command(ChargeCurrent, CHARGER_ADDRESS, REG_CHARGE_CURRENT);
command(ChargeVoltage, CHARGER_ADDRESS, REG_CHARGE_VOLTAGE);
command(ChargeOption_1, CHARGER_ADDRESS, REG_CHARGE_OPTION_1);
command(ChargeOption_2, CHARGER_ADDRESS, REG_CHARGE_OPTION_2);
command(AdapterCurrent, CHARGER_ADDRESS, REG_ADAPTER_CURRENT);
#undef command
}

View File

@@ -1,5 +1,30 @@
# SPDX-License-Identifier: GPL-3.0-only
board-common-y += acpi.c
board-common-y += battery.c
board-common-y += config.c
board-common-$(CONFIG_HAVE_DGPU) += dgpu.c
board-common-y += ecpm.c
board-common-$(CONFIG_BUS_ESPI) += espi.c
board-common-y += fan.c
board-common-y += gctrl.c
board-common-y += kbc.c
board-common-y += kbscan.c
board-common-y += keymap.c
board-common-y += lid.c
board-common-y += main.c
board-common-y += parallel.c
board-common-y += pmc.c
board-common-y += pnp.c
board-common-y += ps2.c
board-common-y += pwm.c
board-common-y += scratch.c
board-common-$(CONFIG_SECURITY) += security.c
board-common-y += smbus.c
board-common-y += smfi.c
board-common-y += stdio.c
board-common-y += wireless.c
# Set log level
# 0 - NONE
# 1 - ERROR
@@ -15,20 +40,80 @@ CFLAGS+=-DLEVEL=4
# Uncomment to enable I2C debug on 0x76
#CFLAGS+=-DI2C_DEBUGGER=0x76
ifeq ($(CONFIG_PLATFORM_INTEL),y)
board-common-y += peci.c
board-common-y += power/intel.c
CFLAGS += -DCONFIG_PLATFORM_INTEL=1
else ifeq ($(CONFIG_PLATFORM_AMD),y)
board-common-y += power/amd.c
CFLAGS += -DCONFIG_PLATFORM_AMD=1
else
$(error PLATFORM not specified)
endif
ifeq ($(CONFIG_SECURITY),y)
CFLAGS+=-DCONFIG_SECURITY=1
endif
# Set external programmer
PROGRAMMER=$(wildcard /dev/serial/by-id/usb-Arduino*)
ifeq ($(CONFIG_BUS_ESPI),y)
CFLAGS += -DCONFIG_BUS_ESPI=1
# TODO: Use PECI over eSPI on all boards using eSPI
ifeq ($(CONFIG_PECI_OVER_ESPI),y)
CFLAGS += -DCONFIG_PECI_OVER_ESPI=1
endif
endif
ifeq ($(CONFIG_HAVE_DGPU),y)
CFLAGS += -DCONFIG_HAVE_DGPU=1
endif
# Include system76 common source
SYSTEM76_COMMON_DIR=src/board/system76/common
SRC+=$(wildcard $(SYSTEM76_COMMON_DIR)/*.c)
INCLUDE+=$(wildcard $(SYSTEM76_COMMON_DIR)/include/common/*.h) $(SYSTEM76_COMMON_DIR)/common.mk
INCLUDE += $(SYSTEM76_COMMON_DIR)/common.mk
CFLAGS+=-I$(SYSTEM76_COMMON_DIR)/include
# Set battery charging thresholds
BATTERY_START_THRESHOLD?=90
BATTERY_END_THRESHOLD?=100
CFLAGS+=\
-DBATTERY_START_THRESHOLD=$(BATTERY_START_THRESHOLD) \
-DBATTERY_END_THRESHOLD=$(BATTERY_END_THRESHOLD)
# Add charger
CHARGER?=bq24780s
board-common-y += charger/$(CHARGER).c
# Add USB-PD
ifeq ($(CONFIG_HAVE_USBPD),y)
CFLAGS += -DCONFIG_HAVE_USBPD=1
board-common-$(CONFIG_USBPD_TPS65987) += usbpd/tps65987.c
endif
# Add keyboard
ifndef KEYBOARD
$(error KEYBOARD is not set by the board)
endif
KEYBOARD_DIR=src/keyboard/system76/$(KEYBOARD)
include $(KEYBOARD_DIR)/keyboard.mk
# Add kbled
ifeq ($(CONFIG_HAVE_KBLED),y)
CFLAGS += -DCONFIG_HAVE_KBLED=1
board-common-y += kbled/common.c
board-common-y += kbled/$(KBLED).c
endif
# Add scratch ROM
include $(SYSTEM76_COMMON_DIR)/scratch/scratch.mk
# Add scratch ROM for flash access
include $(SYSTEM76_COMMON_DIR)/flash/flash.mk
board-common-y += flash/wrapper.c
console_internal:
cargo build --manifest-path tool/Cargo.toml --release
@@ -39,6 +124,11 @@ console_external:
sleep 1 && echo C | sudo tee "$(PROGRAMMER)" &
sudo tio -b 1000000 -m INLCRNL -t "$(PROGRAMMER)"
console_external_forced:
sudo test -c "$(PROGRAMMER)"
sleep 1 && echo F | sudo tee "$(PROGRAMMER)" &
sudo tio -b 1000000 -m INLCRNL -t "$(PROGRAMMER)"
flash_internal: $(BUILD)/ec.rom
cargo build --manifest-path tool/Cargo.toml --release
sudo tool/target/release/system76_ectool flash $<

View File

@@ -1,105 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/dgpu.h>
#if HAVE_DGPU
#include <board/fan.h>
#include <board/gpio.h>
#include <board/power.h>
#include <common/debug.h>
#include <common/macro.h>
#include <ec/i2c.h>
#include <ec/pwm.h>
// Fan speed is the lowest requested over HEATUP seconds
#ifndef BOARD_DGPU_HEATUP
#define BOARD_DGPU_HEATUP 10
#endif
static uint8_t FAN_HEATUP[BOARD_DGPU_HEATUP] = { 0 };
// Fan speed is the highest HEATUP speed over COOLDOWN seconds
#ifndef BOARD_DGPU_COOLDOWN
#define BOARD_DGPU_COOLDOWN 10
#endif
static uint8_t FAN_COOLDOWN[BOARD_DGPU_COOLDOWN] = { 0 };
int16_t dgpu_temp = 0;
#define DGPU_TEMP(X) ((int16_t)(X))
#define FAN_POINT(T, D) { .temp = DGPU_TEMP(T), .duty = PWM_DUTY(D) }
// Fan curve with temperature in degrees C, duty cycle in percent
static struct FanPoint __code FAN_POINTS[] = {
#ifdef BOARD_DGPU_FAN_POINTS
BOARD_DGPU_FAN_POINTS
#else
FAN_POINT(70, 40),
FAN_POINT(75, 50),
FAN_POINT(80, 60),
FAN_POINT(85, 65),
FAN_POINT(90, 65)
#endif
};
static struct Fan __code FAN = {
.points = FAN_POINTS,
.points_size = ARRAY_SIZE(FAN_POINTS),
.heatup = FAN_HEATUP,
.heatup_size = ARRAY_SIZE(FAN_HEATUP),
.cooldown = FAN_COOLDOWN,
.cooldown_size = ARRAY_SIZE(FAN_COOLDOWN),
.interpolate = false,
};
void dgpu_init(void) {
// Set up for i2c usage
i2c_reset(&I2C_DGPU, true);
}
void dgpu_event(void) {
uint8_t duty;
if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) {
// Use I2CS if in S0 state
bool dgpu_get_temp(int16_t *const data) {
if (gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) {
int8_t rlts;
int res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1);
int16_t res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1);
if (res == 1) {
dgpu_temp = (int16_t)rlts;
duty = fan_duty(&FAN, dgpu_temp);
*data = (int16_t)rlts;
return true;
} else {
DEBUG("DGPU temp error: %d\n", res);
// Default to 50% if there is an error
dgpu_temp = 0;
duty = PWM_DUTY(50);
*data = 0;
return false;
}
} else {
// Turn fan off if not in S0 state or GPU power not on
dgpu_temp = 0;
duty = PWM_DUTY(0);
}
if (fan_max) {
// Override duty if fans are manually set to maximum
duty = PWM_DUTY(100);
} else {
// Apply heatup and cooldown filters to duty
duty = fan_heatup(&FAN, duty);
duty = fan_cooldown(&FAN, duty);
}
if (duty != DCR4) {
DCR4 = duty;
DEBUG("DGPU temp=%d = %d\n", dgpu_temp, duty);
}
*data = 0;
return true;
}
#else
void dgpu_read_temp(void) {
if (power_state == POWER_STATE_S0) {
if (dgpu_get_temp(&dgpu_temp)) {
return;
}
}
void dgpu_init(void) {}
void dgpu_event(void) {}
#endif // HAVE_DGPU
dgpu_temp = 0;
}

View File

@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-only
#include <board/ecpm.h>
#include <common/macro.h>
void ecpm_init(void) {
// Clock gate EGPC, CIR, and SWUC
CGCTRL2 |= (1 << 6) | (1 << 5) | (1 << 4);
CGCTRL2 |= BIT(6) | BIT(5) | BIT(4);
// Clock gate UART, SSPI, and DBGR
CGCTRL3 |= (1 << 2) | (1 << 1) | (1 << 0);
CGCTRL3 |= BIT(2) | BIT(1) | BIT(0);
// Clock gate CEC
CGCTRL4 |= (1 << 0);
CGCTRL4 |= BIT(0);
}

Some files were not shown because too many files have changed in this diff Show More