Compare commits
451 Commits
29034569c8
...
e41716575c
Author | SHA1 | Date | |
---|---|---|---|
|
e41716575c | ||
|
3d8204c3f4 | ||
|
2c6977bc6b | ||
|
ae63a9e3fb | ||
|
88ad52491a | ||
|
85cd3aa9ce | ||
|
710b4795fb | ||
|
2925376b6b | ||
|
51d35cb272 | ||
|
716efd4eb5 | ||
|
984428b6a8 | ||
|
0f7642defb | ||
|
9e7f1952fa | ||
|
face381354 | ||
|
a7bd81432e | ||
|
ffd0b7cbde | ||
|
e75a2f1e10 | ||
|
f8697a7ec4 | ||
|
ceba69d7fa | ||
|
e01536005a | ||
|
8f88c0c7aa | ||
|
80cfa91b9f | ||
|
2a44e03a40 | ||
|
70c8678a5f | ||
|
54d795480c | ||
|
426dc99f10 | ||
|
1e02be1cbe | ||
|
d3894392d5 | ||
|
6c3b34ee6e | ||
|
3d09a0b546 | ||
|
5b0766a209 | ||
|
d88a175e23 | ||
|
2c5c708569 | ||
|
a67b0c98b8 | ||
|
f79f4d1157 | ||
|
1e4667f1d3 | ||
|
fc3bad29a2 | ||
|
8382c81b9d | ||
|
09c5a3b5f0 | ||
|
b4768ed2dd | ||
|
88c77aa1d3 | ||
|
522284e5d5 | ||
|
e7ad77898b | ||
|
b744529960 | ||
|
748ec13132 | ||
|
38d4666a90 | ||
|
637036ec02 | ||
|
6a40a54932 | ||
|
91b8c48773 | ||
|
90af96faf5 | ||
|
17aae5af71 | ||
|
6aced2fd57 | ||
|
16e4f93f2c | ||
|
9fb08ffa46 | ||
|
d60a8e4c8e | ||
|
8c52c313e1 | ||
|
8af7fd5bad | ||
|
2174b4593a | ||
|
fff6208f98 | ||
|
ecac574671 | ||
|
acf67d4413 | ||
|
183778c32f | ||
|
82b9e19746 | ||
|
449bafd130 | ||
|
ef4eeae2df | ||
|
4b86176659 | ||
|
766fb738a0 | ||
|
0ccb8079ae | ||
|
0e1a748b16 | ||
|
11b1e724b5 | ||
|
47b070418a | ||
|
cbad8e09be | ||
|
713e1d9681 | ||
|
01be30f107 | ||
|
946415f3a7 | ||
|
a3fb9e1c77 | ||
|
166e03972b | ||
|
4fa389e1bd | ||
|
782f18a3f6 | ||
|
c461e20df3 | ||
|
bb1ce2273b | ||
|
181d4c5d59 | ||
|
1097fd999a | ||
|
34dd9ccbac | ||
|
894b82d4fb | ||
|
dc482dd11a | ||
|
13dd6a1038 | ||
|
c0bfb257db | ||
|
8d844cf966 | ||
|
01907011bb | ||
|
b63e2092ce | ||
|
ebc5168cb0 | ||
|
9b7c6704c3 | ||
|
bd291871f4 | ||
|
9302a30a2d | ||
|
459e5a3614 | ||
|
120ed1e2c5 | ||
|
d4ecd8a79a | ||
|
0f2ff7e540 | ||
|
546458e368 | ||
|
8a1adc2bdc | ||
|
45520646aa | ||
|
de546fa761 | ||
|
0d83819a21 | ||
|
64e5b8308d | ||
|
1ebc0bc6c2 | ||
|
e093952dd2 | ||
|
1fded3f7bf | ||
|
4458d5dbe2 | ||
|
42a19b3d6b | ||
|
dd555b9012 | ||
|
c7288a5a60 | ||
|
8e6d938f90 | ||
|
347bbf0d9a | ||
|
faede6264a | ||
|
fe6faa21fc | ||
|
485f390077 | ||
|
9b111bafc6 | ||
|
c09960cbc6 | ||
|
2dd33ffec5 | ||
|
399415fdf6 | ||
|
9ac513128a | ||
|
4c9d3197b8 | ||
|
bfbbfe43e6 | ||
|
598aef8c4a | ||
|
c71a58f7cf | ||
|
e60873a82c | ||
|
002823908a | ||
|
498508f2f1 | ||
|
f4ad9520a8 | ||
|
82f091ef55 | ||
|
2d5cbadf71 | ||
|
43dfbb055b | ||
|
99dfbeaec3 | ||
|
b967e7c921 | ||
|
f5c4eaba97 | ||
|
ca1996dd44 | ||
|
bc92291c26 | ||
|
e6b8eb4c42 | ||
|
93c2784eb3 | ||
|
f5c2548d04 | ||
|
36e6059e90 | ||
|
3f4c65931a | ||
|
55632aab7a | ||
|
f80f40f006 | ||
|
5d2f2fd5c0 | ||
|
930f16b230 | ||
|
d38ef1413f | ||
|
916c9f8c5f | ||
|
5d11cc14f8 | ||
|
a03ce8d1c3 | ||
|
da9648dddb | ||
|
d0596100bd | ||
|
cd0321bfbb | ||
|
658f24a8a8 | ||
|
7a5c111786 | ||
|
c5229fafab | ||
|
a5ea9f4f05 | ||
|
49aee51343 | ||
|
edcfac1050 | ||
|
5b55048ef3 | ||
|
a1f4bb55bb | ||
|
cd53d28d2e | ||
|
5adacc4241 | ||
|
4745b109d8 | ||
|
c76919b189 | ||
|
3eaa5e6e06 | ||
|
c1c082d2cc | ||
|
568fae6aba | ||
|
a198289695 | ||
|
b1bd244d49 | ||
|
546dd30b5e | ||
|
1dd25e0bf0 | ||
|
8228362c5d | ||
|
584e397b07 | ||
|
86f281b410 | ||
|
4a1e0a5aa8 | ||
|
4567f99015 | ||
|
3dde812dba | ||
|
dd97946056 | ||
|
373dc36676 | ||
|
22487f737d | ||
|
0348800411 | ||
|
f73160fad5 | ||
|
4aeb3669a0 | ||
|
7587a6412d | ||
|
ba5438a79a | ||
|
55df52a013 | ||
|
cb8e0971c6 | ||
|
34ef03b19a | ||
|
33eaef2dd0 | ||
|
0d438a3314 | ||
|
962d55309a | ||
|
fc1fda0725 | ||
|
35d3c4f161 | ||
|
6b80721138 | ||
|
a0c81f6304 | ||
|
4e11f6220b | ||
|
cea89a78d8 | ||
|
a5a677ee63 | ||
|
8c52a51af1 | ||
|
cda67e6d1e | ||
|
9abd9d853a | ||
|
83f40c643f | ||
|
95a654aaff | ||
|
53f22a6658 | ||
|
c8df652723 | ||
|
9c59871986 | ||
|
cd3e5ac329 | ||
|
d68a42180b | ||
|
55f961406c | ||
|
db10c198b3 | ||
|
c7bc078cbd | ||
|
60f9cfc8d6 | ||
|
e4542d2aa5 | ||
|
e4d7196b5c | ||
|
d723e2e13d | ||
|
ff7d7138b0 | ||
|
8bd3b49273 | ||
|
213f79e2b6 | ||
|
bc111b7a4b | ||
|
ef6ea32c37 | ||
|
1046dd7aec | ||
|
96b2d78c2e | ||
|
ddb19e8738 | ||
|
084aefd506 | ||
|
59c386ec12 | ||
|
f687000a4f | ||
|
7205f1a49e | ||
|
623d3ce8ab | ||
|
58f9ed4051 | ||
|
1aadc68257 | ||
|
b03c960b4f | ||
|
2056d4d5e0 | ||
|
9a52042f95 | ||
|
84fe76cad4 | ||
|
28882975e3 | ||
|
f46360fb45 | ||
|
7ebec4f7b1 | ||
|
e032c5f0f2 | ||
|
c3267fc4ad | ||
|
d687df482a | ||
|
5e884cf413 | ||
|
a8e37276e9 | ||
|
1019878e3c | ||
|
cd28de382d | ||
|
004c7acf6c | ||
|
2a8befc195 | ||
|
be4659a0cb | ||
|
839abf7878 | ||
|
861f1f2cc8 | ||
|
ac9631f948 | ||
|
ce66685c70 | ||
|
c5b737f505 | ||
|
edbb5b594a | ||
|
be5d34dc0d | ||
|
d36fb62cd7 | ||
|
69f97fe149 | ||
|
01885609e8 | ||
|
f8d1123934 | ||
|
76019bdb61 | ||
|
a32a3e3e95 | ||
|
7f28764436 | ||
|
5cf57d69b9 | ||
|
cc3effb6a4 | ||
|
49abf83c08 | ||
|
b78631e316 | ||
|
a8213311b1 | ||
|
a6a6c5fba4 | ||
|
cd86c1e7d7 | ||
|
371f6d3047 | ||
|
6295f60172 | ||
|
20d40f3477 | ||
|
22fa2769ad | ||
|
7ab91e9f1d | ||
|
5ef477ab5b | ||
|
e8d91e5c2d | ||
|
60dfb62f90 | ||
|
7b9b91187a | ||
|
158ec124fe | ||
|
375d11f4ed | ||
|
a70ea4558c | ||
|
5780bb5e83 | ||
|
700f9e3756 | ||
|
b70a09e205 | ||
|
04df6ae311 | ||
|
f21cc6d602 | ||
|
ee8ba5b72e | ||
|
84f9aad7d8 | ||
|
cb341cfb2b | ||
|
474b1c2191 | ||
|
2262097c2b | ||
|
4bab1cc00d | ||
|
c31ef33101 | ||
|
1cb61e6918 | ||
|
ca58502137 | ||
|
7d75235081 | ||
|
ab0c55fae2 | ||
|
85595a8d4c | ||
|
d9ce247a15 | ||
|
e8ce6d9096 | ||
|
95632b4503 | ||
|
55a617f2e0 | ||
|
987a5b4b70 | ||
|
43e5cf4ba3 | ||
|
975377af42 | ||
|
9fa83ad359 | ||
|
d3ee037879 | ||
|
9046f1e527 | ||
|
15c5f936b5 | ||
|
646a6436a7 | ||
|
f55e493001 | ||
|
e00686a661 | ||
|
73c6bd986d | ||
|
d99ea41259 | ||
|
37fa06ebc8 | ||
|
5599c02e83 | ||
|
458cb000f3 | ||
|
571316a4ea | ||
|
f27d6350f2 | ||
|
2a3830fb57 | ||
|
784202383e | ||
|
99af8a35f5 | ||
|
38b2a628f9 | ||
|
ff53939a56 | ||
|
2720bb9037 | ||
|
90057df94f | ||
|
913b0dfc44 | ||
|
e25af93f2e | ||
|
9aab239f0a | ||
|
701adb2f27 | ||
|
146f2d2b4a | ||
|
e86e18d4b1 | ||
|
f9e4e25b05 | ||
|
cd8e76420d | ||
|
851221da61 | ||
|
c7fafe0103 | ||
|
92c8f8f3d1 | ||
|
1fc832ca94 | ||
|
d1db553e8c | ||
|
f8d81a1e1b | ||
|
43651cf2c2 | ||
|
a8229d9e62 | ||
|
3f446e5c6e | ||
|
8ea0403850 | ||
|
b7368e8202 | ||
|
5a7fd2d7b3 | ||
|
dab3a24fcb | ||
|
d36cf981fe | ||
|
ca09e86987 | ||
|
df469a9eea | ||
|
4742fd9742 | ||
|
689cea4e9c | ||
|
6c5257ff3e | ||
|
51d6319f5b | ||
|
b3b2a312b7 | ||
|
3fe0e2f4e4 | ||
|
1b539e1206 | ||
|
532219c3f8 | ||
|
76e02c9514 | ||
|
285d622fbc | ||
|
aa880033e3 | ||
|
316376c271 | ||
|
8bdcf243ec | ||
|
4963e04a83 | ||
|
720af4b2b0 | ||
|
9a3ecba010 | ||
|
7888f214bb | ||
|
606ba01b48 | ||
|
f0c42f5839 | ||
|
73b4e42726 | ||
|
1ea21aedbe | ||
|
55523d4083 | ||
|
84d5c6b79d | ||
|
16778e4a41 | ||
|
a04d353096 | ||
|
2401fcc50d | ||
|
61428bd198 | ||
|
0017450cbb | ||
|
17f8e37ed5 | ||
|
66a970fa51 | ||
|
9ad6b54aed | ||
|
91d128f0a0 | ||
|
aab45bfcc1 | ||
|
301eef6f21 | ||
|
59df32814b | ||
|
aefad937bb | ||
|
325762d4d8 | ||
|
8825b906bd | ||
|
f30a9d84f7 | ||
|
2ef4cd7bbd | ||
|
c931eb4eef | ||
|
67e143178d | ||
|
4cd4df03e8 | ||
|
b11bc64bba | ||
|
73a5d8b8a1 | ||
|
221da86e20 | ||
|
340ddd2e81 | ||
|
ba99aec1b7 | ||
|
71534e736c | ||
|
3e154d7f00 | ||
|
3e742b0da7 | ||
|
9ef191edff | ||
|
44a0b887c4 | ||
|
4ba943e3df | ||
|
230d7f10b1 | ||
|
55b6256ed6 | ||
|
2ac214352b | ||
|
71f0f1e181 | ||
|
e30779ab8d | ||
|
2768925ec6 | ||
|
171257916c | ||
|
49b79f665b | ||
|
7c5ba4e62c | ||
|
504284bf72 | ||
|
0c1584385c | ||
|
f4458aebca | ||
|
791b3224f9 | ||
|
18ec0eb694 | ||
|
3a9665a753 | ||
|
12a9ac8d84 | ||
|
304e7534c9 | ||
|
5bab59a526 | ||
|
9309efb3e0 | ||
|
47c1062e08 | ||
|
7f4a837bcf | ||
|
fbaea59b46 | ||
|
8f340d6164 | ||
|
b156d18bc2 | ||
|
fb6355f907 | ||
|
31a908556b | ||
|
5559d4e2f6 | ||
|
3f41cd6ab3 | ||
|
99a0d6861f | ||
|
c7827e4a7c | ||
|
c3fa2a27a7 | ||
|
0595ba2b16 | ||
|
6da7a48e16 | ||
|
515c7495c1 | ||
|
e4e7f89a67 | ||
|
4de18eba93 | ||
|
b0c196d4b9 | ||
|
87e16205d6 | ||
|
932dbe8e71 | ||
|
f0c129c9f1 | ||
|
c40dd06da6 | ||
|
42f1b4863f | ||
|
802bf417cc | ||
|
43d31ca0c3 | ||
|
5c4f9b6c8b | ||
|
2a56a82164 |
@@ -13,8 +13,8 @@ trim_trailing_whitespace = true
|
|||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
[*.mk]
|
[{Makefile,*.mk}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
[Makefile]
|
[*.yml]
|
||||||
indent_style = tab
|
indent_size = 2
|
||||||
|
67
.github/workflows/ci.yml
vendored
Normal file
67
.github/workflows/ci.yml
vendored
Normal 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
156
.uncrustify.cfg
Normal 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__
|
86
Makefile
86
Makefile
@@ -2,60 +2,102 @@
|
|||||||
|
|
||||||
-include config.mk
|
-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
|
# Parameter for current board
|
||||||
ifeq ($(BOARD),)
|
ifeq ($(BOARD),)
|
||||||
all:
|
all:
|
||||||
@echo "Please set BOARD to one of the following:"
|
$(error BOARD must be specified)
|
||||||
@cd src/board && for board in */*/board.mk; do \
|
|
||||||
echo " $$(dirname "$$board")"; \
|
|
||||||
done
|
|
||||||
@exit 1
|
|
||||||
else
|
else
|
||||||
# Calculate version
|
# Calculate version
|
||||||
DATE=$(shell git show --format="%cd" --date="format:%Y-%m-%d" --no-patch)
|
DATE=$(shell git show --format="%cs" --no-patch --no-show-signature)
|
||||||
REV=$(shell git describe --always --dirty)
|
REV=$(shell git describe --abbrev=7 --always --dirty)
|
||||||
VERSION?=$(DATE)_$(REV)
|
VERSION?=$(DATE)_$(REV)
|
||||||
|
|
||||||
# Set build directory
|
|
||||||
BUILD=build/$(BOARD)/$(VERSION)
|
|
||||||
|
|
||||||
# Default target - build the board's EC firmware
|
# Default target - build the board's EC firmware
|
||||||
all: $(BUILD)/ec.rom
|
all: $(BUILD)/ec.rom
|
||||||
$(info Built '$(VERSION)' for '$(BOARD)')
|
$(info Built $(VERSION) for $(BOARD))
|
||||||
|
|
||||||
# Include common source
|
# Include common source
|
||||||
COMMON_DIR=src/common
|
COMMON_DIR=src/common
|
||||||
SRC=$(wildcard $(COMMON_DIR)/*.c)
|
INCLUDE += $(COMMON_DIR)/common.mk
|
||||||
INCLUDE=$(wildcard $(COMMON_DIR)/include/common/*.h) $(COMMON_DIR)/common.mk
|
|
||||||
CFLAGS=-I$(COMMON_DIR)/include -D__FIRMWARE_VERSION__=$(VERSION)
|
CFLAGS=-I$(COMMON_DIR)/include -D__FIRMWARE_VERSION__=$(VERSION)
|
||||||
include $(COMMON_DIR)/common.mk
|
include $(COMMON_DIR)/common.mk
|
||||||
|
SRC += $(foreach src, $(common-y), $(COMMON_DIR)/$(src))
|
||||||
|
|
||||||
# Include the board's source
|
# Include the board's source
|
||||||
BOARD_DIR=src/board/$(BOARD)
|
BOARD_DIR=src/board/$(BOARD)
|
||||||
SRC+=$(wildcard $(BOARD_DIR)/*.c)
|
INCLUDE += $(BOARD_DIR)/board.mk
|
||||||
INCLUDE+=$(wildcard $(BOARD_DIR)/include/board/*.h) $(BOARD_DIR)/board.mk
|
|
||||||
CFLAGS+=-I$(BOARD_DIR)/include -D__BOARD__=$(BOARD)
|
CFLAGS+=-I$(BOARD_DIR)/include -D__BOARD__=$(BOARD)
|
||||||
include $(BOARD_DIR)/board.mk
|
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
|
# The board will define the embedded controller
|
||||||
# Include the embedded controller's source
|
# Include the embedded controller's source
|
||||||
EC_DIR=src/ec/$(EC)
|
EC_DIR=src/ec/$(EC)
|
||||||
SRC+=$(wildcard $(EC_DIR)/*.c)
|
INCLUDE += $(EC_DIR)/ec.mk
|
||||||
INCLUDE+=$(wildcard $(EC_DIR)/include/ec/*.h) $(EC_DIR)/ec.mk
|
CFLAGS+=-I$(EC_DIR)/include
|
||||||
CFLAGS+=-I$(EC_DIR)/include -D__EC__=$(EC)
|
|
||||||
include $(EC_DIR)/ec.mk
|
include $(EC_DIR)/ec.mk
|
||||||
|
SRC += $(foreach src, $(ec-y), $(EC_DIR)/$(src))
|
||||||
|
|
||||||
# The EC will define the architecture
|
# The EC will define the architecture
|
||||||
# Include the architecture's source
|
# Include the architecture's source
|
||||||
ARCH_DIR=src/arch/$(ARCH)
|
ARCH_DIR=src/arch/$(ARCH)
|
||||||
SRC+=$(wildcard $(ARCH_DIR)/*.c)
|
INCLUDE += $(ARCH_DIR)/arch.mk
|
||||||
INCLUDE+=$(wildcard $(ARCH_DIR)/include/arch/*.h) $(ARCH_DIR)/arch.mk
|
|
||||||
CFLAGS+=-I$(ARCH_DIR)/include -D__ARCH__=$(ARCH)
|
CFLAGS+=-I$(ARCH_DIR)/include -D__ARCH__=$(ARCH)
|
||||||
include $(ARCH_DIR)/arch.mk
|
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
|
# The architecture defines build targets, no more is required
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Target to remove build artifacts
|
.PHONY: docs
|
||||||
|
docs:
|
||||||
|
mdbook build docs/
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
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"
|
||||||
|
72
README.md
72
README.md
@@ -5,23 +5,67 @@ laptops.
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- [Supported embedded controllers](./doc/controllers.md)
|
- [Supported embedded controllers](./docs/controllers.md)
|
||||||
- [Flashing firmware](./doc/flashing.md)
|
- [Flashing firmware](./docs/flashing.md)
|
||||||
- [Debugging](./doc/debugging.md)
|
- [Debugging](./docs/debugging.md)
|
||||||
- [Creating a custom keyboard layout](./doc/keyboard-layout-customization.md)
|
- [Creating a custom keyboard layout](./docs/keyboard-layout-customization.md)
|
||||||
- [Adding a new board](./doc/adding-a-new-board.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
|
Install dependencies using the provided script.
|
||||||
from the [Open Firmware](https://github.com/system76/firmware-open) repo.
|
|
||||||
|
|
||||||
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 \
|
git ls-tree <release_hash> ec
|
||||||
avr-libc \
|
|
||||||
avrdude \
|
|
||||||
gcc-avr \
|
|
||||||
sdcc
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[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
|
||||||
|
@@ -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
|
|
||||||
```
|
|
@@ -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
10
docs/SUMMARY.md
Normal 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)
|
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
## Charger parameters
|
## 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
|
- `CHARGER_CHARGE_VOLTAGE`: On the battery, look for 充电限制电压 (charge limit
|
||||||
voltage). Convert this from volts to millivolts.
|
voltage). Convert this from volts to millivolts.
|
||||||
- `CHARGER_INPUT_CURRENT`: On the charger, look for DC output. Convert the
|
- `CHARGER_INPUT_CURRENT`: On the charger, look for DC output. Convert the
|
||||||
@@ -10,23 +12,28 @@
|
|||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
The gaze15 battery has
|
The gaze15 battery has:
|
||||||
|
|
||||||
```
|
```
|
||||||
充电限制电压: 16.8Vdc
|
充电限制电压: 16.8Vdc
|
||||||
```
|
```
|
||||||
|
|
||||||
and its charger has
|
Its charger has:
|
||||||
|
|
||||||
```
|
```
|
||||||
DC OUTPUT (输出/輸出): 19.5V⎓9.23A 180W
|
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+=\
|
CFLAGS+=\
|
||||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
-DCHARGER_ADAPTER_RSENSE=5 \
|
||||||
|
-DCHARGER_BATTERY_RSENSE=5 \
|
||||||
|
-DCHARGER_CHARGE_CURRENT=3072 \
|
||||||
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
||||||
-DCHARGER_INPUT_CURRENT=9230
|
-DCHARGER_INPUT_CURRENT=9230
|
||||||
```
|
```
|
20
docs/book.toml
Normal file
20
docs/book.toml
Normal 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
|
@@ -5,7 +5,25 @@ Terms used:
|
|||||||
- *host*: The system that will have all devices connected to it and
|
- *host*: The system that will have all devices connected to it and
|
||||||
will receive the EC logs
|
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.
|
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
|
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
|
For details on configuring the Mega 2560 and breakout board, see
|
||||||
[mega2560](./mega2560.md).
|
[mega2560](./mega2560.md).
|
||||||
|
|
||||||
### Setup
|
#### Setup
|
||||||
|
|
||||||
1. Enable parallel port debugging in the EC firmware
|
1. Enable parallel port debugging in the EC firmware
|
||||||
- Uncomment `PARALLEL_DEBUG` in `src/board/system76/common/common.mk`
|
- 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.
|
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
|
**Failure to follow steps in order, or performing steps on an
|
||||||
unsupported board, may result in damaged board components.**
|
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
|
The I2C connection is made through the battery pins. Find the pins marked
|
||||||
`SMC_BAT` (clock) and `SMD_BAT` (data) in the service manual.
|
`SMC_BAT` (clock) and `SMD_BAT` (data) in the service manual.
|
||||||
@@ -69,8 +87,10 @@ galp4 | 4 | 5
|
|||||||
gaze14 | 4 | 3
|
gaze14 | 4 | 3
|
||||||
gaze15 | 4 | 3
|
gaze15 | 4 | 3
|
||||||
lemp9 | 6 | 5
|
lemp9 | 6 | 5
|
||||||
|
lemp10 | 6 | 5
|
||||||
oryp5 | 4 | 5
|
oryp5 | 4 | 5
|
||||||
oryp6 | 6 | 5
|
oryp6 | 6 | 5
|
||||||
|
oryp7 | 6 | 5
|
||||||
|
|
||||||
1. Power off system
|
1. Power off system
|
||||||
2. Unplug AC adapter
|
2. Unplug AC adapter
|
||||||
@@ -84,7 +104,7 @@ oryp6 | 6 | 5
|
|||||||
9. Reconnect battery
|
9. Reconnect battery
|
||||||
10. Replace bottom panel
|
10. Replace bottom panel
|
||||||
|
|
||||||
### Setup
|
#### Setup
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
- Target wired for EC debugging
|
- Target wired for EC debugging
|
53
docs/dev-env.md
Normal file
53
docs/dev-env.md
Normal 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
76
docs/flashing.md
Normal 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
|
||||||
|
```
|
118
docs/keyboard-layout-customization.md
Normal file
118
docs/keyboard-layout-customization.md
Normal 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.
|
@@ -18,7 +18,7 @@ it uses the ATmega16U2, find a different model.
|
|||||||
A flexible printed circuit (FPC) breakout board is required. It should have:
|
A flexible printed circuit (FPC) breakout board is required. It should have:
|
||||||
|
|
||||||
- 24 pins with 0.1" (2.54mm) pitch
|
- 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)
|
- 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
|
Depending on the vendor, the connectors may not come soldered to the board (or
|
13
docs/security.md
Normal file
13
docs/security.md
Normal 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.
|
2
ecflash
2
ecflash
Submodule ecflash updated: 1f947933e1...2b94b81b97
2
ecsim
2
ecsim
Submodule ecsim updated: aee30bc263...2d672adae5
2
ecspy
2
ecspy
Submodule ecspy updated: b3bde0a1be...f0bf26d577
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
cargo build --release --manifest-path tool/Cargo.toml
|
|
||||||
sudo tool/target/release/system76_ectool "$@"
|
|
65
layouts.sh
65
layouts.sh
@@ -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
|
|
@@ -1 +0,0 @@
|
|||||||
nightly-2020-07-27
|
|
4
rust-toolchain.toml
Normal file
4
rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly-2024-05-11"
|
||||||
|
components = ["clippy", "rustfmt"]
|
||||||
|
profile = "minimal"
|
14
scripts/coccinelle/bit-macro.cocci
Normal file
14
scripts/coccinelle/bit-macro.cocci
Normal 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)
|
9
scripts/coccinelle/macros.h
Normal file
9
scripts/coccinelle/macros.h
Normal 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
94
scripts/deps.sh
Executable 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
6
scripts/ectool.sh
Executable 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
7
scripts/hooks/pre-commit.sh
Executable 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
52
scripts/lint/01-spdx-tags.sh
Executable 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
36
scripts/lint/02-uncrustify.sh
Executable 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
36
scripts/lint/03-shellcheck.sh
Executable 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
14
scripts/lint/lint.sh
Executable 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
15
scripts/lint/util.sh
Normal 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"
|
||||||
|
}
|
@@ -1,9 +1,16 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
has_bat=0
|
||||||
|
if [ -d /sys/class/power_supply/BAT0/ ]
|
||||||
|
then
|
||||||
|
has_bat=1
|
||||||
|
fi
|
||||||
|
|
||||||
has_ec=0
|
has_ec=0
|
||||||
if ./ectool.sh info 2> /dev/null
|
if ./scripts/ectool.sh info 2> /dev/null
|
||||||
then
|
then
|
||||||
has_ec=1
|
has_ec=1
|
||||||
fi
|
fi
|
||||||
@@ -27,7 +34,10 @@ do
|
|||||||
if [ "${header}" == "1" ]
|
if [ "${header}" == "1" ]
|
||||||
then
|
then
|
||||||
F="Time "
|
F="Time "
|
||||||
F="${F}\tBAT W"
|
if [ "${has_bat}" == "1" ]
|
||||||
|
then
|
||||||
|
F="${F}\tBAT W"
|
||||||
|
fi
|
||||||
F="${F}\tCPU W"
|
F="${F}\tCPU W"
|
||||||
F="${F}\tCPU PL1"
|
F="${F}\tCPU PL1"
|
||||||
F="${F}\tCPU PL2"
|
F="${F}\tCPU PL2"
|
||||||
@@ -50,25 +60,28 @@ do
|
|||||||
else
|
else
|
||||||
F="$(date "+%T")"
|
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
|
sleep 1
|
||||||
|
|
||||||
uV="$(cat /sys/class/power_supply/BAT0/voltage_now)"
|
if [ "${has_bat}" == "1" ]
|
||||||
V="$(echo "${uV}/1000000" | bc -lq)"
|
then
|
||||||
uA="$(cat /sys/class/power_supply/BAT0/current_now)"
|
uV="$(cat /sys/class/power_supply/BAT0/voltage_now)"
|
||||||
A="$(echo "${uA}/1000000" | bc -lq)"
|
V="$(echo "${uV}/1000000" | bc -lq)"
|
||||||
bat_W="$(echo "${V} * ${A}" | bc -lq)"
|
uA="$(cat /sys/class/power_supply/BAT0/current_now)"
|
||||||
F="${F}\t$(printf "%.2f" "${bat_W}")"
|
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)"
|
W="$(echo "(${E} - ${last_E})/1000000" | bc -lq)"
|
||||||
F="${F}\t$(printf "%.1f" "${W}")"
|
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)"
|
PL1_W="$(echo "${PL1_uW}/1000000" | bc -lq)"
|
||||||
F="${F}\t$(printf "%.1f" "${PL1_W}")"
|
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)"
|
PL2_W="$(echo "${PL2_uW}/1000000" | bc -lq)"
|
||||||
F="${F}\t$(printf "%.1f" "${PL2_W}")"
|
F="${F}\t$(printf "%.1f" "${PL2_W}")"
|
||||||
|
|
11
scripts/spatch.sh
Executable file
11
scripts/spatch.sh
Executable 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/
|
@@ -1,27 +1,5 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
CC=sdcc -mmcs51 --model-large --code-size $(CODE_SIZE) --xram-size $(SRAM_SIZE) --Werror
|
arch-y += arch.c
|
||||||
OBJ=$(patsubst src/%.c,$(BUILD)/%.rel,$(SRC))
|
arch-y += delay.c
|
||||||
|
arch-y += time.c
|
||||||
# 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 $<
|
|
||||||
|
@@ -15,8 +15,8 @@ void delay_ticks(uint16_t ticks) {
|
|||||||
|
|
||||||
// Start timer in mode 1
|
// Start timer in mode 1
|
||||||
TMOD = (TMOD & 0x0F) | 0x10;
|
TMOD = (TMOD & 0x0F) | 0x10;
|
||||||
TH1 = (unsigned char)(value >> 8);
|
TH1 = (uint8_t)(value >> 8);
|
||||||
TL1 = (unsigned char)value;
|
TL1 = (uint8_t)value;
|
||||||
TR1 = 1;
|
TR1 = 1;
|
||||||
|
|
||||||
// Wait until complete
|
// 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
|
// This loops through delays of one ms in order to avoid overflow
|
||||||
void delay_ms(int ms) {
|
void delay_ms(uint8_t ms) {
|
||||||
for (int i = 0; i < ms; i++) {
|
for (uint8_t i = ms; i != 0; i--) {
|
||||||
delay_us(1000);
|
delay_us(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,14 +9,12 @@ void delay_ticks(uint16_t ticks);
|
|||||||
|
|
||||||
// 1 us * 9.2 MHz / 12 is 69/90
|
// 1 us * 9.2 MHz / 12 is 69/90
|
||||||
// Warning: this will round to the nearest tick
|
// Warning: this will round to the nearest tick
|
||||||
#define delay_us(X) \
|
#define delay_us(X) delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89UL) / 90UL));
|
||||||
delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89UL) / 90UL));
|
|
||||||
|
|
||||||
// 1 ns * 9.2 MHz / 12 is 69/90000
|
// 1 ns * 9.2 MHz / 12 is 69/90000
|
||||||
// Warning: this will round to the nearest tick
|
// Warning: this will round to the nearest tick
|
||||||
#define delay_ns(X) \
|
#define delay_ns(X) delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89999UL) / 90000UL));
|
||||||
delay_ticks((uint16_t)((((uint32_t)(X)) * 69UL + 89999UL) / 90000UL));
|
|
||||||
|
void delay_ms(uint8_t ms);
|
||||||
void delay_ms(int ms);
|
|
||||||
|
|
||||||
#endif // _ARCH_DELAY_H
|
#endif // _ARCH_DELAY_H
|
||||||
|
@@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint16_t systick_t;
|
||||||
|
|
||||||
void time_init(void);
|
void time_init(void);
|
||||||
uint32_t time_get(void);
|
systick_t time_get(void);
|
||||||
|
|
||||||
#endif // _ARCH_TIME_H
|
#endif // _ARCH_TIME_H
|
||||||
|
@@ -3,23 +3,34 @@
|
|||||||
// Uses timer 0 to keep track of global time
|
// Uses timer 0 to keep track of global time
|
||||||
|
|
||||||
#include <8051.h>
|
#include <8051.h>
|
||||||
|
|
||||||
#include <arch/time.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) {
|
void timer_0(void) __interrupt(1) {
|
||||||
|
// Hardware automatically clears the the interrupt
|
||||||
|
|
||||||
// Stop timer
|
// Stop timer
|
||||||
TR0 = 0;
|
TR0 = 0;
|
||||||
|
|
||||||
time_overflows++;
|
time_overflows++;
|
||||||
|
|
||||||
// Start timer
|
// Reload the values
|
||||||
TH0 = 0xFD;
|
TH0 = TIMER_RELOAD >> 8;
|
||||||
TL0 = 0x01;
|
TL0 = TIMER_RELOAD & 0xFF;
|
||||||
|
|
||||||
|
// Restart the timer
|
||||||
TR0 = 1;
|
TR0 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up Timer 0 as the system tick.
|
||||||
|
*/
|
||||||
void time_init(void) __critical {
|
void time_init(void) __critical {
|
||||||
// Stop the timer
|
// Stop the timer
|
||||||
TR0 = 0;
|
TR0 = 0;
|
||||||
@@ -27,17 +38,20 @@ void time_init(void) __critical {
|
|||||||
|
|
||||||
time_overflows = 0;
|
time_overflows = 0;
|
||||||
|
|
||||||
// Enable timer interrupts
|
// Enable the interrupt
|
||||||
ET0 = 1;
|
ET0 = 1;
|
||||||
|
|
||||||
// Start timer in mode 1
|
// Set the timer to mode 1 (16-bit timer)
|
||||||
// (65536 - 64769) / (9.2 MHz / 12) = ~1 ms interval
|
|
||||||
TMOD = (TMOD & 0xF0) | 0x01;
|
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;
|
TR0 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t time_get(void) __critical {
|
systick_t time_get(void) __critical {
|
||||||
return time_overflows;
|
return time_overflows;
|
||||||
}
|
}
|
||||||
|
58
src/arch/8051/toolchain.mk
Normal file
58
src/arch/8051/toolchain.mk
Normal 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)
|
@@ -1,29 +1,6 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
CC=avr-gcc -mmcu=$(EC)
|
arch-y += gpio.c
|
||||||
CFLAGS+=-Os -fstack-usage -Wall -Werror -Wl,--gc-sections -Wl,-u,vfprintf -lprintf_flt
|
arch-y += i2c.c
|
||||||
OBJ=$(patsubst src/%.c,$(BUILD)/%.o,$(SRC))
|
arch-y += i2c_slave.c
|
||||||
|
arch-y += uart.c
|
||||||
# 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 $<
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <arch/gpio.h>
|
#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) {
|
if (*gpio->ddr & gpio->value) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} 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) {
|
if (value) {
|
||||||
*gpio->ddr |= gpio->value;
|
*gpio->ddr |= gpio->value;
|
||||||
} else {
|
} 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) {
|
if (*gpio->pin & gpio->value) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} 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) {
|
if (value) {
|
||||||
*gpio->port |= gpio->value;
|
*gpio->port |= gpio->value;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -6,81 +6,93 @@
|
|||||||
|
|
||||||
#include <board/cpu.h>
|
#include <board/cpu.h>
|
||||||
#include <common/i2c.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) {
|
int16_t i2c_start(struct I2C *const i2c, uint8_t addr, bool read) {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
|
|
||||||
// reset TWI control register
|
// reset TWI control register
|
||||||
TWCR = 0;
|
TWCR = 0;
|
||||||
// transmit START condition
|
// transmit START condition
|
||||||
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
TWCR = BIT(TWINT) | BIT(TWSTA) | BIT(TWEN);
|
||||||
// wait for end of transmission
|
// wait for end of transmission
|
||||||
count = TIMEOUT;
|
count = TIMEOUT;
|
||||||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
|
while (!(TWCR & BIT(TWINT)) && count > 0)
|
||||||
if (count == 0) return -1;
|
count -= 1;
|
||||||
|
if (count == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
// check if the start condition was successfully transmitted
|
// check if the start condition was successfully transmitted
|
||||||
if((TWSR & 0xF8) != TW_START) return -1;
|
if ((TWSR & 0xF8) != TW_START)
|
||||||
|
return -1;
|
||||||
|
|
||||||
// load slave addr into data register
|
// load slave addr into data register
|
||||||
TWDR = ((addr << 1) | read);
|
TWDR = ((addr << 1) | read);
|
||||||
// start transmission of addr
|
// start transmission of addr
|
||||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
TWCR = BIT(TWINT) | BIT(TWEN);
|
||||||
// wait for end of transmission
|
// wait for end of transmission
|
||||||
count = TIMEOUT;
|
count = TIMEOUT;
|
||||||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
|
while (!(TWCR & BIT(TWINT)) && count > 0)
|
||||||
if (count == 0) return -1;
|
count -= 1;
|
||||||
|
if (count == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
// check if the device has acknowledged the READ / WRITE mode
|
// check if the device has acknowledged the READ / WRITE mode
|
||||||
uint8_t twst = TW_STATUS & 0xF8;
|
uint8_t twst = TW_STATUS;
|
||||||
if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) return -1;
|
if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK))
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_stop(struct I2C * i2c) {
|
void i2c_stop(struct I2C *const i2c) {
|
||||||
// transmit STOP condition
|
// transmit STOP condition
|
||||||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
TWCR = BIT(TWINT) | BIT(TWEN) | BIT(TWSTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_write(struct I2C * i2c, uint8_t * data, int length) {
|
int16_t i2c_write(struct I2C *const i2c, const uint8_t *const data, uint16_t length) {
|
||||||
int i;
|
uint16_t i;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
// load data into data register
|
// load data into data register
|
||||||
TWDR = data[i];
|
TWDR = data[i];
|
||||||
// start transmission of data
|
// start transmission of data
|
||||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
TWCR = BIT(TWINT) | BIT(TWEN);
|
||||||
// wait for end of transmission
|
// wait for end of transmission
|
||||||
uint32_t count = TIMEOUT;
|
uint32_t count = TIMEOUT;
|
||||||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
|
while (!(TWCR & BIT(TWINT)) && count > 0)
|
||||||
// timed out
|
count -= 1;
|
||||||
if (count == 0) return -1;
|
// timed out
|
||||||
// failed to receive ack
|
if (count == 0)
|
||||||
if((TWSR & 0xF8) != TW_MT_DATA_ACK) return -1;
|
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) {
|
int16_t i2c_read(struct I2C *const i2c, uint8_t *const data, uint16_t length) {
|
||||||
int i;
|
uint16_t i;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
if ((i + 1) < length) {
|
if ((i + 1) < length) {
|
||||||
// start TWI module and acknowledge data after reception
|
// start TWI module and acknowledge data after reception
|
||||||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
|
TWCR = BIT(TWINT) | BIT(TWEN) | BIT(TWEA);
|
||||||
} else {
|
} else {
|
||||||
// start receiving without acknowledging reception
|
// start receiving without acknowledging reception
|
||||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
TWCR = BIT(TWINT) | BIT(TWEN);
|
||||||
}
|
}
|
||||||
// wait for end of transmission
|
// wait for end of transmission
|
||||||
uint32_t count = TIMEOUT;
|
uint32_t count = TIMEOUT;
|
||||||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1;
|
while (!(TWCR & BIT(TWINT)) && count > 0)
|
||||||
if (count == 0) return -1;
|
count -= 1;
|
||||||
// return received data from TWDR
|
if (count == 0)
|
||||||
data[i] = TWDR;
|
return -1;
|
||||||
}
|
// return received data from TWDR
|
||||||
|
data[i] = TWDR;
|
||||||
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@@ -9,81 +9,89 @@
|
|||||||
|
|
||||||
#include <board/cpu.h>
|
#include <board/cpu.h>
|
||||||
#include <arch/i2c_slave.h>
|
#include <arch/i2c_slave.h>
|
||||||
|
#include <common/macro.h>
|
||||||
|
|
||||||
static void (* volatile i2c_slave_new_cb)() = NULL;
|
// uncrustify:off
|
||||||
static void (* volatile i2c_slave_recv_cb)(uint8_t) = NULL;
|
static void (*volatile i2c_slave_new_cb)() = NULL;
|
||||||
static uint8_t (* volatile i2c_slave_send_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)()){
|
void i2c_slave_init(
|
||||||
// ensure correct behavior by stopping before changing callbacks or address
|
uint8_t address,
|
||||||
i2c_slave_stop();
|
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
|
// clear interrupts
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
// setup callbacks
|
// setup callbacks
|
||||||
i2c_slave_new_cb = new_cb;
|
i2c_slave_new_cb = new_cb;
|
||||||
i2c_slave_recv_cb = recv_cb;
|
i2c_slave_recv_cb = recv_cb;
|
||||||
i2c_slave_send_cb = send_cb;
|
i2c_slave_send_cb = send_cb;
|
||||||
// load address into TWI address register
|
// load address into TWI address register
|
||||||
TWAR = (address << 1);
|
TWAR = (address << 1);
|
||||||
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
|
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
|
||||||
TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
|
TWCR = BIT(TWIE) | BIT(TWEA) | BIT(TWINT) | BIT(TWEN);
|
||||||
|
|
||||||
// set interrupts
|
// set interrupts
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_slave_stop(){
|
void i2c_slave_stop(void) {
|
||||||
// clear interrupts
|
// clear interrupts
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
// clear acknowledge and enable bits
|
// clear acknowledge and enable bits
|
||||||
TWCR &= ~((1<<TWEA) | (1<<TWEN));
|
TWCR &= ~(BIT(TWEA) | BIT(TWEN));
|
||||||
// clear address
|
// clear address
|
||||||
TWAR = 0;
|
TWAR = 0;
|
||||||
// remove callbacks
|
// remove callbacks
|
||||||
i2c_slave_new_cb = NULL;
|
i2c_slave_new_cb = NULL;
|
||||||
i2c_slave_recv_cb = NULL;
|
i2c_slave_recv_cb = NULL;
|
||||||
i2c_slave_send_cb = NULL;
|
i2c_slave_send_cb = NULL;
|
||||||
|
|
||||||
// set interrupts
|
// set interrupts
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
ISR(TWI_vect) {
|
ISR(TWI_vect) {
|
||||||
uint8_t status = TW_STATUS;
|
uint8_t status = TW_STATUS;
|
||||||
switch(status) {
|
switch (status) {
|
||||||
case TW_SR_SLA_ACK:
|
case TW_SR_SLA_ACK:
|
||||||
// master has started a new transaction, call the new callback
|
// master has started a new transaction, call the new callback
|
||||||
if (i2c_slave_new_cb != NULL) {
|
if (i2c_slave_new_cb != NULL) {
|
||||||
i2c_slave_new_cb();
|
i2c_slave_new_cb();
|
||||||
}
|
}
|
||||||
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
|
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
|
||||||
break;
|
break;
|
||||||
case TW_SR_DATA_ACK:
|
case TW_SR_DATA_ACK:
|
||||||
// received data from master, call the receive callback
|
// received data from master, call the receive callback
|
||||||
if(i2c_slave_send_cb != NULL){
|
if (i2c_slave_send_cb != NULL) {
|
||||||
i2c_slave_recv_cb(TWDR);
|
i2c_slave_recv_cb(TWDR);
|
||||||
}
|
}
|
||||||
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
|
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
|
||||||
break;
|
break;
|
||||||
case TW_ST_SLA_ACK:
|
case TW_ST_SLA_ACK:
|
||||||
case TW_ST_DATA_ACK:
|
case TW_ST_DATA_ACK:
|
||||||
// master is requesting data, call the send callback
|
// master is requesting data, call the send callback
|
||||||
if(i2c_slave_recv_cb != NULL) {
|
if (i2c_slave_recv_cb != NULL) {
|
||||||
TWDR = i2c_slave_send_cb();
|
TWDR = i2c_slave_send_cb();
|
||||||
}
|
}
|
||||||
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
|
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
|
||||||
break;
|
break;
|
||||||
case TW_BUS_ERROR:
|
case TW_BUS_ERROR:
|
||||||
// some sort of erroneous state, prepare TWI to be readdressed
|
// some sort of erroneous state, prepare TWI to be readdressed
|
||||||
printf("TWI_vect bus error\n");
|
printf("TWI_vect bus error\n");
|
||||||
TWCR = 0;
|
TWCR = 0;
|
||||||
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
|
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
|
TWCR = BIT(TWIE) | BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,14 +3,16 @@
|
|||||||
#ifndef _ARCH_GPIO_H
|
#ifndef _ARCH_GPIO_H
|
||||||
#define _ARCH_GPIO_H
|
#define _ARCH_GPIO_H
|
||||||
|
|
||||||
|
#include <common/macro.h>
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct Gpio {
|
struct Gpio {
|
||||||
volatile uint8_t * pin;
|
volatile uint8_t *pin;
|
||||||
volatile uint8_t * ddr;
|
volatile uint8_t *ddr;
|
||||||
volatile uint8_t * port;
|
volatile uint8_t *port;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -18,12 +20,12 @@ struct Gpio {
|
|||||||
.pin = &PIN ## BLOCK, \
|
.pin = &PIN ## BLOCK, \
|
||||||
.ddr = &DDR ## BLOCK, \
|
.ddr = &DDR ## BLOCK, \
|
||||||
.port = &PORT ## BLOCK, \
|
.port = &PORT ## BLOCK, \
|
||||||
.value = (1 << NUMBER), \
|
.value = BIT(NUMBER), \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gpio_get(struct Gpio * gpio);
|
bool gpio_get(const struct Gpio *const gpio);
|
||||||
void gpio_set(struct Gpio * gpio, bool value);
|
void gpio_set(struct Gpio *const gpio, bool value);
|
||||||
bool gpio_get_dir(struct Gpio * gpio);
|
bool gpio_get_dir(const struct Gpio *const gpio);
|
||||||
void gpio_set_dir(struct Gpio * gpio, bool value);
|
void gpio_set_dir(struct Gpio *const gpio, bool value);
|
||||||
|
|
||||||
#endif // _ARCH_GPIO_H
|
#endif // _ARCH_GPIO_H
|
||||||
|
@@ -3,7 +3,12 @@
|
|||||||
#ifndef _ARCH_I2C_SLAVE_H
|
#ifndef _ARCH_I2C_SLAVE_H
|
||||||
#define _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_init(
|
||||||
void i2c_slave_stop();
|
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
|
#endif // _ARCH_I2C_SLAVE_H
|
||||||
|
@@ -6,12 +6,12 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct Uart {
|
struct Uart {
|
||||||
volatile uint8_t * a;
|
volatile uint8_t *a;
|
||||||
volatile uint8_t * b;
|
volatile uint8_t *b;
|
||||||
volatile uint8_t * c;
|
volatile uint8_t *c;
|
||||||
volatile uint8_t * data;
|
volatile uint8_t *data;
|
||||||
volatile uint8_t * baud_l;
|
volatile uint8_t *baud_l;
|
||||||
volatile uint8_t * baud_h;
|
volatile uint8_t *baud_h;
|
||||||
uint8_t a_read;
|
uint8_t a_read;
|
||||||
uint8_t a_write;
|
uint8_t a_write;
|
||||||
uint8_t a_init;
|
uint8_t a_init;
|
||||||
@@ -19,18 +19,18 @@ struct Uart {
|
|||||||
uint8_t c_init;
|
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();
|
int16_t uart_count(void);
|
||||||
struct Uart * uart_new(int num);
|
struct Uart *uart_new(int16_t num);
|
||||||
|
|
||||||
unsigned char uart_can_read(struct Uart * uart);
|
uint8_t uart_can_read(struct Uart *const uart);
|
||||||
unsigned char uart_can_write(struct Uart * uart);
|
uint8_t uart_can_write(struct Uart *const uart);
|
||||||
|
|
||||||
unsigned char uart_read(struct Uart * uart);
|
uint8_t uart_read(struct Uart *const uart);
|
||||||
void uart_write(struct Uart * uart, unsigned char data);
|
void uart_write(struct Uart *const uart, uint8_t data);
|
||||||
|
|
||||||
extern struct Uart * uart_stdio;
|
extern struct Uart *uart_stdio;
|
||||||
void uart_stdio_init(int num, unsigned long baud);
|
void uart_stdio_init(int16_t num, uint32_t baud);
|
||||||
|
|
||||||
#endif // _ARCH_UART_H
|
#endif // _ARCH_UART_H
|
||||||
|
49
src/arch/avr/toolchain.mk
Normal file
49
src/arch/avr/toolchain.mk
Normal 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)
|
@@ -22,29 +22,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__AVR_ATmega328P__)
|
#if defined(__AVR_ATmega328P__)
|
||||||
static struct Uart UARTS[] = {
|
static struct Uart UARTS[] = {
|
||||||
UART(0)
|
UART(0)
|
||||||
};
|
};
|
||||||
#elif defined(__AVR_ATmega32U4__)
|
#elif defined(__AVR_ATmega32U4__)
|
||||||
static struct Uart UARTS[] = {
|
static struct Uart UARTS[] = {
|
||||||
UART(1)
|
UART(1)
|
||||||
};
|
};
|
||||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
static struct Uart UARTS[] = {
|
static struct Uart UARTS[] = {
|
||||||
UART(0),
|
UART(0),
|
||||||
UART(1),
|
UART(1),
|
||||||
UART(2),
|
UART(2),
|
||||||
UART(3)
|
UART(3)
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
#error "Could not find UART definitions"
|
#error "Could not find UART definitions"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int uart_count() {
|
int16_t uart_count(void) {
|
||||||
return sizeof(UARTS)/sizeof(struct Uart);
|
return sizeof(UARTS) / sizeof(struct Uart);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Uart * uart_new(int num) {
|
struct Uart *uart_new(int16_t num) {
|
||||||
if (num < uart_count()) {
|
if (num < uart_count()) {
|
||||||
return &UARTS[num];
|
return &UARTS[num];
|
||||||
} else {
|
} else {
|
||||||
@@ -52,49 +52,49 @@ struct Uart * uart_new(int num) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_init(struct Uart * uart, unsigned long baud) {
|
void uart_init(struct Uart *const uart, uint32_t baud) {
|
||||||
unsigned long baud_prescale = (F_CPU / (baud * 16UL)) - 1;
|
uint32_t baud_prescale = (F_CPU / (baud * 16UL)) - 1;
|
||||||
*(uart->baud_h) = (uint8_t)(baud_prescale>>8);
|
*(uart->baud_h) = (uint8_t)(baud_prescale >> 8);
|
||||||
*(uart->baud_l) = (uint8_t)(baud_prescale);
|
*(uart->baud_l) = (uint8_t)(baud_prescale);
|
||||||
*(uart->a) = uart->a_init;
|
*(uart->a) = uart->a_init;
|
||||||
*(uart->b) = uart->b_init;
|
*(uart->b) = uart->b_init;
|
||||||
*(uart->c) = uart->c_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;
|
return (*(uart->a)) & uart->a_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char uart_read(struct Uart * uart) {
|
uint8_t uart_read(struct Uart *const uart) {
|
||||||
while (!uart_can_read(uart)) ;
|
while (!uart_can_read(uart)) {}
|
||||||
return *(uart->data);
|
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;
|
return (*(uart->a)) & uart->a_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_write(struct Uart * uart, unsigned char data) {
|
void uart_write(struct Uart *const uart, uint8_t data) {
|
||||||
while (!uart_can_write(uart)) ;
|
while (!uart_can_write(uart)) {}
|
||||||
*(uart->data) = data;
|
*(uart->data) = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Uart * uart_stdio = NULL;
|
struct Uart *uart_stdio = NULL;
|
||||||
|
|
||||||
int uart_stdio_get(FILE * stream) {
|
int16_t uart_stdio_get(FILE *stream) {
|
||||||
return (int)uart_read(uart_stdio);
|
return (int16_t)uart_read(uart_stdio);
|
||||||
}
|
}
|
||||||
|
|
||||||
int uart_stdio_put(char data, FILE * stream) {
|
int16_t uart_stdio_put(char data, FILE *stream) {
|
||||||
uart_write(uart_stdio, (unsigned char)data);
|
uart_write(uart_stdio, (uint8_t)data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE uart_stdio_file = FDEV_SETUP_STREAM(uart_stdio_put, uart_stdio_get, _FDEV_SETUP_RW);
|
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) {
|
void uart_stdio_init(int16_t num, uint32_t baud) {
|
||||||
struct Uart * uart = uart_new(num);
|
struct Uart *uart = uart_new(num);
|
||||||
if(uart != NULL) {
|
if (uart != NULL) {
|
||||||
uart_init(uart, baud);
|
uart_init(uart, baud);
|
||||||
uart_stdio = uart;
|
uart_stdio = uart;
|
||||||
stdin = stdout = stderr = &uart_stdio_file;
|
stdin = stdout = stderr = &uart_stdio_file;
|
||||||
|
@@ -4,19 +4,20 @@
|
|||||||
|
|
||||||
#include <common/i2c.h>
|
#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);
|
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);
|
return i2c_set(NULL, address, command, (uint8_t *)&data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_debug(void) {
|
void battery_debug(void) {
|
||||||
uint16_t data = 0;
|
uint16_t data = 0;
|
||||||
int res = 0;
|
int16_t res = 0;
|
||||||
|
|
||||||
#define command(N, A, V) { \
|
#define command(N, A, V) \
|
||||||
|
{ \
|
||||||
printf(#N ": "); \
|
printf(#N ": "); \
|
||||||
res = smbus_read(A, V, &data); \
|
res = smbus_read(A, V, &data); \
|
||||||
if (res < 0) { \
|
if (res < 0) { \
|
||||||
@@ -45,5 +46,5 @@ void battery_debug(void) {
|
|||||||
command(ProchotOption1, 0x09, 0x3D);
|
command(ProchotOption1, 0x09, 0x3D);
|
||||||
command(ProchotStatus, 0x09, 0x3A);
|
command(ProchotStatus, 0x09, 0x3A);
|
||||||
|
|
||||||
#undef command
|
#undef command
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,12 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# 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*)
|
PORT=$(wildcard /dev/ttyACM*)
|
||||||
CONSOLE_BAUD=1000000
|
CONSOLE_BAUD=1000000
|
||||||
@@ -10,4 +16,4 @@ console:
|
|||||||
sudo tio -b $(CONSOLE_BAUD) $(PORT)
|
sudo tio -b $(CONSOLE_BAUD) $(PORT)
|
||||||
|
|
||||||
flash: $(BUILD)/ec.ihx
|
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
|
||||||
|
@@ -5,8 +5,8 @@
|
|||||||
#include <board/cpu.h>
|
#include <board/cpu.h>
|
||||||
#include <board/i2c.h>
|
#include <board/i2c.h>
|
||||||
|
|
||||||
void i2c_init(unsigned long baud) {
|
void i2c_init(uint32_t baud) {
|
||||||
TWAR = 0;
|
TWAR = 0;
|
||||||
TWBR = (uint8_t)(((F_CPU / baud) - 16 ) / 2);
|
TWBR = (uint8_t)(((F_CPU / baud) - 16) / 2);
|
||||||
TWCR = 0;
|
TWCR = 0;
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
#ifndef _BOARD_I2C_H
|
#ifndef _BOARD_I2C_H
|
||||||
#define _BOARD_I2C_H
|
#define _BOARD_I2C_H
|
||||||
|
|
||||||
void i2c_init(unsigned long baud);
|
void i2c_init(uint32_t baud);
|
||||||
|
|
||||||
#endif // _BOARD_I2C_H
|
#endif // _BOARD_I2C_H
|
||||||
|
@@ -12,7 +12,7 @@ void init(void) {
|
|||||||
struct Gpio LED = GPIO(B, 7);
|
struct Gpio LED = GPIO(B, 7);
|
||||||
|
|
||||||
//TODO: .h file
|
//TODO: .h file
|
||||||
void parallel_main(void);
|
int parallel_main(void);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
init();
|
init();
|
||||||
|
@@ -99,47 +99,51 @@ enum ParallelState {
|
|||||||
// Parallel struct definition
|
// Parallel struct definition
|
||||||
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
|
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
|
||||||
struct Parallel {
|
struct Parallel {
|
||||||
#define PIN(N, P) struct Gpio * N;
|
#define PIN(N, P) struct Gpio *N;
|
||||||
PINS
|
PINS
|
||||||
#undef PIN
|
#undef PIN
|
||||||
enum ParallelState state;
|
enum ParallelState state;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parallel struct instance
|
// Parallel struct instance
|
||||||
static struct Parallel PORT = {
|
static struct Parallel PORT = {
|
||||||
#define PIN(N, P) .N = &GPIOS[P - 1],
|
#define PIN(N, P) .N = &GPIOS[P - 1],
|
||||||
PINS
|
PINS
|
||||||
#undef PIN
|
#undef PIN
|
||||||
.state = PARALLEL_STATE_UNKNOWN,
|
.state = PARALLEL_STATE_UNKNOWN,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set port to all high-impedance inputs
|
// Set port to all high-impedance inputs
|
||||||
void parallel_hiz(struct Parallel * port) {
|
void parallel_hiz(struct Parallel *const port) {
|
||||||
#define PIN(N, P) \
|
#define PIN(N, P) \
|
||||||
gpio_set_dir(port->N, false); \
|
gpio_set_dir(port->N, false); \
|
||||||
gpio_set(port->N, false);
|
gpio_set(port->N, false);
|
||||||
PINS
|
PINS
|
||||||
#undef PIN
|
#undef PIN
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place all data lines in high or low impendance state
|
// Place all data lines in high or low impendance state
|
||||||
void parallel_data_dir(struct Parallel * port, bool dir) {
|
void parallel_data_dir(struct Parallel *const port, bool dir) {
|
||||||
#define DATA_BIT(B) gpio_set_dir(port->d ## B, dir);
|
#define DATA_BIT(B) gpio_set_dir(port->d##B, dir);
|
||||||
DATA_BITS
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
}
|
}
|
||||||
#define parallel_data_forward(P) parallel_data_dir(P, true)
|
#define parallel_data_forward(P) parallel_data_dir(P, true)
|
||||||
#define parallel_data_reverse(P) parallel_data_dir(P, false)
|
#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
|
// 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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set port to initial state required before being able to perform cycles
|
// 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);
|
parallel_hiz(port);
|
||||||
|
|
||||||
// nRESET: output on host, input on peripherals
|
// 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);
|
gpio_set_dir(port->wait_n, !host);
|
||||||
|
|
||||||
// Pull up data lines on host, leave floating on peripherals
|
// 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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
|
|
||||||
//TODO: something with straps
|
//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) {
|
if (port->state != state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case PARALLEL_STATE_UNKNOWN:
|
case PARALLEL_STATE_UNKNOWN:
|
||||||
return;
|
return;
|
||||||
case PARALLEL_STATE_HIZ:
|
case PARALLEL_STATE_HIZ:
|
||||||
parallel_hiz(port);
|
parallel_hiz(port);
|
||||||
break;
|
break;
|
||||||
case PARALLEL_STATE_HOST:
|
case PARALLEL_STATE_HOST:
|
||||||
parallel_reset(port, true);
|
parallel_reset(port, true);
|
||||||
break;
|
break;
|
||||||
case PARALLEL_STATE_PERIPHERAL:
|
case PARALLEL_STATE_PERIPHERAL:
|
||||||
parallel_reset(port, false);
|
parallel_reset(port, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
port->state = state;
|
port->state = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t parallel_read_data(struct Parallel * port) {
|
uint8_t parallel_read_data(struct Parallel *const port) {
|
||||||
uint8_t byte = 0;
|
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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
return byte;
|
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
|
// 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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: timeout
|
//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) {
|
if (!read) {
|
||||||
// Set write line low
|
// Set write line low
|
||||||
gpio_set(port->write_n, false);
|
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);
|
parallel_data_forward(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int16_t i;
|
||||||
uint8_t byte = 0;
|
uint8_t byte = 0;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
// Wait for peripheral to indicate it's ready for next cycle
|
// 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
|
// Set data strobe high
|
||||||
gpio_set(port->data_n, true);
|
gpio_set(port->data_n, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for peripheral to indicate it's ready for next cycle
|
// Wait for peripheral to indicate it's ready for next cycle
|
||||||
while (gpio_get(port->wait_n)) {}
|
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 write -> peripheral read
|
||||||
// host read -> peripheral write
|
// 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)) {
|
if (!gpio_get(port->reset_n)) {
|
||||||
// XXX: Give host some time to get ready
|
// XXX: Give host some time to get ready
|
||||||
_delay_ms(1);
|
_delay_ms(1);
|
||||||
return false;
|
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);
|
*read = gpio_get(port->write_n);
|
||||||
*addr = !gpio_get(port->addr_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);
|
parallel_write_data(port, *data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tell host we are ready for cycle
|
||||||
gpio_set(port->wait_n, true);
|
gpio_set(port->wait_n, true);
|
||||||
|
|
||||||
// Wait for host to finish strobe
|
// 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) {
|
if (*read) {
|
||||||
// Set data lines back to inputs
|
// 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);
|
*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);
|
gpio_set(port->wait_n, false);
|
||||||
|
|
||||||
return true;
|
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_INDAR1 = 0x05;
|
||||||
static uint8_t ADDRESS_INDDR = 0x08;
|
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 ZERO = 0x00;
|
||||||
static uint8_t SPI_ENABLE = 0xFE;
|
static uint8_t SPI_ENABLE = 0xFE;
|
||||||
static uint8_t SPI_DATA = 0xFD;
|
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
|
// Disable chip
|
||||||
int parallel_spi_reset(struct Parallel *port) {
|
int16_t parallel_spi_reset(struct Parallel *const port) {
|
||||||
int res;
|
int16_t res;
|
||||||
|
|
||||||
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
|
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);
|
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);
|
res = parallel_set_address(port, &ADDRESS_INDDR, 1);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
return parallel_write(port, &ZERO, 1);
|
return parallel_write(port, &ZERO, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable chip and read or write data
|
// Enable chip and read or write data
|
||||||
int parallel_spi_transaction(struct Parallel *port, uint8_t * data, int length, bool read) {
|
int16_t parallel_spi_transaction(
|
||||||
int res;
|
struct Parallel *const port,
|
||||||
|
uint8_t *const data,
|
||||||
|
int16_t length,
|
||||||
|
bool read
|
||||||
|
) {
|
||||||
|
int16_t res;
|
||||||
|
|
||||||
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
|
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);
|
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);
|
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);
|
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)
|
#define parallel_spi_write(P, D, L) parallel_spi_transaction(P, D, L, false)
|
||||||
|
|
||||||
// "Hardware" accelerated SPI programming, requires ECINDARs to be set
|
// "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 };
|
static uint8_t aai[6] = { 0xAD, 0, 0, 0, 0, 0 };
|
||||||
int res;
|
int16_t res;
|
||||||
int i;
|
int16_t i;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
for(i = 0; (i + 1) < length; i+=2) {
|
for (i = 0; (i + 1) < length; i += 2) {
|
||||||
// Disable chip to begin command
|
// Disable chip to begin command
|
||||||
res = parallel_spi_reset(port);
|
res = parallel_spi_reset(port);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
// If not initialized, the start address must be sent
|
// 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];
|
aai[5] = data[i + 1];
|
||||||
|
|
||||||
res = parallel_spi_write(port, aai, 6);
|
res = parallel_spi_write(port, aai, 6);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -392,36 +473,41 @@ int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, boo
|
|||||||
aai[2] = data[i + 1];
|
aai[2] = data[i + 1];
|
||||||
|
|
||||||
res = parallel_spi_write(port, aai, 3);
|
res = parallel_spi_write(port, aai, 3);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for SPI busy flag to clear
|
// Wait for SPI busy flag to clear
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Disable chip to begin command
|
// Disable chip to begin command
|
||||||
res = parallel_spi_reset(port);
|
res = parallel_spi_reset(port);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
status = 0x05;
|
status = 0x05;
|
||||||
res = parallel_spi_write(port, &status, 1);
|
res = parallel_spi_write(port, &status, 1);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
res = parallel_spi_read(port, &status, 1);
|
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;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int serial_transaction(uint8_t * data, int length, bool read) {
|
int16_t serial_transaction(uint8_t *const data, int16_t length, bool read) {
|
||||||
int i;
|
int16_t i;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
if (read) {
|
if (read) {
|
||||||
data[i] = (uint8_t)uart_read(uart_stdio);
|
data[i] = (uint8_t)uart_read(uart_stdio);
|
||||||
} else {
|
} 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)
|
#define serial_write(D, L) serial_transaction(D, L, false)
|
||||||
|
|
||||||
int parallel_main(void) {
|
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);
|
parallel_state(port, PARALLEL_STATE_HIZ);
|
||||||
|
|
||||||
static uint8_t data[128];
|
static uint8_t data[128];
|
||||||
char command;
|
char command;
|
||||||
int length;
|
int16_t length;
|
||||||
int i;
|
int16_t i;
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
bool set_address = false;
|
bool set_address = false;
|
||||||
bool program_aai = false;
|
bool program_aai = false;
|
||||||
|
|
||||||
unsigned char console_msg[] = "Entering console mode\n";
|
uint8_t console_msg[] = "Entering console mode\n";
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Read command and length
|
// Read command and length
|
||||||
res = serial_read(data, 2);
|
res = serial_read(data, 2);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
// Command is a character
|
// Command is a character
|
||||||
command = (char)data[0];
|
command = (char)data[0];
|
||||||
|
|
||||||
@@ -466,125 +553,185 @@ int parallel_main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Length is received data + 1
|
// Length is received data + 1
|
||||||
length = ((int)data[1]) + 1;
|
length = ((int16_t)data[1]) + 1;
|
||||||
// Truncate length to size of data
|
// Truncate length to size of data
|
||||||
if (length > sizeof(data)) length = sizeof(data);
|
if (length > sizeof(data))
|
||||||
|
length = sizeof(data);
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
// Buffer size
|
// Buffer size
|
||||||
case 'B':
|
case 'B':
|
||||||
// Fill buffer size - 1
|
// Fill buffer size - 1
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
data[i] = (uint8_t)(sizeof(data) - 1);
|
data[i] = (uint8_t)(sizeof(data) - 1);
|
||||||
} else {
|
} else {
|
||||||
data[i] = 0;
|
data[i] = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write data to serial
|
// Write data to serial
|
||||||
res = serial_write(data, length);
|
res = serial_write(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Debug console
|
// Debug console
|
||||||
case 'C':
|
case 'C':
|
||||||
parallel_state(port, PARALLEL_STATE_PERIPHERAL);
|
// Set parallel lines to peripheral mode
|
||||||
|
parallel_state(port, PARALLEL_STATE_PERIPHERAL);
|
||||||
|
|
||||||
serial_write(console_msg, sizeof(console_msg));
|
// Tell the user the console is ready
|
||||||
|
serial_write(console_msg, sizeof(console_msg));
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bool read = false;
|
bool read = false;
|
||||||
bool addr = false;
|
bool addr = false;
|
||||||
bool ret = parallel_peripheral_cycle(port, data, &read, &addr);
|
if (parallel_peripheral_cycle(port, data, &read, &addr)) {
|
||||||
|
if (!read && !addr) {
|
||||||
if (ret && !read && !addr) {
|
|
||||||
res = serial_write(data, 1);
|
res = serial_write(data, 1);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Echo
|
// Echo
|
||||||
case 'E':
|
case 'E':
|
||||||
// Read data from serial
|
// Read data from serial
|
||||||
res = serial_read(data, length);
|
res = serial_read(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
// Write data to serial
|
// Write data to serial
|
||||||
res = serial_write(data, length);
|
res = serial_write(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Read data
|
// Forced debug console (can be used on all firmware but may miss bytes)
|
||||||
case 'R':
|
case 'F':
|
||||||
parallel_state(port, PARALLEL_STATE_HOST);
|
serial_write(console_msg, sizeof(console_msg));
|
||||||
|
|
||||||
// Update parallel address if necessary
|
// We must be in host mode
|
||||||
if (set_address) {
|
parallel_state(port, PARALLEL_STATE_HOST);
|
||||||
res = parallel_set_address(port, &address, 1);
|
|
||||||
if (res < 0) goto err;
|
uint16_t head = 0;
|
||||||
set_address = false;
|
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
|
if (head == 0) {
|
||||||
res = parallel_read(port, data, length);
|
// Set head if necessary
|
||||||
if (res < 0) goto err;
|
head = tail;
|
||||||
|
continue;
|
||||||
// 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
|
while (head != tail) {
|
||||||
res = parallel_write(port, data, length);
|
head += 1;
|
||||||
if (res < 0) goto err;
|
if (head >= 256) {
|
||||||
|
head = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Send ACK of data length
|
// Read byte at head
|
||||||
data[0] = (uint8_t)(length - 1);
|
res = parallel_ecms_read(port, 0xF00 + head, data, 1);
|
||||||
res = serial_write(data, 1);
|
if (res < 0)
|
||||||
if (res < 0) goto err;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
EC=atmega32u4
|
board-y += main.c
|
||||||
|
|
||||||
|
EC=atmega
|
||||||
|
EC_VARIANT=atmega32u4
|
||||||
|
|
||||||
PORT=$(wildcard /dev/ttyACM*)
|
PORT=$(wildcard /dev/ttyACM*)
|
||||||
CONSOLE_BAUD=1000000
|
CONSOLE_BAUD=1000000
|
||||||
@@ -10,4 +13,4 @@ console:
|
|||||||
sudo tio -b $(CONSOLE_BAUD) $(PORT)
|
sudo tio -b $(CONSOLE_BAUD) $(PORT)
|
||||||
|
|
||||||
flash: $(BUILD)/ec.ihx
|
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
|
||||||
|
@@ -4,19 +4,20 @@
|
|||||||
|
|
||||||
#include <common/i2c.h>
|
#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);
|
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);
|
return i2c_set(NULL, address, command, (uint8_t *)&data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_debug(void) {
|
void battery_debug(void) {
|
||||||
uint16_t data = 0;
|
uint16_t data = 0;
|
||||||
int res = 0;
|
int16_t res = 0;
|
||||||
|
|
||||||
#define command(N, A, V) { \
|
#define command(N, A, V) \
|
||||||
|
{ \
|
||||||
printf(#N ": "); \
|
printf(#N ": "); \
|
||||||
res = smbus_read(A, V, &data); \
|
res = smbus_read(A, V, &data); \
|
||||||
if (res < 0) { \
|
if (res < 0) { \
|
||||||
@@ -45,5 +46,5 @@ void battery_debug(void) {
|
|||||||
command(ProchotOption1, 0x09, 0x3D);
|
command(ProchotOption1, 0x09, 0x3D);
|
||||||
command(ProchotStatus, 0x09, 0x3A);
|
command(ProchotStatus, 0x09, 0x3A);
|
||||||
|
|
||||||
#undef command
|
#undef command
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,12 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# 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*)
|
PORT=$(wildcard /dev/ttyACM*)
|
||||||
CONSOLE_BAUD=1000000
|
CONSOLE_BAUD=1000000
|
||||||
@@ -10,4 +16,4 @@ console:
|
|||||||
sudo tio -b $(CONSOLE_BAUD) $(PORT)
|
sudo tio -b $(CONSOLE_BAUD) $(PORT)
|
||||||
|
|
||||||
flash: $(BUILD)/ec.ihx
|
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
|
||||||
|
@@ -5,8 +5,8 @@
|
|||||||
#include <board/cpu.h>
|
#include <board/cpu.h>
|
||||||
#include <board/i2c.h>
|
#include <board/i2c.h>
|
||||||
|
|
||||||
void i2c_init(unsigned long baud) {
|
void i2c_init(uint32_t baud) {
|
||||||
TWAR = 0;
|
TWAR = 0;
|
||||||
TWBR = (uint8_t)(((F_CPU / baud) - 16 ) / 2);
|
TWBR = (uint8_t)(((F_CPU / baud) - 16) / 2);
|
||||||
TWCR = 0;
|
TWCR = 0;
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
#ifndef _BOARD_I2C_H
|
#ifndef _BOARD_I2C_H
|
||||||
#define _BOARD_I2C_H
|
#define _BOARD_I2C_H
|
||||||
|
|
||||||
void i2c_init(unsigned long baud);
|
void i2c_init(uint32_t baud);
|
||||||
|
|
||||||
#endif // _BOARD_I2C_H
|
#endif // _BOARD_I2C_H
|
||||||
|
@@ -12,7 +12,7 @@ void init(void) {
|
|||||||
struct Gpio LED = GPIO(B, 5);
|
struct Gpio LED = GPIO(B, 5);
|
||||||
|
|
||||||
//TODO: .h file
|
//TODO: .h file
|
||||||
void parallel_main(void);
|
int parallel_main(void);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
init();
|
init();
|
||||||
|
@@ -65,49 +65,53 @@ static struct Gpio GPIOS[13] = {
|
|||||||
GPIO(C, 0),
|
GPIO(C, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Parallel struct definition
|
// Parallel struct definition
|
||||||
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
|
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
|
||||||
struct Parallel {
|
struct Parallel {
|
||||||
#define PIN(N, P) struct Gpio * N;
|
#define PIN(N, P) struct Gpio *N;
|
||||||
PINS
|
PINS
|
||||||
#undef PIN
|
#undef PIN
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parallel struct instance
|
// Parallel struct instance
|
||||||
static struct Parallel PORT = {
|
static struct Parallel PORT = {
|
||||||
#define PIN(N, P) .N = &GPIOS[P - 1],
|
#define PIN(N, P) .N = &GPIOS[P - 1],
|
||||||
PINS
|
PINS
|
||||||
#undef PIN
|
#undef PIN
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set port to all high-impedance inputs
|
// Set port to all high-impedance inputs
|
||||||
void parallel_hiz(struct Parallel * port) {
|
void parallel_hiz(struct Parallel *const port) {
|
||||||
#define PIN(N, P) \
|
#define PIN(N, P) \
|
||||||
gpio_set_dir(port->N, false); \
|
gpio_set_dir(port->N, false); \
|
||||||
gpio_set(port->N, false);
|
gpio_set(port->N, false);
|
||||||
|
|
||||||
PINS
|
PINS
|
||||||
#undef PIN
|
#undef PIN
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place all data lines in high or low impendance state
|
// Place all data lines in high or low impendance state
|
||||||
void parallel_data_dir(struct Parallel * port, bool dir) {
|
void parallel_data_dir(struct Parallel *const port, bool dir) {
|
||||||
#define DATA_BIT(B) gpio_set_dir(port->d ## B, dir);
|
#define DATA_BIT(B) gpio_set_dir(port->d##B, dir);
|
||||||
DATA_BITS
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
}
|
}
|
||||||
#define parallel_data_forward(P) parallel_data_dir(P, true)
|
#define parallel_data_forward(P) parallel_data_dir(P, true)
|
||||||
#define parallel_data_reverse(P) parallel_data_dir(P, false)
|
#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
|
// 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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set port to initial state required before being able to perform cycles
|
// 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);
|
parallel_hiz(port);
|
||||||
|
|
||||||
// nRESET: output on host, input on peripherals
|
// 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);
|
gpio_set_dir(port->wait_n, !host);
|
||||||
|
|
||||||
// Pull up data lines on host, leave floating on peripherals
|
// 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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
|
|
||||||
//TODO: something with straps
|
//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;
|
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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
return byte;
|
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
|
// 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
|
DATA_BITS
|
||||||
#undef DATA_BIT
|
#undef DATA_BIT
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: timeout
|
//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) {
|
if (!read) {
|
||||||
// Set write line low
|
// Set write line low
|
||||||
gpio_set(port->write_n, false);
|
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);
|
parallel_data_forward(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int16_t i;
|
||||||
uint8_t byte = 0;
|
uint8_t byte = 0;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
// Wait for peripheral to indicate it's ready for next cycle
|
// 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 write -> peripheral read
|
||||||
// host read -> peripheral write
|
// 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)) {
|
if (!gpio_get(port->reset_n)) {
|
||||||
// XXX: Give host some time to get ready
|
// XXX: Give host some time to get ready
|
||||||
_delay_ms(1);
|
_delay_ms(1);
|
||||||
@@ -278,33 +301,44 @@ static uint8_t SPI_ENABLE = 0xFE;
|
|||||||
static uint8_t SPI_DATA = 0xFD;
|
static uint8_t SPI_DATA = 0xFD;
|
||||||
|
|
||||||
// Disable chip
|
// Disable chip
|
||||||
int parallel_spi_reset(struct Parallel *port) {
|
int16_t parallel_spi_reset(struct Parallel *const port) {
|
||||||
int res;
|
int16_t res;
|
||||||
|
|
||||||
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
|
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);
|
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);
|
res = parallel_set_address(port, &ADDRESS_INDDR, 1);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
return parallel_write(port, &ZERO, 1);
|
return parallel_write(port, &ZERO, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable chip and read or write data
|
// Enable chip and read or write data
|
||||||
int parallel_spi_transaction(struct Parallel *port, uint8_t * data, int length, bool read) {
|
int16_t parallel_spi_transaction(
|
||||||
int res;
|
struct Parallel *const port,
|
||||||
|
uint8_t *const data,
|
||||||
|
int16_t length,
|
||||||
|
bool read
|
||||||
|
) {
|
||||||
|
int16_t res;
|
||||||
|
|
||||||
res = parallel_set_address(port, &ADDRESS_INDAR1, 1);
|
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);
|
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);
|
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);
|
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)
|
#define parallel_spi_write(P, D, L) parallel_spi_transaction(P, D, L, false)
|
||||||
|
|
||||||
// "Hardware" accelerated SPI programming, requires ECINDARs to be set
|
// "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 };
|
static uint8_t aai[6] = { 0xAD, 0, 0, 0, 0, 0 };
|
||||||
int res;
|
int16_t res;
|
||||||
int i;
|
int16_t i;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
for(i = 0; (i + 1) < length; i+=2) {
|
for (i = 0; (i + 1) < length; i += 2) {
|
||||||
// Disable chip to begin command
|
// Disable chip to begin command
|
||||||
res = parallel_spi_reset(port);
|
res = parallel_spi_reset(port);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
// If not initialized, the start address must be sent
|
// 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];
|
aai[5] = data[i + 1];
|
||||||
|
|
||||||
res = parallel_spi_write(port, aai, 6);
|
res = parallel_spi_write(port, aai, 6);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -342,36 +383,41 @@ int parallel_spi_program(struct Parallel * port, uint8_t * data, int length, boo
|
|||||||
aai[2] = data[i + 1];
|
aai[2] = data[i + 1];
|
||||||
|
|
||||||
res = parallel_spi_write(port, aai, 3);
|
res = parallel_spi_write(port, aai, 3);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for SPI busy flag to clear
|
// Wait for SPI busy flag to clear
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Disable chip to begin command
|
// Disable chip to begin command
|
||||||
res = parallel_spi_reset(port);
|
res = parallel_spi_reset(port);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
status = 0x05;
|
status = 0x05;
|
||||||
res = parallel_spi_write(port, &status, 1);
|
res = parallel_spi_write(port, &status, 1);
|
||||||
if (res < 0) return res;
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
res = parallel_spi_read(port, &status, 1);
|
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;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int serial_transaction(uint8_t * data, int length, bool read) {
|
int16_t serial_transaction(uint8_t *const data, int16_t length, bool read) {
|
||||||
int i;
|
int16_t i;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
if (read) {
|
if (read) {
|
||||||
data[i] = (uint8_t)uart_read(uart_stdio);
|
data[i] = (uint8_t)uart_read(uart_stdio);
|
||||||
} else {
|
} 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_read(D, L) serial_transaction(D, L, true)
|
||||||
#define serial_write(D, L) serial_transaction(D, L, false)
|
#define serial_write(D, L) serial_transaction(D, L, false)
|
||||||
|
|
||||||
int parallel_main(void) {
|
int16_t parallel_main(void) {
|
||||||
int res = 0;
|
int16_t res = 0;
|
||||||
|
|
||||||
struct Parallel * port = &PORT;
|
struct Parallel *port = &PORT;
|
||||||
parallel_reset(port, true);
|
parallel_reset(port, true);
|
||||||
|
|
||||||
static uint8_t data[128];
|
static uint8_t data[128];
|
||||||
char command;
|
char command;
|
||||||
int length;
|
int16_t length;
|
||||||
int i;
|
int16_t i;
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
bool set_address = false;
|
bool set_address = false;
|
||||||
bool program_aai = false;
|
bool program_aai = false;
|
||||||
|
|
||||||
unsigned char console_msg[] = "Entering console mode\n";
|
uint8_t console_msg[] = "Entering console mode\n";
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Read command and length
|
// Read command and length
|
||||||
res = serial_read(data, 2);
|
res = serial_read(data, 2);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
// Command is a character
|
// Command is a character
|
||||||
command = (char)data[0];
|
command = (char)data[0];
|
||||||
|
|
||||||
@@ -416,120 +463,135 @@ int parallel_main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Length is received data + 1
|
// Length is received data + 1
|
||||||
length = ((int)data[1]) + 1;
|
length = ((int16_t)data[1]) + 1;
|
||||||
// Truncate length to size of data
|
// Truncate length to size of data
|
||||||
if (length > sizeof(data)) length = sizeof(data);
|
if (length > sizeof(data))
|
||||||
|
length = sizeof(data);
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
// Buffer size
|
// Buffer size
|
||||||
case 'B':
|
case 'B':
|
||||||
// Fill buffer size - 1
|
// Fill buffer size - 1
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
data[i] = (uint8_t)(sizeof(data) - 1);
|
data[i] = (uint8_t)(sizeof(data) - 1);
|
||||||
} else {
|
} else {
|
||||||
data[i] = 0;
|
data[i] = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write data to serial
|
// Write data to serial
|
||||||
res = serial_write(data, length);
|
res = serial_write(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Debug console
|
// Debug console
|
||||||
case 'C':
|
case 'C':
|
||||||
serial_write(console_msg, sizeof(console_msg));
|
serial_write(console_msg, sizeof(console_msg));
|
||||||
|
|
||||||
// Reconfigure as a peripheral
|
// Reconfigure as a peripheral
|
||||||
parallel_reset(port, false);
|
parallel_reset(port, false);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bool read = false;
|
bool read = false;
|
||||||
bool addr = false;
|
bool addr = false;
|
||||||
bool ret = parallel_peripheral_cycle(port, data, &read, &addr);
|
bool ret = parallel_peripheral_cycle(port, data, &read, &addr);
|
||||||
|
|
||||||
if (ret && !read && !addr) {
|
if (ret && !read && !addr) {
|
||||||
res = serial_write(data, 1);
|
res = serial_write(data, 1);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
}
|
goto err;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Echo
|
// Echo
|
||||||
case 'E':
|
case 'E':
|
||||||
// Read data from serial
|
// Read data from serial
|
||||||
res = serial_read(data, length);
|
res = serial_read(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
// Write data to serial
|
// Write data to serial
|
||||||
res = serial_write(data, length);
|
res = serial_write(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Read data
|
// Read data
|
||||||
case 'R':
|
case 'R':
|
||||||
// Update parallel address if necessary
|
// Update parallel address if necessary
|
||||||
if (set_address) {
|
if (set_address) {
|
||||||
res = parallel_set_address(port, &address, 1);
|
res = parallel_set_address(port, &address, 1);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
set_address = false;
|
goto err;
|
||||||
}
|
set_address = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Read data from parallel
|
// Read data from parallel
|
||||||
res = parallel_read(port, data, length);
|
res = parallel_read(port, data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
// Write data to serial
|
// Write data to serial
|
||||||
res = serial_write(data, length);
|
res = serial_write(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Accelerated program function
|
// Accelerated program function
|
||||||
case 'P':
|
case 'P':
|
||||||
// Read data from serial
|
// Read data from serial
|
||||||
res = serial_read(data, length);
|
res = serial_read(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
// Run accelerated programming function
|
// Run accelerated programming function
|
||||||
res = parallel_spi_program(port, data, length, program_aai);
|
res = parallel_spi_program(port, data, length, program_aai);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
program_aai = true;
|
goto err;
|
||||||
|
program_aai = true;
|
||||||
|
|
||||||
// Send ACK of data length
|
// Send ACK of data length
|
||||||
data[0] = (uint8_t)(length - 1);
|
data[0] = (uint8_t)(length - 1);
|
||||||
res = serial_write(data, 1);
|
res = serial_write(data, 1);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Write data
|
// Write data
|
||||||
case 'W':
|
case 'W':
|
||||||
// Read data from serial
|
// Read data from serial
|
||||||
res = serial_read(data, length);
|
res = serial_read(data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
// Update parallel address if necessary
|
// Update parallel address if necessary
|
||||||
if (set_address) {
|
if (set_address) {
|
||||||
res = parallel_set_address(port, &address, 1);
|
res = parallel_set_address(port, &address, 1);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
set_address = false;
|
goto err;
|
||||||
}
|
set_address = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Write data to parallel
|
// Write data to parallel
|
||||||
res = parallel_write(port, data, length);
|
res = parallel_write(port, data, length);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
// Send ACK of data length
|
// Send ACK of data length
|
||||||
data[0] = (uint8_t)(length - 1);
|
data[0] = (uint8_t)(length - 1);
|
||||||
res = serial_write(data, 1);
|
res = serial_write(data, 1);
|
||||||
if (res < 0) goto err;
|
if (res < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,14 +1,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <arch/time.h>
|
|
||||||
#include <board/battery.h>
|
|
||||||
#include <board/board.h>
|
#include <board/board.h>
|
||||||
#include <board/dgpu.h>
|
|
||||||
#include <board/gctrl.h>
|
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbc.h>
|
#include <board/kbc.h>
|
||||||
#include <board/peci.h>
|
|
||||||
#include <board/power.h>
|
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
|
||||||
extern uint8_t main_cycle;
|
extern uint8_t main_cycle;
|
||||||
@@ -20,10 +14,6 @@ void board_init(void) {
|
|||||||
gpio_set(&BKL_EN, true);
|
gpio_set(&BKL_EN, true);
|
||||||
// Enable camera
|
// Enable camera
|
||||||
gpio_set(&CCD_EN, true);
|
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
|
// Enable right USB port
|
||||||
gpio_set(&USB_PWR_EN_N, false);
|
gpio_set(&USB_PWR_EN_N, false);
|
||||||
// Assert SMI#, SCI#, and SWI#
|
// Assert SMI#, SCI#, and SWI#
|
||||||
@@ -32,45 +22,7 @@ void board_init(void) {
|
|||||||
gpio_set(&SWI_N, true);
|
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) {
|
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) {
|
if (main_cycle == 0) {
|
||||||
// Set keyboard LEDs
|
// Set keyboard LEDs
|
||||||
static uint8_t last_kbc_leds = 0;
|
static uint8_t last_kbc_leds = 0;
|
||||||
|
@@ -1,13 +1,21 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
EC=it8587e
|
board-y += board.c
|
||||||
|
board-y += gpio.c
|
||||||
|
|
||||||
# Add keymap to src
|
EC=ite
|
||||||
KEYMAP?=default
|
CONFIG_EC_ITE_IT8587E=y
|
||||||
SRC+=$(BOARD_DIR)/keymap/$(KEYMAP).c
|
CONFIG_EC_FLASH_SIZE_128K = y
|
||||||
|
|
||||||
# Set discrete GPU I2C bus
|
# Intel-based host
|
||||||
CFLAGS+=-DI2C_DGPU=I2C_1
|
CONFIG_PLATFORM_INTEL = y
|
||||||
|
|
||||||
|
# Include keyboard
|
||||||
|
KEYBOARD=15in_102
|
||||||
|
|
||||||
|
# Set keyboard LED mechanism
|
||||||
|
CONFIG_HAVE_KBLED = y
|
||||||
|
KBLED=rgb_pwm
|
||||||
|
|
||||||
# Set battery I2C bus
|
# Set battery I2C bus
|
||||||
CFLAGS+=-DI2C_SMBUS=I2C_0
|
CFLAGS+=-DI2C_SMBUS=I2C_0
|
||||||
@@ -17,41 +25,38 @@ CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
|||||||
|
|
||||||
# Set smart charger parameters
|
# Set smart charger parameters
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
-DCHARGER_ADAPTER_RSENSE=5 \
|
||||||
|
-DCHARGER_BATTERY_RSENSE=10 \
|
||||||
|
-DCHARGER_CHARGE_CURRENT=3072 \
|
||||||
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
||||||
-DCHARGER_INPUT_CURRENT=11800
|
-DCHARGER_INPUT_CURRENT=11800
|
||||||
|
|
||||||
# Set battery charging thresholds
|
|
||||||
CFLAGS+=\
|
|
||||||
-DBATTERY_START_THRESHOLD=0 \
|
|
||||||
-DBATTERY_END_THRESHOLD=100
|
|
||||||
|
|
||||||
# Set CPU power limits in watts
|
# Set CPU power limits in watts
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DPOWER_LIMIT_AC=180 \
|
-DPOWER_LIMIT_AC=180 \
|
||||||
-DPOWER_LIMIT_DC=28
|
-DPOWER_LIMIT_DC=45
|
||||||
|
|
||||||
# Custom fan curve
|
# Enable dGPU support
|
||||||
CFLAGS+=-DBOARD_HEATUP=5
|
CONFIG_HAVE_DGPU = y
|
||||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
CFLAGS += -DI2C_DGPU=I2C_1
|
||||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
|
||||||
|
# Fan configs
|
||||||
|
CFLAGS += -DFAN1_PWM=DCR2
|
||||||
|
CFLAGS += -DBOARD_FAN1_POINTS="\
|
||||||
FAN_POINT(60, 40), \
|
FAN_POINT(60, 40), \
|
||||||
FAN_POINT(65, 60), \
|
FAN_POINT(65, 60), \
|
||||||
FAN_POINT(70, 75), \
|
FAN_POINT(70, 75), \
|
||||||
FAN_POINT(75, 90), \
|
FAN_POINT(75, 90), \
|
||||||
FAN_POINT(80, 100) \
|
FAN_POINT(80, 100), \
|
||||||
"
|
"
|
||||||
|
|
||||||
# Enable DGPU support
|
CFLAGS += -DFAN2_PWM=DCR4
|
||||||
CFLAGS+=-DHAVE_DGPU=1
|
CFLAGS += -DBOARD_FAN2_POINTS="\
|
||||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
|
||||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
|
||||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
|
||||||
FAN_POINT(60, 40), \
|
FAN_POINT(60, 40), \
|
||||||
FAN_POINT(65, 60), \
|
FAN_POINT(65, 60), \
|
||||||
FAN_POINT(70, 75), \
|
FAN_POINT(70, 75), \
|
||||||
FAN_POINT(75, 90), \
|
FAN_POINT(75, 90), \
|
||||||
FAN_POINT(80, 100) \
|
FAN_POINT(80, 100), \
|
||||||
"
|
"
|
||||||
|
|
||||||
# Add system76 common code
|
# Add system76 common code
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <board/gpio.h>
|
#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 ACIN_N = GPIO(B, 6);
|
||||||
struct Gpio __code AC_PRESENT = GPIO(E, 7);
|
struct Gpio __code AC_PRESENT = GPIO(E, 7);
|
||||||
struct Gpio __code ALL_SYS_PWRGD = GPIO(C, 0);
|
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_PWR = GPIO(H, 5);
|
||||||
struct Gpio __code LED_SCROLL_N = GPIO(J, 3);
|
struct Gpio __code LED_SCROLL_N = GPIO(J, 3);
|
||||||
struct Gpio __code LID_SW_N = GPIO(D, 1);
|
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_CLKRUN_N = GPIO(H, 0); // renamed to ECCLKRUN#
|
||||||
struct Gpio __code PM_PWROK = GPIO(C, 6);
|
struct Gpio __code PM_PWROK = GPIO(C, 6);
|
||||||
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
|
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
|
||||||
struct Gpio __code PWR_SW_N = GPIO(D, 0);
|
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 SB_KBCRST_N = GPIO(E, 6);
|
||||||
struct Gpio __code SCI_N = GPIO(D, 4);
|
struct Gpio __code SCI_N = GPIO(D, 4);
|
||||||
struct Gpio __code SMI_N = GPIO(D, 3);
|
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 VA_EC_EN = GPIO(J, 0); // renamed to SLP_SUS_EC#
|
||||||
struct Gpio __code WLAN_EN = GPIO(J, 2);
|
struct Gpio __code WLAN_EN = GPIO(J, 2);
|
||||||
struct Gpio __code WLAN_PWR_EN = GPIO(B, 0);
|
struct Gpio __code WLAN_PWR_EN = GPIO(B, 0);
|
||||||
|
// uncrustify:on
|
||||||
|
|
||||||
void gpio_init() {
|
void gpio_init(void) {
|
||||||
// Enable LPC reset on GPD2
|
// Enable LPC reset on GPD2
|
||||||
GCR = 0x04;
|
GCR = 0x04;
|
||||||
|
|
||||||
// Set GPIO data
|
// Set GPIO data
|
||||||
// SYS_FAN
|
// SYS_FAN
|
||||||
GPDRA = (1 << 3);
|
GPDRA = BIT(3);
|
||||||
GPDRB = 0x00;
|
GPDRB = 0x00;
|
||||||
GPDRC = 0x00;
|
GPDRC = 0x00;
|
||||||
// PWR_BTN#, SCI#, SMI#
|
// PWR_BTN#, SCI#, SMI#
|
||||||
GPDRD = (1 << 5) | (1 << 4) | (1 << 3);
|
GPDRD = BIT(5) | BIT(4) | BIT(3);
|
||||||
GPDRE = 0x00;
|
GPDRE = 0x00;
|
||||||
// H_PECI
|
// H_PECI
|
||||||
GPDRF = (1 << 6);
|
GPDRF = BIT(6);
|
||||||
// AIRPLAN_LED#
|
// AIRPLAN_LED#
|
||||||
GPDRG = (1 << 6);
|
GPDRG = BIT(6);
|
||||||
GPDRH = 0x00;
|
GPDRH = 0x00;
|
||||||
GPDRI = 0x00;
|
GPDRI = 0x00;
|
||||||
// LED_CAP#, LED_NUM#, LED_SCROLL#, KBC_MUTE#
|
// 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
|
// Set GPIO control
|
||||||
// EC_PWM_LEDKB_P
|
// EC_PWM_LEDKB_P
|
||||||
@@ -101,11 +105,11 @@ void gpio_init() {
|
|||||||
// SMD_VGA_THERM
|
// SMD_VGA_THERM
|
||||||
GPCRC2 = GPIO_OUT;
|
GPCRC2 = GPIO_OUT;
|
||||||
// KB-SO16
|
// KB-SO16
|
||||||
GPCRC3 = GPIO_IN | GPIO_UP;
|
GPCRC3 = GPIO_ALT | GPIO_UP;
|
||||||
// CNVI_DET#_EC
|
// CNVI_DET#_EC
|
||||||
GPCRC4 = GPIO_IN | GPIO_UP;
|
GPCRC4 = GPIO_IN | GPIO_UP;
|
||||||
// KB-SO17
|
// KB-SO17
|
||||||
GPCRC5 = GPIO_IN | GPIO_UP;
|
GPCRC5 = GPIO_ALT | GPIO_UP;
|
||||||
// PM_PWROK
|
// PM_PWROK
|
||||||
GPCRC6 = GPIO_OUT;
|
GPCRC6 = GPIO_OUT;
|
||||||
// LED_ACIN
|
// LED_ACIN
|
||||||
@@ -188,8 +192,6 @@ void gpio_init() {
|
|||||||
GPCRH5 = GPIO_OUT | GPIO_UP;
|
GPCRH5 = GPIO_OUT | GPIO_UP;
|
||||||
// SUSB#_PCH
|
// SUSB#_PCH
|
||||||
GPCRH6 = GPIO_IN;
|
GPCRH6 = GPIO_IN;
|
||||||
// TODO
|
|
||||||
GPCRH7 = GPIO_IN;
|
|
||||||
// BAT_DET
|
// BAT_DET
|
||||||
GPCRI0 = GPIO_ALT;
|
GPCRI0 = GPIO_ALT;
|
||||||
// BAT_VOLT
|
// BAT_VOLT
|
||||||
@@ -237,40 +239,3 @@ void gpio_init() {
|
|||||||
// SERIRQ
|
// SERIRQ
|
||||||
GPCRM6 = GPIO_ALT;
|
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
|
|
||||||
|
@@ -5,14 +5,7 @@
|
|||||||
|
|
||||||
#include <ec/gpio.h>
|
#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_init(void);
|
||||||
void gpio_debug(void);
|
|
||||||
|
|
||||||
extern struct Gpio __code ACIN_N;
|
extern struct Gpio __code ACIN_N;
|
||||||
extern struct Gpio __code AC_PRESENT;
|
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_PWR;
|
||||||
extern struct Gpio __code LED_SCROLL_N;
|
extern struct Gpio __code LED_SCROLL_N;
|
||||||
extern struct Gpio __code LID_SW_N;
|
extern struct Gpio __code LID_SW_N;
|
||||||
|
extern struct Gpio __code ME_WE;
|
||||||
#define HAVE_PCH_DPWROK_EC 0
|
#define HAVE_PCH_DPWROK_EC 0
|
||||||
#define HAVE_PCH_PWROK_EC 0
|
#define HAVE_PCH_PWROK_EC 0
|
||||||
extern struct Gpio __code PM_CLKRUN_N;
|
extern struct Gpio __code PM_CLKRUN_N;
|
||||||
extern struct Gpio __code PM_PWROK;
|
extern struct Gpio __code PM_PWROK;
|
||||||
extern struct Gpio __code PWR_BTN_N;
|
extern struct Gpio __code PWR_BTN_N;
|
||||||
extern struct Gpio __code PWR_SW_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 SB_KBCRST_N;
|
||||||
extern struct Gpio __code SCI_N;
|
extern struct Gpio __code SCI_N;
|
||||||
#define HAVE_SLP_SUS_N 0
|
#define HAVE_SLP_SUS_N 0
|
||||||
|
@@ -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);
|
|
||||||
}
|
|
@@ -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
|
|
||||||
)
|
|
||||||
};
|
|
@@ -1,15 +1,11 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <arch/time.h>
|
|
||||||
#include <board/battery.h>
|
|
||||||
#include <board/board.h>
|
#include <board/board.h>
|
||||||
#include <board/dgpu.h>
|
|
||||||
#include <board/gctrl.h>
|
#include <board/gctrl.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbc.h>
|
#include <board/kbc.h>
|
||||||
#include <board/peci.h>
|
|
||||||
#include <board/power.h>
|
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
#include <ec/ec.h>
|
||||||
|
|
||||||
extern uint8_t main_cycle;
|
extern uint8_t main_cycle;
|
||||||
|
|
||||||
@@ -18,65 +14,14 @@ void board_init(void) {
|
|||||||
gpio_set(&BKL_EN, true);
|
gpio_set(&BKL_EN, true);
|
||||||
// Enable camera
|
// Enable camera
|
||||||
gpio_set(&CCD_EN, true);
|
gpio_set(&CCD_EN, true);
|
||||||
// Enable wireless
|
|
||||||
gpio_set(&WLAN_EN, true);
|
|
||||||
gpio_set(&WLAN_PWR_EN, true);
|
|
||||||
// Assert SMI#, SCI#, and SWI#
|
// Assert SMI#, SCI#, and SWI#
|
||||||
gpio_set(&SCI_N, true);
|
gpio_set(&SCI_N, true);
|
||||||
gpio_set(&SMI_N, true);
|
gpio_set(&SMI_N, true);
|
||||||
gpio_set(&SWI_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) {
|
void board_event(void) {
|
||||||
bool ac = !gpio_get(&ACIN_N);
|
ec_read_post_codes();
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (main_cycle == 0) {
|
if (main_cycle == 0) {
|
||||||
// Set keyboard LEDs
|
// Set keyboard LEDs
|
||||||
|
@@ -1,13 +1,21 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
EC=it5570e
|
board-y += board.c
|
||||||
|
board-y += gpio.c
|
||||||
|
|
||||||
# Add keymap to src
|
EC=ite
|
||||||
KEYMAP?=default
|
CONFIG_EC_ITE_IT5570E=y
|
||||||
SRC+=$(BOARD_DIR)/keymap/$(KEYMAP).c
|
CONFIG_EC_FLASH_SIZE_128K = y
|
||||||
|
|
||||||
# Set discrete GPU I2C bus
|
# Intel-based host
|
||||||
CFLAGS+=-DI2C_DGPU=I2C_1
|
CONFIG_PLATFORM_INTEL = y
|
||||||
|
|
||||||
|
# Include keyboard
|
||||||
|
KEYBOARD=15in_102
|
||||||
|
|
||||||
|
# Set keyboard LED mechanism
|
||||||
|
CONFIG_HAVE_KBLED = y
|
||||||
|
KBLED=rgb_pwm
|
||||||
|
|
||||||
# Set battery I2C bus
|
# Set battery I2C bus
|
||||||
CFLAGS+=-DI2C_SMBUS=I2C_4
|
CFLAGS+=-DI2C_SMBUS=I2C_4
|
||||||
@@ -17,41 +25,38 @@ CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
|||||||
|
|
||||||
# Set smart charger parameters
|
# Set smart charger parameters
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
-DCHARGER_ADAPTER_RSENSE=5 \
|
||||||
|
-DCHARGER_BATTERY_RSENSE=10 \
|
||||||
|
-DCHARGER_CHARGE_CURRENT=3072 \
|
||||||
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
||||||
-DCHARGER_INPUT_CURRENT=11800
|
-DCHARGER_INPUT_CURRENT=11800
|
||||||
|
|
||||||
# Set battery charging thresholds
|
|
||||||
CFLAGS+=\
|
|
||||||
-DBATTERY_START_THRESHOLD=0 \
|
|
||||||
-DBATTERY_END_THRESHOLD=100
|
|
||||||
|
|
||||||
# Set CPU power limits in watts
|
# Set CPU power limits in watts
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DPOWER_LIMIT_AC=180 \
|
-DPOWER_LIMIT_AC=180 \
|
||||||
-DPOWER_LIMIT_DC=28
|
-DPOWER_LIMIT_DC=45
|
||||||
|
|
||||||
# Custom fan curve
|
# Enable dGPU support
|
||||||
CFLAGS+=-DBOARD_HEATUP=5
|
CONFIG_HAVE_DGPU = y
|
||||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
CFLAGS += -DI2C_DGPU=I2C_1
|
||||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
|
||||||
|
# Fan configs
|
||||||
|
CFLAGS += -DFAN1_PWM=DCR2
|
||||||
|
CFLAGS += -DBOARD_FAN1_POINTS="\
|
||||||
FAN_POINT(60, 40), \
|
FAN_POINT(60, 40), \
|
||||||
FAN_POINT(65, 60), \
|
FAN_POINT(65, 60), \
|
||||||
FAN_POINT(70, 75), \
|
FAN_POINT(70, 75), \
|
||||||
FAN_POINT(75, 90), \
|
FAN_POINT(75, 90), \
|
||||||
FAN_POINT(80, 100) \
|
FAN_POINT(80, 100), \
|
||||||
"
|
"
|
||||||
|
|
||||||
# Enable DGPU support
|
CFLAGS += -DFAN2_PWM=DCR4
|
||||||
CFLAGS+=-DHAVE_DGPU=1
|
CFLAGS += -DBOARD_FAN2_POINTS="\
|
||||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
|
||||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
|
||||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
|
||||||
FAN_POINT(60, 40), \
|
FAN_POINT(60, 40), \
|
||||||
FAN_POINT(65, 60), \
|
FAN_POINT(65, 60), \
|
||||||
FAN_POINT(70, 75), \
|
FAN_POINT(70, 75), \
|
||||||
FAN_POINT(75, 90), \
|
FAN_POINT(75, 90), \
|
||||||
FAN_POINT(80, 100) \
|
FAN_POINT(80, 100), \
|
||||||
"
|
"
|
||||||
|
|
||||||
# Add system76 common code
|
# Add system76 common code
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <board/gpio.h>
|
#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 ACIN_N = GPIO(B, 0);
|
||||||
struct Gpio __code AC_PRESENT = GPIO(E, 1);
|
struct Gpio __code AC_PRESENT = GPIO(E, 1);
|
||||||
struct Gpio __code ALL_SYS_PWRGD = GPIO(C, 0);
|
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_PWR = GPIO(D, 0);
|
||||||
struct Gpio __code LED_SCROLL_N = GPIO(J, 3);
|
struct Gpio __code LED_SCROLL_N = GPIO(J, 3);
|
||||||
struct Gpio __code LID_SW_N = GPIO(B, 1);
|
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_CLKRUN_N = GPIO(H, 0); // renamed to ECCLKRUN#
|
||||||
struct Gpio __code PM_PWROK = GPIO(C, 6);
|
struct Gpio __code PM_PWROK = GPIO(C, 6);
|
||||||
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
|
struct Gpio __code PWR_BTN_N = GPIO(D, 5);
|
||||||
struct Gpio __code PWR_SW_N = GPIO(B, 3);
|
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 SCI_N = GPIO(D, 3);
|
||||||
struct Gpio __code SMI_N = GPIO(D, 4);
|
struct Gpio __code SMI_N = GPIO(D, 4);
|
||||||
struct Gpio __code SUSB_N_PCH = GPIO(H, 6);
|
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_EN = GPIO(G, 1);
|
||||||
struct Gpio __code WLAN_PWR_EN = GPIO(J, 7);
|
struct Gpio __code WLAN_PWR_EN = GPIO(J, 7);
|
||||||
struct Gpio __code XLP_OUT = GPIO(B, 4);
|
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
|
// Enable LPC reset on GPD2
|
||||||
GCR = 0x04;
|
GCR = 0x04;
|
||||||
// Enable SMBus channel 4
|
// Enable SMBus channel 4
|
||||||
GCR15 = (1 << 4);
|
GCR15 = BIT(4);
|
||||||
// Set GPF2 and GPF3 to 3.3V
|
// Set GPF2 and GPF3 to 3.3V
|
||||||
GCR20 = 0;
|
GCR20 = 0;
|
||||||
|
|
||||||
// Set GPIO data
|
// Set GPIO data
|
||||||
GPDRA = 0x00;
|
GPDRA = 0x00;
|
||||||
// XLP_OUT, PWR_SW#
|
// XLP_OUT, PWR_SW#
|
||||||
GPDRB = (1 << 4) | (1 << 3);
|
GPDRB = BIT(4) | BIT(3);
|
||||||
GPDRC = 0x00;
|
GPDRC = 0x00;
|
||||||
// PWR_BTN#, SCI#, SMI#
|
// PWR_BTN#, SCI#, SMI#
|
||||||
GPDRD = (1 << 5) | (1 << 4) | (1 << 3);
|
GPDRD = BIT(5) | BIT(4) | BIT(3);
|
||||||
// PLVDD_RST_EC
|
// PLVDD_RST_EC
|
||||||
GPDRE = (1 << 6);
|
GPDRE = BIT(6);
|
||||||
// EC_PECI
|
// EC_PECI
|
||||||
GPDRF = (1 << 6);
|
GPDRF = BIT(6);
|
||||||
// H_PROCHOT#_EC, LED_NUM#
|
// H_PROCHOT#_EC, LED_NUM#
|
||||||
GPDRG = (1 << 6) | (1 << 0);
|
GPDRG = BIT(6) | BIT(0);
|
||||||
// AIRPLAN_LED#
|
// AIRPLAN_LED#
|
||||||
GPDRH = 0x80; // (1 << 7)
|
GPDRH = BIT(7);
|
||||||
GPDRI = 0x00;
|
GPDRI = 0x00;
|
||||||
// LED_SCROLL#, LED_CAP#
|
// LED_SCROLL#, LED_CAP#
|
||||||
GPDRJ = (1 << 3) | (1 << 2);
|
GPDRJ = BIT(3) | BIT(2);
|
||||||
|
|
||||||
// Set GPIO control
|
// Set GPIO control
|
||||||
// EC_PWM_LEDKB_P
|
// EC_PWM_LEDKB_P
|
||||||
@@ -96,8 +105,6 @@ void gpio_init() {
|
|||||||
GPCRB5 = GPIO_OUT | GPIO_UP;
|
GPCRB5 = GPIO_OUT | GPIO_UP;
|
||||||
// SUSBC_EN
|
// SUSBC_EN
|
||||||
GPCRB6 = GPIO_OUT | GPIO_UP;
|
GPCRB6 = GPIO_OUT | GPIO_UP;
|
||||||
//
|
|
||||||
GPCRB7 = GPIO_IN;
|
|
||||||
// ALL_SYS_PWRGD
|
// ALL_SYS_PWRGD
|
||||||
GPCRC0 = GPIO_IN;
|
GPCRC0 = GPIO_IN;
|
||||||
// SMC_VGA_THERM
|
// SMC_VGA_THERM
|
||||||
@@ -105,11 +112,11 @@ void gpio_init() {
|
|||||||
// SMD_VGA_THERM
|
// SMD_VGA_THERM
|
||||||
GPCRC2 = GPIO_ALT;
|
GPCRC2 = GPIO_ALT;
|
||||||
// KB-SO16
|
// KB-SO16
|
||||||
GPCRC3 = GPIO_IN;
|
GPCRC3 = GPIO_ALT | GPIO_UP;
|
||||||
// CNVI_DET#_EC
|
// CNVI_DET#_EC
|
||||||
GPCRC4 = GPIO_IN | GPIO_UP;
|
GPCRC4 = GPIO_IN | GPIO_UP;
|
||||||
// KB-SO17
|
// KB-SO17
|
||||||
GPCRC5 = GPIO_IN;
|
GPCRC5 = GPIO_ALT | GPIO_UP;
|
||||||
// PM_PWROK
|
// PM_PWROK
|
||||||
GPCRC6 = GPIO_OUT;
|
GPCRC6 = GPIO_OUT;
|
||||||
// LED_ACIN
|
// LED_ACIN
|
||||||
@@ -241,40 +248,3 @@ void gpio_init() {
|
|||||||
// SERIRQ
|
// SERIRQ
|
||||||
GPCRM6 = GPIO_ALT;
|
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
|
|
||||||
|
@@ -5,19 +5,13 @@
|
|||||||
|
|
||||||
#include <ec/gpio.h>
|
#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_init(void);
|
||||||
void gpio_debug(void);
|
|
||||||
|
|
||||||
extern struct Gpio __code ACIN_N;
|
extern struct Gpio __code ACIN_N;
|
||||||
extern struct Gpio __code AC_PRESENT;
|
extern struct Gpio __code AC_PRESENT;
|
||||||
extern struct Gpio __code ALL_SYS_PWRGD;
|
extern struct Gpio __code ALL_SYS_PWRGD;
|
||||||
extern struct Gpio __code BKL_EN;
|
extern struct Gpio __code BKL_EN;
|
||||||
|
#define HAVE_BT_EN 0
|
||||||
extern struct Gpio __code BUF_PLT_RST_N;
|
extern struct Gpio __code BUF_PLT_RST_N;
|
||||||
extern struct Gpio __code CCD_EN;
|
extern struct Gpio __code CCD_EN;
|
||||||
extern struct Gpio __code DD_ON;
|
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_PWR;
|
||||||
extern struct Gpio __code LED_SCROLL_N;
|
extern struct Gpio __code LED_SCROLL_N;
|
||||||
extern struct Gpio __code LID_SW_N;
|
extern struct Gpio __code LID_SW_N;
|
||||||
|
extern struct Gpio __code ME_WE;
|
||||||
#define HAVE_PCH_DPWROK_EC 0
|
#define HAVE_PCH_DPWROK_EC 0
|
||||||
#define HAVE_PCH_PWROK_EC 0
|
#define HAVE_PCH_PWROK_EC 0
|
||||||
extern struct Gpio __code PM_CLKRUN_N; // renamed to ECCLKRUN#
|
extern struct Gpio __code PM_CLKRUN_N; // renamed to ECCLKRUN#
|
||||||
extern struct Gpio __code PM_PWROK;
|
extern struct Gpio __code PM_PWROK;
|
||||||
extern struct Gpio __code PWR_BTN_N;
|
extern struct Gpio __code PWR_BTN_N;
|
||||||
extern struct Gpio __code PWR_SW_N;
|
extern struct Gpio __code PWR_SW_N;
|
||||||
|
extern struct Gpio __code RGBKB_DET_N;
|
||||||
extern struct Gpio __code SCI_N;
|
extern struct Gpio __code SCI_N;
|
||||||
#define HAVE_SLP_SUS_N 0
|
#define HAVE_SLP_SUS_N 0
|
||||||
extern struct Gpio __code SMI_N;
|
extern struct Gpio __code SMI_N;
|
||||||
|
@@ -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);
|
|
||||||
}
|
|
27
src/board/system76/addw3/board.c
Normal file
27
src/board/system76/addw3/board.c
Normal 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();
|
||||||
|
}
|
74
src/board/system76/addw3/board.mk
Normal file
74
src/board/system76/addw3/board.mk
Normal 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
|
272
src/board/system76/addw3/gpio.c
Normal file
272
src/board/system76/addw3/gpio.c
Normal 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;
|
||||||
|
}
|
43
src/board/system76/addw3/include/board/gpio.h
Normal file
43
src/board/system76/addw3/include/board/gpio.h
Normal 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
|
27
src/board/system76/addw4/board.c
Normal file
27
src/board/system76/addw4/board.c
Normal 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();
|
||||||
|
}
|
74
src/board/system76/addw4/board.mk
Normal file
74
src/board/system76/addw4/board.mk
Normal 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
|
259
src/board/system76/addw4/gpio.c
Normal file
259
src/board/system76/addw4/gpio.c
Normal 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;
|
||||||
|
}
|
43
src/board/system76/addw4/include/board/gpio.h
Normal file
43
src/board/system76/addw4/include/board/gpio.h
Normal 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
|
@@ -1,17 +1,10 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <arch/time.h>
|
|
||||||
#include <board/battery.h>
|
|
||||||
#include <board/board.h>
|
#include <board/board.h>
|
||||||
#include <board/dgpu.h>
|
|
||||||
#include <board/gctrl.h>
|
#include <board/gctrl.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbc.h>
|
|
||||||
#include <board/peci.h>
|
|
||||||
#include <board/power.h>
|
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
#include <ec/ec.h>
|
||||||
extern uint8_t main_cycle;
|
|
||||||
|
|
||||||
void board_init(void) {
|
void board_init(void) {
|
||||||
// Allow CPU to boot
|
// Allow CPU to boot
|
||||||
@@ -20,66 +13,14 @@ void board_init(void) {
|
|||||||
gpio_set(&BKL_EN, true);
|
gpio_set(&BKL_EN, true);
|
||||||
// Enable camera
|
// Enable camera
|
||||||
gpio_set(&CCD_EN, true);
|
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?
|
// Enable USB port power?
|
||||||
gpio_set(&USB_PWR_EN_N, false);
|
gpio_set(&USB_PWR_EN_N, false);
|
||||||
// Assert SMI#, SCI#, and SWI#
|
// Assert SMI#, SCI#, and SWI#
|
||||||
gpio_set(&SCI_N, true);
|
gpio_set(&SCI_N, true);
|
||||||
gpio_set(&SMI_N, true);
|
gpio_set(&SMI_N, true);
|
||||||
gpio_set(&SWI_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) {
|
void board_event(void) {
|
||||||
bool ac = !gpio_get(&ACIN_N);
|
ec_read_post_codes();
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,21 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
EC=it5570e
|
board-y += board.c
|
||||||
|
board-y += gpio.c
|
||||||
|
|
||||||
# Add keymap to src
|
EC=ite
|
||||||
KEYMAP?=default
|
CONFIG_EC_ITE_IT5570E=y
|
||||||
SRC+=$(BOARD_DIR)/keymap/$(KEYMAP).c
|
CONFIG_EC_FLASH_SIZE_128K = y
|
||||||
|
|
||||||
# Set discrete GPU I2C bus
|
# Intel-based host
|
||||||
CFLAGS+=-DI2C_DGPU=I2C_1
|
CONFIG_PLATFORM_INTEL = y
|
||||||
|
|
||||||
|
# Include keyboard
|
||||||
|
KEYBOARD=15in_102_nkey
|
||||||
|
|
||||||
|
# Set keyboard LED mechanism
|
||||||
|
CONFIG_HAVE_KBLED = y
|
||||||
|
KBLED=bonw14
|
||||||
|
|
||||||
# Set battery I2C bus
|
# Set battery I2C bus
|
||||||
CFLAGS+=-DI2C_SMBUS=I2C_4
|
CFLAGS+=-DI2C_SMBUS=I2C_4
|
||||||
@@ -17,41 +25,38 @@ CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
|||||||
|
|
||||||
# Set smart charger parameters
|
# Set smart charger parameters
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
-DCHARGER_ADAPTER_RSENSE=5 \
|
||||||
|
-DCHARGER_BATTERY_RSENSE=10 \
|
||||||
|
-DCHARGER_CHARGE_CURRENT=3072 \
|
||||||
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
||||||
-DCHARGER_INPUT_CURRENT=14000
|
-DCHARGER_INPUT_CURRENT=14000
|
||||||
|
|
||||||
# Set battery charging thresholds
|
|
||||||
CFLAGS+=\
|
|
||||||
-DBATTERY_START_THRESHOLD=0 \
|
|
||||||
-DBATTERY_END_THRESHOLD=100
|
|
||||||
|
|
||||||
# Set CPU power limits in watts
|
# Set CPU power limits in watts
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DPOWER_LIMIT_AC=180 \
|
-DPOWER_LIMIT_AC=180 \
|
||||||
-DPOWER_LIMIT_DC=28
|
-DPOWER_LIMIT_DC=45
|
||||||
|
|
||||||
# Custom fan curve
|
# Enable dGPU support
|
||||||
CFLAGS+=-DBOARD_HEATUP=5
|
CONFIG_HAVE_DGPU = y
|
||||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
CFLAGS += -DI2C_DGPU=I2C_1
|
||||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
|
||||||
|
# Fan configs
|
||||||
|
CFLAGS += -DFAN1_PWM=DCR2
|
||||||
|
CFLAGS += -DBOARD_FAN1_POINTS="\
|
||||||
FAN_POINT(60, 40), \
|
FAN_POINT(60, 40), \
|
||||||
FAN_POINT(65, 60), \
|
FAN_POINT(65, 60), \
|
||||||
FAN_POINT(70, 75), \
|
FAN_POINT(70, 75), \
|
||||||
FAN_POINT(75, 90), \
|
FAN_POINT(75, 90), \
|
||||||
FAN_POINT(80, 100) \
|
FAN_POINT(80, 100), \
|
||||||
"
|
"
|
||||||
|
|
||||||
# Enable DGPU support
|
CFLAGS += -DFAN2_PWM=DCR4
|
||||||
CFLAGS+=-DHAVE_DGPU=1
|
CFLAGS += -DBOARD_FAN2_POINTS="\
|
||||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
|
||||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
|
||||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
|
||||||
FAN_POINT(60, 40), \
|
FAN_POINT(60, 40), \
|
||||||
FAN_POINT(65, 60), \
|
FAN_POINT(65, 60), \
|
||||||
FAN_POINT(70, 75), \
|
FAN_POINT(70, 75), \
|
||||||
FAN_POINT(75, 90), \
|
FAN_POINT(75, 90), \
|
||||||
FAN_POINT(80, 100) \
|
FAN_POINT(80, 100), \
|
||||||
"
|
"
|
||||||
|
|
||||||
# Add system76 common code
|
# Add system76 common code
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <board/gpio.h>
|
#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 ACIN_N = GPIO(B, 0);
|
||||||
struct Gpio __code AC_PRESENT = GPIO(E, 1);
|
struct Gpio __code AC_PRESENT = GPIO(E, 1);
|
||||||
struct Gpio __code AC_V1_EC = GPIO(J, 7);
|
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_EN = GPIO(G, 1);
|
||||||
struct Gpio __code WLAN_PWR_EN = GPIO(A, 3);
|
struct Gpio __code WLAN_PWR_EN = GPIO(A, 3);
|
||||||
struct Gpio __code XLP_OUT = GPIO(B, 4); // renamed to EN_3V
|
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
|
// Enable LPC reset on GPD2
|
||||||
GCR = 0x04;
|
GCR = 0x04;
|
||||||
// Enable SMBus channel 4
|
// Enable SMBus channel 4
|
||||||
GCR15 = (1 << 4);
|
GCR15 = BIT(4);
|
||||||
// Set GPF2 and GPF3 to 3.3V
|
// Set GPF2 and GPF3 to 3.3V
|
||||||
GCR20 = 0;
|
GCR20 = 0;
|
||||||
|
|
||||||
@@ -90,8 +97,6 @@ void gpio_init() {
|
|||||||
GPCRB5 = GPIO_OUT | GPIO_UP;
|
GPCRB5 = GPIO_OUT | GPIO_UP;
|
||||||
// EC_EN
|
// EC_EN
|
||||||
GPCRB6 = GPIO_OUT | GPIO_UP;
|
GPCRB6 = GPIO_OUT | GPIO_UP;
|
||||||
// NO PIN
|
|
||||||
GPCRB7 = GPIO_IN;
|
|
||||||
// ALL_SYS_PWRGD
|
// ALL_SYS_PWRGD
|
||||||
GPCRC0 = GPIO_IN;
|
GPCRC0 = GPIO_IN;
|
||||||
// KBC_SMBus_CLK1
|
// KBC_SMBus_CLK1
|
||||||
@@ -99,11 +104,11 @@ void gpio_init() {
|
|||||||
// KBC_SMBus_DAT1
|
// KBC_SMBus_DAT1
|
||||||
GPCRC2 = GPIO_ALT;
|
GPCRC2 = GPIO_ALT;
|
||||||
// KB-SO16
|
// KB-SO16
|
||||||
GPCRC3 = GPIO_IN;
|
GPCRC3 = GPIO_ALT | GPIO_UP;
|
||||||
// CNVI_DET#
|
// CNVI_DET#
|
||||||
GPCRC4 = GPIO_IN | GPIO_UP;
|
GPCRC4 = GPIO_IN | GPIO_UP;
|
||||||
// KB-SO17
|
// KB-SO17
|
||||||
GPCRC5 = GPIO_IN;
|
GPCRC5 = GPIO_ALT | GPIO_UP;
|
||||||
// PM_PWROK
|
// PM_PWROK
|
||||||
GPCRC6 = GPIO_OUT;
|
GPCRC6 = GPIO_OUT;
|
||||||
// LED_ACIN
|
// LED_ACIN
|
||||||
@@ -235,40 +240,3 @@ void gpio_init() {
|
|||||||
// SERIRQ
|
// SERIRQ
|
||||||
GPCRM6 = GPIO_ALT;
|
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
|
|
||||||
|
@@ -5,14 +5,7 @@
|
|||||||
|
|
||||||
#include <ec/gpio.h>
|
#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_init(void);
|
||||||
void gpio_debug(void);
|
|
||||||
|
|
||||||
extern struct Gpio __code ACIN_N;
|
extern struct Gpio __code ACIN_N;
|
||||||
extern struct Gpio __code AC_PRESENT;
|
extern struct Gpio __code AC_PRESENT;
|
||||||
|
81
src/board/system76/bonw15-b/board.mk
Normal file
81
src/board/system76/bonw15-b/board.mk
Normal 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
|
25
src/board/system76/bonw15/board.c
Normal file
25
src/board/system76/bonw15/board.c
Normal 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();
|
||||||
|
}
|
79
src/board/system76/bonw15/board.mk
Normal file
79
src/board/system76/bonw15/board.mk
Normal 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
|
275
src/board/system76/bonw15/gpio.c
Normal file
275
src/board/system76/bonw15/gpio.c
Normal 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;
|
||||||
|
}
|
46
src/board/system76/bonw15/include/board/gpio.h
Normal file
46
src/board/system76/bonw15/include/board/gpio.h
Normal 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
|
@@ -3,12 +3,17 @@
|
|||||||
#include <board/acpi.h>
|
#include <board/acpi.h>
|
||||||
#include <board/battery.h>
|
#include <board/battery.h>
|
||||||
#include <board/dgpu.h>
|
#include <board/dgpu.h>
|
||||||
|
#include <board/fan.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbled.h>
|
#include <board/kbled.h>
|
||||||
#include <board/lid.h>
|
#include <board/lid.h>
|
||||||
#include <board/peci.h>
|
#include <board/pwm.h>
|
||||||
#include <common/debug.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
|
#ifndef HAVE_LED_AIRPLANE_N
|
||||||
#define HAVE_LED_AIRPLANE_N 1
|
#define HAVE_LED_AIRPLANE_N 1
|
||||||
@@ -24,31 +29,48 @@ static uint8_t fbuf[4] = { 0, 0, 0, 0 };
|
|||||||
|
|
||||||
void fcommand(void) {
|
void fcommand(void) {
|
||||||
switch (fcmd) {
|
switch (fcmd) {
|
||||||
// Keyboard backlight
|
#if CONFIG_HAVE_KBLED
|
||||||
case 0xCA:
|
// Keyboard backlight
|
||||||
switch (fdat) {
|
case 0xCA:
|
||||||
// Set white LED brightness
|
switch (fdat) {
|
||||||
case 0x00:
|
// Set brightness
|
||||||
kbled_set(fbuf[0]);
|
case 0:
|
||||||
break;
|
kbled_set(fbuf[0]);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
break;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uncrustify:off
|
||||||
uint8_t acpi_read(uint8_t addr) {
|
uint8_t acpi_read(uint8_t addr) {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
|
|
||||||
@@ -86,47 +109,53 @@ uint8_t acpi_read(uint8_t addr) {
|
|||||||
case 0x03:
|
case 0x03:
|
||||||
if (gpio_get(&LID_SW_N)) {
|
if (gpio_get(&LID_SW_N)) {
|
||||||
// Lid is open
|
// Lid is open
|
||||||
data |= 1 << 0;
|
data |= BIT(0);
|
||||||
}
|
}
|
||||||
if (lid_wake) {
|
if (lid_wake) {
|
||||||
data |= 1 << 2;
|
data |= BIT(2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ACPI_8(0x07, peci_temp >> 6);
|
#if CONFIG_PLATFORM_INTEL
|
||||||
|
ACPI_8(0x07, peci_temp);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Handle AC adapter and battery present
|
// Handle AC adapter and battery present
|
||||||
case 0x10:
|
case 0x10:
|
||||||
if (!gpio_get(&ACIN_N)) {
|
if (!gpio_get(&ACIN_N)) {
|
||||||
// AC adapter connected
|
// AC adapter connected
|
||||||
data |= 1 << 0;
|
data |= BIT(0);
|
||||||
}
|
}
|
||||||
if (battery_status & BATTERY_INITIALIZED) {
|
if (battery_info.status & BATTERY_INITIALIZED) {
|
||||||
// BAT0 connected
|
// BAT0 connected
|
||||||
data |= 1 << 2;
|
data |= BIT(2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ACPI_16(0x16, battery_design_capacity);
|
ACPI_16(0x16, battery_info.design_capacity);
|
||||||
ACPI_16(0x1A, battery_full_capacity);
|
ACPI_16(0x1A, battery_info.full_capacity);
|
||||||
ACPI_16(0x22, battery_design_voltage);
|
ACPI_16(0x22, battery_info.design_voltage);
|
||||||
|
|
||||||
case 0x26:
|
case 0x26:
|
||||||
// If AC adapter connected
|
// If AC adapter connected
|
||||||
if (!gpio_get(&ACIN_N)) {
|
if (!gpio_get(&ACIN_N)) {
|
||||||
// And battery is not fully charged
|
// And battery is not fully charged
|
||||||
if (battery_current != 0) {
|
if (battery_info.current != 0) {
|
||||||
// Battery is charging
|
// Battery is charging
|
||||||
data |= 1 << 1;
|
data |= BIT(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ACPI_16(0x2A, battery_current);
|
ACPI_16(0x2A, battery_info.current);
|
||||||
ACPI_16(0x2E, battery_remaining_capacity);
|
ACPI_16(0x2E, battery_info.remaining_capacity);
|
||||||
ACPI_16(0x32, battery_voltage);
|
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:
|
case 0xBC:
|
||||||
data = battery_get_start_threshold();
|
data = battery_get_start_threshold();
|
||||||
@@ -138,86 +167,87 @@ uint8_t acpi_read(uint8_t addr) {
|
|||||||
|
|
||||||
ACPI_8(0xCC, sci_extra);
|
ACPI_8(0xCC, sci_extra);
|
||||||
|
|
||||||
ACPI_8(0xCE, DCR2);
|
ACPI_8(0xCE, fan1_pwm_actual);
|
||||||
ACPI_8(0xD0, F1TLRR);
|
ACPI_16(0xD0, fan1_rpm);
|
||||||
ACPI_8(0xD1, F1TMRR);
|
#if CONFIG_HAVE_DGPU
|
||||||
#if HAVE_DGPU
|
|
||||||
ACPI_8(0xCD, dgpu_temp);
|
ACPI_8(0xCD, dgpu_temp);
|
||||||
ACPI_8(0xCF, DCR4);
|
#endif // CONFIG_HAVE_DGPU
|
||||||
ACPI_8(0xD2, F2TLRR);
|
#ifdef FAN2_PWM
|
||||||
ACPI_8(0xD3, F2TMRR);
|
ACPI_8(0xCF, fan2_pwm_actual);
|
||||||
#endif // HAVE_DGPU
|
ACPI_16(0xD2, fan2_rpm);
|
||||||
|
#endif // FAN2_PWM
|
||||||
|
|
||||||
#if HAVE_LED_AIRPLANE_N
|
#if HAVE_LED_AIRPLANE_N
|
||||||
// Airplane mode LED
|
// Airplane mode LED
|
||||||
case 0xD9:
|
case 0xD9:
|
||||||
if (!gpio_get(&LED_AIRPLANE_N)) {
|
if (!gpio_get(&LED_AIRPLANE_N)) {
|
||||||
data |= (1 << 6);
|
data |= BIT(6);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif // HAVE_LED_AIRPLANE_N
|
#endif // HAVE_LED_AIRPLANE_N
|
||||||
|
|
||||||
// Set size of flash (from old firmware)
|
// Set size of flash (from old firmware)
|
||||||
ACPI_8 (0xE5, 0x80);
|
ACPI_8(0xE5, 0x80);
|
||||||
|
|
||||||
ACPI_8 (0xF8, fcmd);
|
ACPI_8(0xF8, fcmd);
|
||||||
ACPI_8 (0xF9, fdat);
|
ACPI_8(0xF9, fdat);
|
||||||
ACPI_8 (0xFA, fbuf[0]);
|
ACPI_8(0xFA, fbuf[0]);
|
||||||
ACPI_8 (0xFB, fbuf[1]);
|
ACPI_8(0xFB, fbuf[1]);
|
||||||
ACPI_8 (0xFC, fbuf[2]);
|
ACPI_8(0xFC, fbuf[2]);
|
||||||
ACPI_8 (0xFD, fbuf[3]);
|
ACPI_8(0xFD, fbuf[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("acpi_read %02X = %02X\n", addr, data);
|
TRACE("acpi_read %02X = %02X\n", addr, data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
// uncrustify:on
|
||||||
|
|
||||||
void acpi_write(uint8_t addr, uint8_t data) {
|
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) {
|
switch (addr) {
|
||||||
// Lid state and other flags
|
// Lid state and other flags
|
||||||
case 0x03:
|
case 0x03:
|
||||||
lid_wake = (bool)(data & (1 << 2));
|
lid_wake = (bool)(data & BIT(2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x68:
|
case 0x68:
|
||||||
acpi_ecos = (enum EcOs)data;
|
acpi_ecos = (enum EcOs)data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xBC:
|
case 0xBC:
|
||||||
battery_set_start_threshold(data);
|
battery_set_start_threshold(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xBD:
|
case 0xBD:
|
||||||
battery_set_end_threshold(data);
|
battery_set_end_threshold(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if HAVE_LED_AIRPLANE_N
|
#if HAVE_LED_AIRPLANE_N
|
||||||
// Airplane mode LED
|
// Airplane mode LED
|
||||||
case 0xD9:
|
case 0xD9:
|
||||||
gpio_set(&LED_AIRPLANE_N, !(bool)(data & (1 << 6)));
|
gpio_set(&LED_AIRPLANE_N, !(bool)(data & BIT(6)));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 0xF8:
|
case 0xF8:
|
||||||
fcmd = data;
|
fcmd = data;
|
||||||
fcommand();
|
fcommand();
|
||||||
break;
|
break;
|
||||||
case 0xF9:
|
case 0xF9:
|
||||||
fdat = data;
|
fdat = data;
|
||||||
break;
|
break;
|
||||||
case 0xFA:
|
case 0xFA:
|
||||||
fbuf[0] = data;
|
fbuf[0] = data;
|
||||||
break;
|
break;
|
||||||
case 0xFB:
|
case 0xFB:
|
||||||
fbuf[1] = data;
|
fbuf[1] = data;
|
||||||
break;
|
break;
|
||||||
case 0xFC:
|
case 0xFC:
|
||||||
fbuf[2] = data;
|
fbuf[2] = data;
|
||||||
break;
|
break;
|
||||||
case 0xFD:
|
case 0xFD:
|
||||||
fbuf[3] = data;
|
fbuf[3] = data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,25 +1,17 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <board/battery.h>
|
#include <board/battery.h>
|
||||||
|
#include <board/gpio.h>
|
||||||
#include <board/smbus.h>
|
#include <board/smbus.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
|
||||||
#define BATTERY_ADDRESS 0x0B
|
struct battery_info battery_info = { 0 };
|
||||||
#define CHARGER_ADDRESS 0x09
|
|
||||||
|
|
||||||
// ChargeOption0 flags
|
uint16_t battery_charger_input_current = CHARGER_INPUT_CURRENT;
|
||||||
// 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))
|
|
||||||
|
|
||||||
// Default values to disable battery charging thresholds
|
// Default values to disable battery charging thresholds
|
||||||
#define BATTERY_START_DEFAULT 0
|
#define BATTERY_START_DEFAULT 0
|
||||||
#define BATTERY_END_DEFAULT 100
|
#define BATTERY_END_DEFAULT 100
|
||||||
|
|
||||||
// Represents a battery percentage level, below which charging will begin.
|
// Represents a battery percentage level, below which charging will begin.
|
||||||
// Valid values are [0, 100]
|
// Valid values are [0, 100]
|
||||||
@@ -59,94 +51,25 @@ bool battery_set_end_threshold(uint8_t value) {
|
|||||||
return true;
|
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.
|
* Configure the charger based on charging threshold values.
|
||||||
*/
|
*/
|
||||||
int battery_charger_configure(void) {
|
int16_t battery_charger_configure(void) {
|
||||||
static bool should_charge = true;
|
static bool should_charge = true;
|
||||||
|
bool ac_present = !gpio_get(&ACIN_N);
|
||||||
|
|
||||||
if (battery_get_end_threshold() == BATTERY_END_DEFAULT) {
|
if (!ac_present || (battery_info.status & BATTERY_FULLY_CHARGED)) {
|
||||||
// Stop threshold not configured: Always charge on AC.
|
// Always disable charger if:
|
||||||
should_charge = true;
|
// - AC is not plugged in, or
|
||||||
}
|
// - Battery is fully charged
|
||||||
else if (battery_charge >= battery_get_end_threshold()) {
|
should_charge = false;
|
||||||
|
} else if (battery_info.charge > battery_get_end_threshold()) {
|
||||||
// Stop threshold configured: Stop charging at threshold.
|
// Stop threshold configured: Stop charging at threshold.
|
||||||
should_charge = false;
|
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.
|
// Start threshold not configured: Always charge up to stop threshold.
|
||||||
should_charge = true;
|
should_charge = true;
|
||||||
}
|
} else if (battery_info.charge < battery_get_start_threshold()) {
|
||||||
else if (battery_charge <= battery_get_start_threshold()) {
|
|
||||||
// Start threshold configured: Start charging at threshold.
|
// Start threshold configured: Start charging at threshold.
|
||||||
should_charge = true;
|
should_charge = true;
|
||||||
}
|
}
|
||||||
@@ -156,74 +79,33 @@ int battery_charger_configure(void) {
|
|||||||
return battery_charger_disable();
|
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) {
|
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); \
|
res = smbus_read(BATTERY_ADDRESS, V, &N); \
|
||||||
if (res < 0) { \
|
if (res < 0) { \
|
||||||
N = 0; \
|
N = 0; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
command(battery_temp, 0x08);
|
command(battery_info.temp, 0x08);
|
||||||
command(battery_voltage, 0x09);
|
command(battery_info.voltage, 0x09);
|
||||||
command(battery_current, 0x0A);
|
command(battery_info.current, 0x0A);
|
||||||
command(battery_charge, 0x0D);
|
command(battery_info.charge, 0x0D);
|
||||||
command(battery_remaining_capacity, 0x0F);
|
command(battery_info.remaining_capacity, 0x0F);
|
||||||
command(battery_full_capacity, 0x10);
|
command(battery_info.full_capacity, 0x10);
|
||||||
command(battery_status, 0x16);
|
command(battery_info.status, 0x16);
|
||||||
command(battery_design_capacity, 0x18);
|
command(battery_info.cycle_count, 0x17);
|
||||||
command(battery_design_voltage, 0x19);
|
command(battery_info.design_capacity, 0x18);
|
||||||
|
command(battery_info.design_voltage, 0x19);
|
||||||
|
|
||||||
#undef command
|
#undef command
|
||||||
}
|
|
||||||
|
|
||||||
void battery_debug(void) {
|
TRACE("BAT %d mV %d mA\n", battery_info.voltage, battery_info.current);
|
||||||
uint16_t data = 0;
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
#define command(N, A, V) { \
|
battery_charger_event();
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_reset(void) {
|
void battery_reset(void) {
|
||||||
|
215
src/board/system76/common/charger/bq24780s.c
Normal file
215
src/board/system76/common/charger/bq24780s.c
Normal 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
|
||||||
|
}
|
223
src/board/system76/common/charger/oz26786.c
Normal file
223
src/board/system76/common/charger/oz26786.c
Normal 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
|
||||||
|
}
|
@@ -1,5 +1,30 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-only
|
# 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
|
# Set log level
|
||||||
# 0 - NONE
|
# 0 - NONE
|
||||||
# 1 - ERROR
|
# 1 - ERROR
|
||||||
@@ -15,20 +40,80 @@ CFLAGS+=-DLEVEL=4
|
|||||||
# Uncomment to enable I2C debug on 0x76
|
# Uncomment to enable I2C debug on 0x76
|
||||||
#CFLAGS+=-DI2C_DEBUGGER=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
|
# Set external programmer
|
||||||
PROGRAMMER=$(wildcard /dev/serial/by-id/usb-Arduino*)
|
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
|
# Include system76 common source
|
||||||
SYSTEM76_COMMON_DIR=src/board/system76/common
|
SYSTEM76_COMMON_DIR=src/board/system76/common
|
||||||
SRC+=$(wildcard $(SYSTEM76_COMMON_DIR)/*.c)
|
INCLUDE += $(SYSTEM76_COMMON_DIR)/common.mk
|
||||||
INCLUDE+=$(wildcard $(SYSTEM76_COMMON_DIR)/include/common/*.h) $(SYSTEM76_COMMON_DIR)/common.mk
|
|
||||||
CFLAGS+=-I$(SYSTEM76_COMMON_DIR)/include
|
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
|
# Add scratch ROM
|
||||||
include $(SYSTEM76_COMMON_DIR)/scratch/scratch.mk
|
include $(SYSTEM76_COMMON_DIR)/scratch/scratch.mk
|
||||||
|
|
||||||
# Add scratch ROM for flash access
|
# Add scratch ROM for flash access
|
||||||
include $(SYSTEM76_COMMON_DIR)/flash/flash.mk
|
include $(SYSTEM76_COMMON_DIR)/flash/flash.mk
|
||||||
|
board-common-y += flash/wrapper.c
|
||||||
|
|
||||||
console_internal:
|
console_internal:
|
||||||
cargo build --manifest-path tool/Cargo.toml --release
|
cargo build --manifest-path tool/Cargo.toml --release
|
||||||
@@ -39,6 +124,11 @@ console_external:
|
|||||||
sleep 1 && echo C | sudo tee "$(PROGRAMMER)" &
|
sleep 1 && echo C | sudo tee "$(PROGRAMMER)" &
|
||||||
sudo tio -b 1000000 -m INLCRNL -t "$(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
|
flash_internal: $(BUILD)/ec.rom
|
||||||
cargo build --manifest-path tool/Cargo.toml --release
|
cargo build --manifest-path tool/Cargo.toml --release
|
||||||
sudo tool/target/release/system76_ectool flash $<
|
sudo tool/target/release/system76_ectool flash $<
|
||||||
|
@@ -1,105 +1,43 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <board/dgpu.h>
|
#include <board/dgpu.h>
|
||||||
|
|
||||||
#if HAVE_DGPU
|
|
||||||
|
|
||||||
#include <board/fan.h>
|
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/power.h>
|
#include <board/power.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
#include <common/macro.h>
|
#include <common/macro.h>
|
||||||
#include <ec/i2c.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;
|
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) {
|
void dgpu_init(void) {
|
||||||
// Set up for i2c usage
|
// Set up for i2c usage
|
||||||
i2c_reset(&I2C_DGPU, true);
|
i2c_reset(&I2C_DGPU, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dgpu_event(void) {
|
bool dgpu_get_temp(int16_t *const data) {
|
||||||
uint8_t duty;
|
if (gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) {
|
||||||
if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) {
|
|
||||||
// Use I2CS if in S0 state
|
|
||||||
int8_t rlts;
|
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) {
|
if (res == 1) {
|
||||||
dgpu_temp = (int16_t)rlts;
|
*data = (int16_t)rlts;
|
||||||
duty = fan_duty(&FAN, dgpu_temp);
|
return true;
|
||||||
} else {
|
} else {
|
||||||
DEBUG("DGPU temp error: %d\n", res);
|
DEBUG("DGPU temp error: %d\n", res);
|
||||||
// Default to 50% if there is an error
|
*data = 0;
|
||||||
dgpu_temp = 0;
|
return false;
|
||||||
duty = PWM_DUTY(50);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Turn fan off if not in S0 state or GPU power not on
|
|
||||||
dgpu_temp = 0;
|
|
||||||
duty = PWM_DUTY(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fan_max) {
|
*data = 0;
|
||||||
// Override duty if fans are manually set to maximum
|
return true;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
void dgpu_read_temp(void) {
|
||||||
|
if (power_state == POWER_STATE_S0) {
|
||||||
|
if (dgpu_get_temp(&dgpu_temp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dgpu_init(void) {}
|
dgpu_temp = 0;
|
||||||
|
}
|
||||||
void dgpu_event(void) {}
|
|
||||||
|
|
||||||
#endif // HAVE_DGPU
|
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include <board/ecpm.h>
|
#include <board/ecpm.h>
|
||||||
|
#include <common/macro.h>
|
||||||
|
|
||||||
void ecpm_init(void) {
|
void ecpm_init(void) {
|
||||||
// Clock gate EGPC, CIR, and SWUC
|
// 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
|
// Clock gate UART, SSPI, and DBGR
|
||||||
CGCTRL3 |= (1 << 2) | (1 << 1) | (1 << 0);
|
CGCTRL3 |= BIT(2) | BIT(1) | BIT(0);
|
||||||
// Clock gate CEC
|
// 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
Reference in New Issue
Block a user